it-swarm.com.de

Ausnutzen der MD5-Sicherheitslücke in diesem PHP Formular?

Ich habe in sicherheitsrelevanten Themen geübt und bin auf dieses Problem gestoßen, das ich überhaupt nicht verstehe. Sie erhalten ein Formular mit einer Eingabe namens pass, und dies ist der Code, den Sie umgehen müssen:

<?php
error_reporting(0);
session_save_path('/home/mawekl/sessions/');
session_start();
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>';
echo 'This task is as hard to beat as the castle which you can see on the bottom.<br>';
echo '<pre>';
include('./ascii.txt');
echo '</pre><br>';

$_SESSION['admin_level']=1;

if (!isset($_POST['pass']) || md5($_POST['pass'])!='castle')
{
    echo '<b>Wrong or empty password.</b><br>';
    $_SESSION['admin_level']=0;
}

Wenn es in die endgültige if-Anweisung eingeht, verlieren Sie (müssen es so machen $_SESSION['admin_level'] bleibt bei 1).

Jede Hilfe wird geschätzt, danke!

Klarstellung :

Ich kann den von mir geposteten Code nicht bearbeiten. Es ist eine Herausforderung. Ich kann nur ein Passwort über eine Eingabe senden, deren Name "pass" ist. Ja, ich weiß, dass md5 eine 32 Zeichen lange Zeichenfolge zurückgeben soll. Das ist die Herausforderung.

42
Tom

Versuchen Sie, eine HEAD - Anfrage zu senden.

Ich gehe davon aus, dass mit ascii.txt die Ausgabe des Skripts knapp über einer Nice-Zahl wie 4096 Bytes liegt, einem gemeinsamen Wert von output_buffering. Sobald das Skript output_buffering Bytes geschrieben hat, muss es den Ausgabepuffer leeren, bevor es fortfährt.

Normalerweise funktioniert dies einwandfrei und das Skript wird fortgesetzt, aber wenn der Anforderungstyp HEAD ist, kann die Ausgabe nirgendwo hingehen und die Ausführung wird gestoppt, hoffentlich mitten in der Meldung "Falsches Passwort", was bedeutet, dass admin_level Nie gesetzt wird zurück auf 0.

Wenn ascii.txt eine Datei ist, die Sie steuern können, müssen Sie die Größe anpassen, damit die Zahlen output_buffering Überschreiten, während Sie die Nachricht "Falsches Passwort" schreiben.

Hier ist ein Artikel über diese Technik . Es ist möglicherweise nicht immer auf der Grundlage von PHP version/config) anwendbar, aber das letzte Beispiel in diesem Dokument ist diesem Problem so ähnlich, dass ich erwarten würde, dass es die beabsichtigte Lösung ist.

59
gabedwrds

Die Sicherheitslücke liegt in diesem Fall nicht in MD5. Und die Idee ist nicht, if (!isset($_POST['pass']) || md5($_POST['pass'])!='castle') dazu zu bringen, zugunsten des Hackers zu bewerten. Die Sicherheitsanfälligkeit wird angezeigt, wenn Sie das Skript zum Absturz bringen. Die Administratorrechte sind nicht bedingt. Unabhängig davon, was der Benutzer erhält, wird seine Berechtigung durch Setzen von 1 auf $_SESSION['admin_level'] Erhöht. PHP ist prozedural. Wenn Sie also die folgende IF-Anweisung fehlerhaft ausführen können, wird die Berechtigung nicht nur festgelegt, sondern bleibt dauerhaft. Diese steht jetzt dem Rest des Programms zur Verfügung, da sie in der gespeichert ist Sitzung. Auch wenn das Skript abstürzt und Fehler auftreten. Wenn die IF-Anweisung nur während einer Anmeldung vorhanden ist, kann der Angreifer alle anderen eingeschränkten Skripte als admin_level auf 1 setzen.

Also Zeitleiste der Ereignisse:

  • Der Angreifer fügt fehlerhafte Daten oder einen Datenüberlauf in die Anforderung POST) ein
  • Skript läuft
  • Das Skript gibt admin_level von 1 an, das in der Sitzung gespeichert ist
  • Skriptbomben bei der Auswertung
  • Der Angreifer wechselt zu einer anderen Seite/einem anderen Skript, um zu prüfen, ob $_SESSION['admin_level'] 1 ist

Dies könnte vermieden werden, wenn das Skript den Sitzungswert in die IF-Anweisung aufnehmen würde:

if (!isset($_POST['pass']) || md5($_POST['pass'])!='castle')
{
    echo '<b>Wrong or empty password.</b><br>';
    $_SESSION['admin_level']=0;
} else {
    $_SESSION['admin_level']=1;
}

Es sollte jedoch noch viel mehr getan werden, um diesen Code zu sichern.

27
Bacon Brad

Ich habe irgendwo eine ähnliche Herausforderung gesehen. Versuchen Sie, etwas wie 'QNKCDZO' Als Eingabe zu senden. md5('QNKCDZO') ist '0e830400451993494058024219903391' (beachten Sie das Präfix 0e im Hash, das die wissenschaftliche Notation einer Zahl angibt) und da der Code den Operator != verwendet (anstelle von Der typsensitive !==) PHP (nur ältere Versionen?) wandelt ihn vor dem Vergleich tatsächlich in eine Zahl um. Offensichtlich werden beide dann zu 0 und ausgewertet du gewinnst.

Edit: Ruakh ist richtig. Dies funktioniert nicht ganz, da sowohl der Hash als auch die Zeichenfolge 'castle' Wie eine Zahl für PHP] aussehen müssten, damit die Besetzung stattfinden kann.

17
Younis Bensalah

Ich konnte nicht in PHP 5.5.9 testen, und was ich vorschlagen werde, funktioniert nicht auf meinem PHP 5.6.22) (aber ich hätte vielleicht einen dummen Fehler gemacht).

Die einzige Problemumgehung, die ich mir vorstellen kann, ist, wenn MD5 etwas zurückgibt, das als Zahl behandelt wird. Ich habe gegoogelt und gefunden etwas, das deutsch erscheint .

9
LSerni

Ich sehe, dass Sie die gabedwrds-Lösung akzeptiert haben (was übrigens ausgezeichnet ist), aber ich wollte eine mögliche Lösung veröffentlichen, die ich in der Vergangenheit verwendet habe, als ich eine interessante Pentest-Übung durchgeführt habe. (Ich bin kein Experte auf diesem Gebiet, aber manchmal ein Hobbiest.)

Wenn Sie bemerken, legt das Skript niemals eine Richtlinie für die Behandlung eines Benutzerabbruchs fest. Standardmäßig (sofern in PHP ini) nicht anders konfiguriert) wird das Skript PHP] sofort beendet und stoppt alle, wenn ein Benutzer seine Verbindung abbricht, während eine Seite geladen wird Wenn Sie Ihre Verbindung genau richtig einstellen, können Sie aus diesem Grund Ihre Verbindung zwischen $_SESSION['admin_level']=1; und der Auswertung der Bedingung abbrechen und den Server dazu zwingen, das Skript sofort zu beenden, ohne die bedingte Auswertung zu beenden würde dazu führen, dass admin_level auf Null zurückgesetzt wird.

Dies hängt natürlich vollständig von der PHP Konfiguration ohne ignore_user_abort=1 Ab. Wenn dies so eingestellt ist, dass es auch dann fortgesetzt wird, wenn ein Benutzer abbricht, werden die Berechtigungen weiterhin zurückgesetzt.

Um Ihr Zeitfenster für die Verwendung dieses Exploits zu vergrößern, können Sie die Größe Ihrer pass Nutzdaten/variablen Daten erhöhen. md5 Muss in Blöcken hashen. Wenn Sie also die Größe der pass -Daten erhöhen, wird die Funktion md5 Mehr Zeit für die Berechnung des Hashs aufwenden, wodurch ein großer Wert entsteht Zeitspanne, in der Sie die Verbindung abbrechen müssen.

4
Spencer D

Angenommen, Sie können die ./ascii.txt ändern, würde ich diesen Text einfügen:

<?php

override_function('md5', '$a', 'return "castle";');

Und das sollte funktionieren.

2
peterpeterson

Ähnlich wie andere gesagt haben, hat PHP eine maximale Speichergröße. Wenn Sie POST Daten eingeben, die NUR groß genug waren, um fast den gesamten PHP-Speicher zu nutzen) up, dann könnte es möglicherweise abstürzen, wenn es genau zu dieser Zeile kommt, wenn es nicht genügend Speicher hat:

echo 'Falsches oder leeres Passwort.'

Dies basiert auf drei Prinzipien:

1) Wenn Sitzungen aktiviert sind, wird PHP die Ausgabe nicht leeren, sondern alles in RAM speichern), bis das Rendern der Seite abgeschlossen ist.

2) PHP hat ein Maximum RAM Größe für jede Anforderung zugewiesen und stürzt bei Erreichen Ihr Skript ab.

3) Wenn neue Zeilen geschrieben werden, wird mehr RAM verwendet, wobei der verbleibende RAM verbraucht wird.

Wenn Sie unter Berücksichtigung der oben genannten Fakten mehr HTTP POST -Daten in Ihre HTTP-Anforderung einfügen (z. B. $ _POST ["data"] = "größter Ring"), können Sie möglicherweise einen Speicherfehler auslösen bevor $ _SESSION ["admin_level"] = 0 ausgeführt wird.

In einem realen Szenario ist dies höchst unwahrscheinlich, da PHP hat auch ein Maximum POST Körpergröße, maximale Headergröße und welcher Servercontainer es auch hostet) (nginx, Apache usw.) hat normalerweise auch maximale Grenzwerte. Sie würden wahrscheinlich alle diese maximalen Grenzwerte erreichen, aber wenn Sie schlecht konfiguriert sind, ist es möglich, dass $ _SESSION ["admin_level"] = 1 effektiv zum Administrator wird, wenn Sie zu einem beliebigen gehen andere Seiten auf der Website mit dieser Methode.

pdate : Eine andere ähnliche Methode wäre, ein großes Passwort einzugeben, damit die Funktion md5 () während der Verarbeitung fehlschlägt oder so, was wiederum zum Absturz führt, weil der Speicher knapp wird. Kommt darauf an, wie md5 () intern funktioniert. Es wird wahrscheinlich eine KOPIE aus dem Feld $ _POST ["pass"] erstellt. Wenn also $ _POST ["pass"] gigantisch wäre, könnte es sehr einfach sein, diese Kopie so zu gestalten, dass sie alle RAM und bringt es zum Absturz.

2
Jacob Beasley