2010-12-09 11 views
3

Ich weiß, dass einige Leute nur "nie" antworten, solange es Benutzereingaben gibt. Aber nehmen wir an, ich habe etwas wie folgt aus:Wie kann ich Eval in PHP sicher verwenden?

$version = $_REQUEST['version']; 
$test = 'return $version > 3;'; 
$success = eval($test); 

Dies ist offensichtlich eine vereinfachte Fall aber ist es etwas, was ein Benutzer eingeben kann als version dies zu bekommen, etwas zu tun böswillige? Wenn ich den Typ der Strings, die $test für den Vergleich des Werts bestimmter Variablen mit anderen Variablen übernehmen können, einschränken kann, gibt es irgendeinen Weg, den irgendjemand sehen kann, um das auszunutzen?

bearbeiten

Ich habe versucht, auf dem Server und nichts das folgende Skript ausgeführt passiert:

<?php 
    $version = "exec('mkdir test') + 4"; 
    $teststr = '$version > 3;'; 
    $result = eval('return ' . $teststr); 
    var_dump($result); 
?> 

alles, was ich bekommen bool(false) ist. Kein neues Verzeichnis wird erstellt. Wenn ich eine Zeile habe, die vorher exec('mkdir test') aufruft, erstellt sie tatsächlich das Verzeichnis. Es scheint korrekt zu funktionieren, indem man nur eine Zeichenfolge, die in eine Zahl konvertiert wurde, mit einer anderen Zahl vergleicht und das Ergebnis als falsch erkennt.

+0

Wie gesagt, '$ success = eval ($ test)' funktioniert nicht wie erwartet in PHP (anders als JavaScript). Sie müssen die Zuweisung in der bewerteten Zeichenfolge vornehmen. –

+1

Zwei Dinge: Sie vertrauen vollständig auf Benutzereingaben.Nicht nur das, Sie erlauben dem Benutzer somit, beliebigen Code auszuführen. Voila, sofortiger Exploit! (ja, ich würde sagen "nimm nie eval") – Piskvor

+0

Ich habe versucht, Code in dort zu injizieren, und es funktioniert einfach nicht für mich. –

Antwort

3

Wenn Sie dies tun. Akzeptiere nur Ints.

Wenn Sie Zeichenfolgen akzeptieren müssen, nicht.

Wenn Sie immer noch denken, dass Sie müssen. Nicht!

Und schließlich, wenn Sie immer noch danach denken, dass Sie Zeichenfolgen benötigen. Einfach nicht!

+2

Für Kommentare, die sagen, dass Sie Zeichenfolgen schützen können. Ja, du kannst. Wenn Sie wirklich wissen, was Sie tun. Wirklich WIRKLICH wissen, was Sie tun. Und OP nicht. Nichts gegen ihn. Ich auch nicht. Und höchstwahrscheinlich auch nicht. – DampeS8N

+0

Siehe meinen bearbeiteten Kommentar oben. Ich kann keine Zeichenfolge finden, die Code in meinem Beispiel injiziert. Gibt es etwas unsicheres daran? –

+0

Nur weil Sie nichts finden können. Bedeutet nicht, dass ein Angreifer das nicht kann. Es scheint, du hast meinen Standpunkt verpasst. Außerdem verwenden Sie eval nicht mehr für Benutzereingaben. – DampeS8N

0

Der Weg, um dies sicher zu machen wäre sicherzustellen, dass $version eine Nummer ist, bevor Sie versuchen, eval.

3

Ohhhh Junge!

$version = "exec('rm-rf/...') + 4"; // Return 4 so the return value is "true" 
            // after all, we're gentlemen! 
$test = "return $version > 3"; 
eval($test); 

:)

würden Sie haben mindestens einen filter_var() oder is_numeric() auf dem Eingabewert in diesem Fall zu tun.

Übrigens, die Art und Weise, wie Sie eval verwenden (Zuweisung des Ergebnisses an $success) funktioniert nicht in PHP. Sie müssten die Zuweisung in die Zeichenfolge eval() ed einfügen.

+0

Zumindest funktioniert die $ success-Zuweisung, weil ich den Wert innerhalb der eval-Anweisung zurückgebe. –

+0

@Ed Ich stehe korrigiert, es ist in der Tat möglich, etwas von der Eval-Anweisung zurückzugeben. Ihr Code ist in Ordnung –

+0

Was die Exec-Sache angeht, habe ich versucht, einen einfachen Test zu schreiben, indem ich eine exec injiziere, und es tut einfach nichts, ich habe eine einfache exec ('mkdir test') versucht. Irgendeine Idee warum? –

1

ja, alles. Ich würde $version = (int)$_REQUEST['version']; verwenden, um die Daten zu validieren.

-1

Sie müssen genauer mit Ihren Definitionen von "bösartig" oder "sicher" sein. Betrachten wir zum Beispiel

exec("rm -rf /"); 

echo "enlarge your rolex!"; 

while(true) echo "*"; 

alle drei Schnipsel „bösartige“ aus dem gesunden Menschenverstand Sicht sind jedoch technisch sind sie ganz anders. Schutztechniken, die für # 1 gelten, funktionieren nicht mit anderen zwei und umgekehrt.

-2

Verwenden Sie diesen Code, um alles außer Zahlen (0-9) zu entfernen: preg_replace ('/ [^ 0-9] + /', '', $ version);