Missbrauch von include
1. Ursache der Sicherheitslücke:
Include ist die am häufigsten verwendete Funktion beim Schreiben von PHP-Websites und unterstützt relative Pfade. Es gibt viele PHP-Skripte, die eine Eingabevariable direkt als Include-Parameter verwenden, was zu Schwachstellen wie willkürlichen Skriptverweisen und absoluten Pfadverlusten führt. Schauen Sie sich den folgenden Code an:
...
$includepage=$_GET["includepage"];
include($includepage);
...
Offensichtlich müssen wir nur verschiedene Includepage-Variablen übermitteln, um die gewünschte Seite zu erhalten. Wenn Sie eine Seite übermitteln, die nicht existiert, kann es zu einem Fehler des PHP-Skripts und einem Verlust des tatsächlichen absoluten Pfads kommen (die Lösung für dieses Problem wird im folgenden Artikel erläutert).
2. Behebung der Sicherheitslücke:
Die Lösung für diese Sicherheitslücke ist sehr einfach: Zuerst feststellen, ob die Seite existiert, und sie dann einbinden. Genauer gesagt: Verwenden Sie ein Array, um die Dateien anzugeben, die eingeschlossen werden können. Schauen Sie sich den folgenden Code an:
$pagelist=array("test1.php","test2.php","test3.php"); //Dies gibt Dateien an, die eingebunden werden können
if(isset($_GET["includepage"])) //Bestimmen Sie, ob $includepage vorhanden ist
{
$includepage=$_GET["includepage"];
foreach($pagelist as $prepage)
{
if($includepage==$prepage) //Überprüfen Sie, ob die Datei in der Liste der zulässigen Dateien enthalten ist
{
include($prepage);
$checkfind=true;
brechen;
}
}
if($checkfind==true){ unset($checkfind }
else{ die("Ungültige Referenzseite!" }
}
Dadurch wird das Problem sehr gut gelöst.
Tipp: Zu den Funktionen mit diesem Problem gehören: require(), require_once(), include_once(), readfile() usw. Auch beim Schreiben sollte man aufpassen.
Eingabevariablen werden nicht gefiltert
1. Ursache der Sicherheitslücke:
Diese Sicherheitsanfälligkeit ist in ASP seit langem aufgetreten und hat zu dieser Zeit unzählige Sicherheitslücken bei der Injektion verursacht. Da PHP zu dieser Zeit jedoch nur einen geringen Einfluss hatte, konnten nicht viele Leute darauf achten. Bei PHP sind die Auswirkungen dieser Schwachstelle größer als bei ASP, da mehr PHP-Skripte Textdatenbanken verwenden. Natürlich gibt es auch das Problem der SQL-Anweisungsinjektion. Um ein klassischeres Beispiel zu nennen: Das erste ist die Datenbank:
$id=$_GET["id"];
$query="SELECT * FROM my_table where id='".$id."'" //Eine sehr klassische SQL-Injection-Schwachstelle
$result=mysql_query($query);
Es ist hier offensichtlich, dass wir die Injektion verwenden können, um andere Inhalte der Datenbank zu erhalten. Ich werde es hier nicht im Detail beschreiben. Genau wie bei der ASP-Injektion können Sie einen Blick auf frühere schwarze Verteidigungen werfen. Dann schauen wir uns das Problem von Textdatenbanken an:
$text1=$_POST["text1"];
$text2=$_POST["text2"];
$text3=$_POST["text3"];
$fd=fopen("test.php","a");
fwrite($fd,"rn$text1&line;$text2&line;$text3");
fclose($fd);
Die Verletzlichkeit des Textes ist wohl noch gravierender. Wenn wir einen kleinen PHP-Code in die übermittelte Variable einfügen, können wir diese Textdatenbank test.php in eine PHP-Hintertür verwandeln. Schon durch das Einfügen des Upload-Codes können wir eine komplette PHP-Hintertür hochladen. Erhöhen Sie dann die Berechtigungen und der Server gehört Ihnen.
2. Behebung der Sicherheitslücke:
Die Lösung für diese Sicherheitsanfälligkeit ist eigentlich sehr einfach: Alle übermittelten Variablen werden strikt gefiltert. Ersetzen Sie einige sensible Zeichen. Mit Hilfe der von PHP bereitgestellten Funktion htmlspecialchars() können wir den Inhalt von HTML ersetzen. Hier ist ein Beispiel:
//Filterfunktion erstellen www.knowsky.com
Funktion flt_tags($text)
{
$badwords=array("Fuck you","fuck"); //Wortfilterliste
$text=rtrim($text);
foreach($badwords as $badword) //Vokabular hier filtern
{
if(stristr($text,$badword)==true){ die("Fehler: Der von Ihnen übermittelte Inhalt enthält sensible Wörter, bitte übermitteln Sie keine sensiblen Inhalte." }
}
$text=htmlspecialchars($text); //HTML-Ersatz
//Diese beiden Zeilen ersetzen den Wagenrücklauf durch
$text=str_replace("r","
",$text);
$text=str_replace("n","",$text);
$text=str_replace("&line;","│",$text); //Ersetzen Sie das Textdatenbanktrennzeichen „&line;“ mit voller Breite.
$text=preg_replace("/s{ 2 }/"," ",$text);
$text=preg_replace("/t/"," ",$text); // Ersetzt weiterhin Leerzeichen
if(get_magic_quotes_gpc()){ $text=stripslashes($text); //Wenn magic_quotes aktiviert ist, ersetzen Sie '
return $text;
}
$text1=$_POST["text1"];
$text2=$_POST["text2"];
$text3=$_POST["text3"];
//Alle Eingaben filtern
$text1=flt_tags($text1);
$text2=flt_tags($text2);
$text3=flt_tags($text3);
$fd=fopen("test.php","a");
fwrite($fd,"rn$text1&line;$text2&line;$text3");
fclose($fd);
Nach einigem Ersetzen und Filtern können Sie die Daten sicher in Text oder eine Datenbank schreiben.
Das Urteil des Verwalters ist unvollständig
1. Ursache der Sicherheitslücke:
Wir verwenden PHP zum Schreiben von Skripten, die in der Regel Administratorrechte erfordern. Einige Skripte urteilen nur mit „Ja“ über Administratorberechtigungen, ignorieren jedoch häufig das Urteil „Nein“. Wenn register_globals in der PHP-Konfigurationsdatei aktiviert ist (in Versionen nach 4.2.0 ist es standardmäßig deaktiviert, aber viele Leute aktivieren es aus Bequemlichkeitsgründen, was ein äußerst gefährliches Verhalten darstellt), kann es Situationen geben, in denen Variablen zum Identitätswechsel übermittelt werden Administratoren. Schauen wir uns den Beispielcode an:
$cookiesign="admincookiesign"; //Bestimmen Sie, ob die Cookie-Variable des Administrators ist
$adminsign=$_COOKIE["sign"]; //Cookie-Variable des Benutzers abrufen
if($adminsign==$cookiesign)
{
$admin=true;
}
if($admin){ echo „Sie sind jetzt Administrator.“ }
Es sieht sehr sicher aus, haha. Nun gehen wir davon aus, dass register_globals in der PHP-Konfigurationsdatei aktiviert ist. Wir haben eine solche Adresse „test.php?admin=true“ übermittelt. Haben Sie das Ergebnis gesehen? Obwohl wir nicht über das richtige Cookie verfügen, wird die von uns übermittelte Admin-Variable automatisch als „true“ registriert, da „register_globals“ aktiviert ist. Darüber hinaus fehlt dem Skript ein „Nein“-Urteil, wodurch wir erfolgreich Administratorrechte über admin=true erhalten können. Dieses Problem besteht auf den meisten Websites und Foren.
2. Behebung der Sicherheitslücke:
Um dieses Problem zu lösen, müssen wir dem Administrator im Skript nur ein „Nein“-Urteil hinzufügen. Wir gehen immer noch davon aus, dass register_globals in der PHP-Konfigurationsdatei aktiviert ist. Schauen Sie sich den Code an:
$cookiesign="admincookiesign"; //Bestimmen Sie, ob die Cookie-Variable des Administrators ist
$adminsign=$_COOKIE["sign"]; //Cookie-Variable des Benutzers abrufen
if($adminsign==$cookiesign)
{
$admin=true;
}
anders
{
$admin=false;
}
if($admin){ echo „Sie sind jetzt Administrator.“ }
Selbst wenn der Angreifer die Variable admin=true ohne das richtige Cookie übermittelt, setzt das Skript auf diese Weise $admin in zukünftigen Entscheidungen auf False. Dies löst einen Teil des Problems. Da es sich bei $admin jedoch um eine Variable handelt, kommt es zu einer neuen Krise, wenn in anderen Skriptreferenzen in Zukunft eine Lücke auftritt und $admin neu zugewiesen wird. Daher sollten wir Konstanten verwenden, um die Bestimmung der Administratorberechtigungen zu speichern. Verwenden Sie die Define()-Anweisung, um eine Admin-Konstante zum Aufzeichnen von Administratorberechtigungen zu definieren. Wenn sie danach neu zugewiesen wird, tritt ein Fehler auf, wodurch der Schutzzweck erreicht wird. Schauen Sie sich den folgenden Code an:
$cookiesign="admincookiesign"; //Bestimmen Sie, ob die Cookie-Variable des Administrators ist
$adminsign=$_COOKIE["sign"]; //Cookie-Variable des Benutzers abrufen
if($adminsign==$cookiesign)
{
define(admin,true);
}
anders
{
define(admin,false);
}
if(admin){ echo „Sie sind jetzt im Administratorstatus.“ }
Es ist erwähnenswert, dass wir die Define-Anweisung verwenden. Wenn Sie also die Admin-Konstante aufrufen, fügen Sie normalerweise nicht das Variablensymbol $ voran, sondern verwenden Sie Admin und !admin.
Textdatenbank offengelegt
1. Ursache der Sicherheitslücke:
Wie bereits erwähnt, ist aufgrund der großen Flexibilität von Textdatenbanken keine externe Unterstützung erforderlich. Darüber hinaus verfügt PHP über sehr starke Dateiverarbeitungsfähigkeiten, sodass Textdatenbanken häufig in PHP-Skripten verwendet werden. Es gibt sogar einige gute Forenprogramme, die Textdatenbanken verwenden. Es gibt jedoch Gewinne und Verluste, und die Sicherheit von Textdatenbanken ist geringer als bei anderen Datenbanken.
2. Behebung der Sicherheitslücke:
Die Textdatenbank fungiert als gewöhnliche Datei, die wie eine MDB heruntergeladen werden kann. Daher müssen wir Textdatenbanken genauso schützen wie MDBs. Ändern Sie den Suffixnamen der Textdatenbank in .PHP. und in die erste Zeile der Datenbank eintragen. Auf diese Weise wird die Textdatenbank als PHP-Datei behandelt und die Ausführung wird in der ersten Zeile beendet. Das heißt, eine leere Seite wird zurückgegeben, um den Zweck des Schutzes der Textdatenbank zu erreichen.
Falscher Pfad durchgesickert
1. Ursache der Sicherheitslücke:
Wenn PHP auf einen Fehler stößt, gibt es den Speicherort, die Zeilennummer und den Grund des Fehlerskripts an, zum Beispiel:
Hinweis: Verwendung der undefinierten Konstante test – angenommen „test“ in D:interpubbigflytest.php in Zeile 3
Viele Leute sagen, es sei keine große Sache. Für einige Eindringlinge sind diese Informationen jedoch unvorstellbar. Tatsächlich haben viele Server dieses Problem.
Einige Netzwerkadministratoren setzen display_errors in der PHP-Konfigurationsdatei einfach auf Off, um das Problem zu lösen, aber ich denke, diese Methode ist zu negativ. Manchmal brauchen wir PHP wirklich, um Fehlerinformationen zum Debuggen zurückzugeben. Und wenn etwas schief geht, müssen Sie dem Benutzer möglicherweise auch eine Erklärung geben oder sogar zu einer anderen Seite navigieren.
2. Behebung der Sicherheitslücke:
PHP stellt seit 4.1.0 eine benutzerdefinierte Fehlerbehandlungs-Handle-Funktion function set_error_handler() zur Verfügung, aber nur wenige Skriptautoren wissen davon. Unter den vielen PHP-Foren habe ich nur wenige gesehen, die mit dieser Situation umgehen. Die Verwendung von set_error_handler ist wie folgt:
string set_error_handler ( callback error_handler [, int error_types])
Jetzt verwenden wir eine benutzerdefinierte Fehlerbehandlung, um die tatsächlichen Pfade herauszufiltern.
//Admin ist die Identitätsbestimmung des Administrators, true ist der Administrator.
// Die benutzerdefinierte Fehlerbehandlungsfunktion muss über diese vier Eingabevariablen $errno, $errstr, $errfile, $errline verfügen, andernfalls ist sie ungültig.
Funktion my_error_handler($errno,$errstr,$errfile,$errline)
{
//Wenn Sie kein Administrator sind, filtern Sie den tatsächlichen Pfad
if(!admin)
{
$errfile=str_replace(getcwd(),'',$errfile);
$errstr=str_replace(getcwd(),'',$errstr);
}
switch($errno)
{
Fall E_ERROR:
echo „FEHLER: [ID $errno] $errstr (Zeile: $errline von $errfile)
N";
echo „Das Programm wurde nicht mehr ausgeführt. Bitte wenden Sie sich an den Administrator.“;
//Das Skript verlassen, wenn ein Fehler der Fehlerebene auftritt
Ausfahrt;
break;
case E_WARNING:
echo „WARNUNG: [ID $errno] $errstr (Zeile: $errline von $errfile)
N";
Pause;
Standard:
//Fehler auf Hinweisebene werden nicht angezeigt
brechen;
}
}
//Fehlerbehandlung auf die Funktion my_error_handler setzen
set_error_handler("my_error_handler");
…
Auf diese Weise kann der Widerspruch zwischen Sicherheit und Debugging-Komfort gut gelöst werden. Und Sie können auch darüber nachdenken, die Fehlermeldung schöner zu gestalten, damit sie zum Stil der Website passt. Beachten Sie jedoch zwei Punkte:
(1) E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR und E_COMPILE_WARNING werden von diesem Handle nicht verarbeitet, dh sie werden auf die originellste Weise angezeigt. Diese Fehler werden jedoch durch Kompilierungs- oder PHP-Kernelfehler verursacht und treten unter normalen Umständen nicht auf.
(2) Nach der Verwendung von set_error_handler() ist error_reporting() ungültig. Das heißt, alle Fehler (mit Ausnahme der oben genannten Fehler) werden zur Verarbeitung an die benutzerdefinierte Funktion übergeben.
Weitere Informationen zu set_error_handler() finden Sie im offiziellen PHP-Handbuch.
POST-Sicherheitslücke
1. Ursache der Sicherheitslücke:
Wie bereits erwähnt, ist es eine schlechte Angewohnheit, sich beim Registrieren von Variablen auf register_globals zu verlassen. In einigen Gästebuch- und Forenprogrammen ist es sogar noch notwendiger, die Methode zum Abrufen von Seiten und den Zeitabstand zwischen den Beiträgen streng zu überprüfen. Um Spam-Beiträge und externe Einsendungen zu verhindern. Schauen wir uns den folgenden Code für ein Gästebuchprogramm an:
...
$text1=flt_tags($text1);
$text2=flt_tags($text2);
$text3=flt_tags($text3);
$fd=fopen("data.php","a");
fwrite($fd,"rn$text1&line;$text2&line;$text3");
fclose($fd);
...
Offensichtlich, wenn wir die URL „post.php?text1=testhaha&text2=testhaha&text3=testhaha“ übermitteln. Die Daten werden normal in die Datei geschrieben. Dieses Programm erkennt nicht die Quelle der Variablen und wie der Browser die Seite erhalten hat. Wenn wir mehrere Beiträge auf dieser Seite einreichen, kommt es zu Überschwemmungen. Es gibt auch einige Softwareprogramme, die diese Schwachstelle ausnutzen, um Werbung in Foren oder Gästebüchern zu veröffentlichen, was ein beschämendes Verhalten ist (das Gästebuch meines Freundes wurde in einer Woche mit mehr als 10 Seiten überflutet, was hilflos war).
2. Behebung der Sicherheitslücke:
Bevor Sie Daten verarbeiten und speichern, stellen Sie zunächst fest, wie der Browser auf die Seite gelangt. Verwenden Sie die Variable $_SERVER["REQUEST_METHOD"], um die Methode des Browsers zum Abrufen der Seite abzurufen. Überprüfen Sie, ob es „POST“ ist. Verwenden Sie die Sitzung im Skript, um aufzuzeichnen, ob der Benutzer Daten über normale Kanäle übermittelt (d. h. über die Seite, auf der der Übermittlungsinhalt ausgefüllt wird). Oder verwenden Sie $_SERVER["HTTP_REFERER"], um dies zu erkennen, dies wird jedoch nicht empfohlen. Da einige Browser REFERER nicht festlegen, blockieren einige Firewalls auch REFERER. Darüber hinaus müssen wir auch die übermittelten Inhalte überprüfen, um festzustellen, ob in der Datenbank doppelte Inhalte vorhanden sind. Nehmen Sie das Gästebuch als Beispiel und verwenden Sie Session, um die Entscheidung zu treffen:
Auf der Seite, auf der Sie den Browserinhalt eingeben, fügen wir am vorderen Ende Folgendes hinzu:
$_SESSION["allowgbookpost"]=time(); //Die Zeit, zu der die Registrierung ausgefüllt wird. Auf der Seite, auf der Nachrichtendaten akzeptiert und gespeichert werden, verwenden wir Session auch, um vor der Datenverarbeitung die folgende Verarbeitung durchzuführen:
if(strtoupper($_SERVER["REQUEST_METHOD"])!="POST"){ die("Fehler: Nicht extern senden." } //Überprüfen Sie, ob die Seitenerfassungsmethode POST ist
if(!isset($_SESSION["allowgbookpost"]) or (time()-$_SESSION["allowgbookpost"] < 10)){ die("Fehler: Nicht extern senden." } //Überprüfen Sie die Nachricht Zeit beim Ausfüllen
if(isset($_SESSION["gbookposttime"]) and (time()-$_SESSION["gbookposttime"] < 120)){ die("Fehler: Das Intervall zwischen zwei Übermittlungen von Nachrichten darf nicht weniger als 2 Minuten betragen. "); } //Überprüfen Sie das Nachrichtenintervall
unset($_SESSION["allowgbookpost"]); //Registrierung der Variableallowgbookpost aufheben, um zu verhindern, dass mehrere Einreichungen gleichzeitig auf die Ausfüllseite gelangen
$_SESSION["gbookposttime"]=time(); //Registrieren Sie die Zeit zum Senden von Nachrichten, um Spam oder böswillige Angriffe zu verhindern
...
Datenverarbeitung und -speicherung
...
Nach so vielen Überprüfungen wird Ihr Programm viel sicherer sein.