Heim >Backend-Entwicklung >PHP-Tutorial >Ausführliche Erläuterung der Ergebnisse der Umgehung der Schwachstelle aufgrund von Offset-Zeichen in PHP
Dieser Artikel führt Sie hauptsächlich in die relevanten Informationen zur Bypass-Schwachstelle ein, die durch die Zeichenoffset-Funktion in PHP verursacht wird. Der Artikel stellt nicht nur die Entstehung der Schwachstelle im Detail vor, sondern, was noch wichtiger ist, stellt die Reparaturmethode vor Freunde, die es brauchen, können einen Blick auf den Referenz-Lernwert werfen.
Zeichenversatzfunktion in PHP
Es gibt eine sehr interessante Funktion in Zeichenfolgen in PHP. Zeichenfolgen in PHP können auch wie Werte sein werden auf die gleiche Weise wie ein Array erhalten.
$test = "hello world"; echo $test[0];
Das Endergebnis ist h.
Die obige Funktion hat jedoch manchmal unerwartete Auswirkungen. Schauen Sie sich den folgenden Code an.
$mystr = "hello world"; echo $mystr["pass"];
Die Ausgabe des obigen Codes ist h. Warum ist das so? Tatsächlich ist es sehr einfach. Wie in vielen anderen Sprachen können auch Strings in PHP Indizes verwenden, um Werte zu erhalten, genau wie Arrays. Der Pass in $mystr["pass"]
wird implizit in 0 konvertiert, sodass das Ausgabeergebnis von $mystr[0]
der Anfangsbuchstabe h ist
Ebenso, wenn Sie den folgenden Code ausprobieren:
$mystr = "hello world"; echo $mystr["1pass"];
Das Ausgabeergebnis ist e. Da 1pass durch den impliziten Typ in 1 konvertiert wird, ist das Ausgabeergebnis von $mystr[1]
der zweite Buchstabe e.
Charaktereigenschaften Die Sicherheitslücke verursacht
Der folgende Code wird in phpspy2006 verwendet, um den beim Anmelden verwendeten Code zu bestimmen.
$admin['check'] = "1"; $admin['pass'] = "angel"; ...... if($admin['check'] == "1") { .... }
Eine solche Verifizierungslogik kann leicht umgangen werden, wenn die oben genannten Funktionen verwendet werden. $admin ist zunächst nicht als Array-Typ definiert. Wenn wir es also mit einer Zeichenfolge phpsyp.php?admin=1abc
übermitteln, übernimmt PHP das erste Bit der Zeichenfolge 1xxx und umgeht so erfolgreich die if-bedingte Beurteilung.
Der obige Code ist ein Codefragment, und der folgende Code ist ein vollständiger Logikcode, der aus Frage 5 in php4fun stammt, was sehr interessant ist.
<?php # GOAL: overwrite password for admin (id=1) # Try to login as admin # $yourInfo=array( //this is your user data in the db # 'id' => 8, # 'name' => 'jimbo18714', # 'pass' => 'MAYBECHANGED', # 'level' => 1 # ); require 'db.inc.php'; function mres($str) { return mysql_real_escape_string($str); } $userInfo = @unserialize($_GET['userInfo']); $query = 'SELECT * FROM users WHERE id = \'' . mres($userInfo['id']) . '\' AND pass = \'' . mres($userInfo['pass']) . '\';'; $result = mysql_query($query); if (!$result || mysql_num_rows($result) < 1) { die('Invalid password!'); } $row = mysql_fetch_assoc($result); foreach ($row as $key => $value) { $userInfo[$key] = $value; } $oldPass = @$_GET['oldPass']; $newPass = @$_GET['newPass']; if ($oldPass == $userInfo['pass']) { $userInfo['pass'] = $newPass; $query = 'UPDATE users SET pass = \'' . mres($newPass) . '\' WHERE id = \'' . mres($userInfo['id']) . '\';'; mysql_query($query); echo 'Password Changed.'; } else { echo 'Invalid old password entered.'; }
Online gibt nur eine abschließende Antwort auf diese Frage, und die Prinzipien werden nicht oder nicht im Detail erklärt. Tatsächlich liegt das Prinzip in den oben erwähnten Charaktereigenschaften von PHP.
Die Frageanforderung ist sehr einfach: Ändern Sie das Passwort des Administrators und die ID des Administrators ist 1. Wir müssen über die folgenden Fragen nachdenken:
Wie ändere ich die ID während des Updates auf 1?
$userInfo['pass'] = $newPass;
Was ist darin enthalten? Codezeile Funktion, warum existiert dieser Code in der if-Beurteilungsanweisung
Nachdem wir diese beiden Probleme herausgefunden haben, ist auch die endgültige Lösung verfügbar. Ändern Sie das Passwort des Benutzers mit der ID 8 in 8, übergeben Sie dann eine UserInfo-Zeichenfolge „8“, um den Abfrageschutz zu durchbrechen, und ändern Sie schließlich mit $userInfo['pass'] = $newPass
die ID in 1.
Die letzte Nutzlast ist;
Die erste Übermittlung, index.php?userInfo=a:2:{s:2:"id";i:8;s:4:"pass";s:12:"MAYBECHANGED";}&oldPass=MAYBECHANGED&newPass=8
, besteht darin, das Passwort des Benutzers mit der ID 8 in 8 zu ändern
Die zweite Übermittlung, index.php?userInfo=s:1:"8";&oldPass=8&newPass=1
, serialisiert $userInfo und ruft die Zeichenfolge „8“ ab, die $userInfo = ‘8'
ist, sodass die Überprüfung der Datenbankabfrage erfolgreich sein kann. Die anschließende Überprüfung kann ebenfalls über diese Codezeile $userInfo['pass'] = $newPass;
erfolgen, da der Wert von $newpass 1 ist, dann wird der obige Code zu $userInfo['pass'] = 1;
, $userInfo
aufgrund eines Zeichenfolgentyps, das Endergebnis ist $userInfo='1'
, Schließlich können Sie das Passwort des Benutzers mit der ID 1 aktualisieren.
Behebungsmethode
Die Reparaturmethode für diese Art von Schwachstelle ist ebenfalls sehr einfach. Definieren Sie den Datentyp im Voraus und überprüfen Sie ihn vor der Verwendung . Entsprechen die verwendeten Datentypen den Erwartungen? Andernfalls kommt es zu den oben genannten Bypass-Problemen. Gleichzeitig muss die Eingabe kontrolliert werden, und die Eingabedaten müssen überprüft werden und dürfen nicht beiläufig verwendet werden.
Das obige ist der detaillierte Inhalt vonAusführliche Erläuterung der Ergebnisse der Umgehung der Schwachstelle aufgrund von Offset-Zeichen in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!