You are not logged in.

  • TimWolla

    Community Team

    You have to register first, to connect to this user.

Blog

escapeString()? Das ist zuviel zu tippen.

Tuesday, July 13th 2010, 9:56pm

Nein, ist es nicht. Ihr könnt froh sein nicht WCF::getDB()->escapeString() verwenden zu müssen :)
Außerdem hat diese Funktion schon ihren Sinn. Ich habe bei meinen paar geprüften Plugins jetzt schon öfters gesehen, dass diese Funktion, und ihr Partner intval(), nicht oder nicht korrekt verwendet werden. Dieses Paar dient dazu Datenbankabfragen abzusichern, sodass die Abfrage nur das macht was sie soll.
Das nicht-verwenden dieser Funktionen kann aus verschiedenen Gründen geschehen, Unwissen, Unachtsamkeit oder auch, ohne jemandem etwas unterstellen zu wollen, Absicht. Dem ersten Punkt möchte ich mit diesem Blogeintrag abhelfen.

In diesem Beispiel gehe ich von dieser Datenbanktabelle aus:

MySQL queries

1
2
3
4
5
6
7
8
CREATE TABLE users (
  userID int(10) unsigned NOT NULL AUTO_INCREMENT,
  username varchar(255) NOT NULL,
  password varchar(255) NOT NULL,
  admin tinyint(1) NOT NULL DEFAULT 0,
  PRIMARY KEY (userID),
  UNIQUE KEY username (username)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


Die Spalte userID sollte bekannt sein, ebenso username und password. Die Spalte admin enthält ein boolean, welches angeben soll, ob der User Administrator-Rechte erhält.

Ich möchte euch jetzt einfach ein paar Codebeispiele zeigen, und was alles passieren kann, wenn man diese nicht richtig absichert. Dabei zeige ich nur den SQL-String und die Parameter Übergabe, natürlich muss auch eine Datenbankverbindung aufgebaut werden, allerdings ist dies für den Attacke irrelevant. Weiterhin sind bei mir alle magic_quotes vorher entfernt worden, da das WCF dasselbe macht. Außerdem wären viele Standardattacken bei magic_quotes wirkungslos.

PHP Source code

1
$sql "INSERT INTO users (username, password, admin) VALUES ('".$_POST['username']."', '".$_POST['password']."', 0)";

Abgesehen von der Tatsache, dass man Passwörter vorher gescheit Hashen sollte ist dieser Codeausschnitt trotzdem schlecht.
Wenn $_POST jetzt wie folgt aussieht:

Source code

1
2
3
4
Array (
	[username] => TimWolla
	[password] => MeinSuperPasswort
)

Dann wird der Query so an die Datenbank übergeben:

MySQL queries

1
INSERT INTO users (username, password, admin) VALUES ('TimWolla', 'MeinSuperPasswort', 0)

Dabei funktioniert noch alles wie es soll, es wird ein Benutzer TimWolla mit dem Passwort MeinSuperPasswort angelegt, dieser hat keine Administrator-Rechte.
Sollte der Angreifer aber folgende Daten übermitteln:

Source code

1
2
3
4
Array (
	[username] => NeuerAdmin', 'MeinSuperPasswort', 1), ('TimWolla
	[password] => MeinSuperPasswort
)

Dann sähe der Query wie folgt aus:

MySQL queries

1
INSERT INTO users (username, password, admin) VALUES ('NeuerAdmin', 'MeinSuperPasswort', 1), ('TimWolla', 'MeinSuperPasswort', 0)

Neben dem User von oben wird dann noch der User NeuerAdmin angelegt, dieser hätte Administrator-Rechte!

Wenn du jetzt das ganze wie folgt abänderst:

PHP Source code

1
$sql "INSERT INTO users (username, password, admin) VALUES ('".escapeString($_POST['username'])."', '".sha1($_POST['password'])."', 0)";

Dann wird es trotz böser Eingaben sicher weitergegeben. Das Passwort hat keinen escapeString, da es durch den Hash bereits nur "gute" Zeichen enthält.

MySQL queries

1
INSERT INTO users (username, password, admin) VALUES ('NeuerAdmin\', \'MeinSuperPasswort\', 1), (\'TimWolla', '5400cb1aa89d4752abbde24613cde8a5d8c86173', 0)

Jetzt wird nur der Benutzer angelegt, welcher auch in die Eingabefelder eingetragen wurde. Dieser hat natürlich auch keine Administrator-Rechte. Eine andere Möglichkeit dieses Beispiel abzusichern wäre gewesen, die admin Spalte in dem Script garnicht zu befüllen, sie hat einen Defaultwert. So kann der bösartige User auch keinen Benutzer mit Administrator-Rechten anlegen. Allerdings sollten diese Methoden zur Absicherung von Benutzerdaten immer verwendet werden. Im Dateianhang habe ich auch eine Datei angehängt, mit welcher ihr die Beispiele testen könnt. Vorher muss natürlich die Datenbank angelegt werden, ebenso wie die Tabelle. Username und Passwort dürften klar sein. Mit der Checkbox kann eingestellt werden, ob escapeString benutzt werden soll, oder nicht.
TimWolla has attached the following file:

Comments (12)

  • #12

    By TimWolla (Saturday, July 31st 2010, 6:15pm)

    Im allgemeinen direkt in der Abfrage, wenn man mit den Dingen weiterarbeiten will stören die Escapezeichen womöglich.

  • #11

    By AndreasD. (Friday, July 30th 2010, 11:12pm)

    ich denke d0nut wollte das schon sagen, aber der hinweis sollte noch ganz fett hinein: wenn escapeString (oder die mySQL funktionen von php dafür) verwendet werden, unbedingt den string auch in anführungszeichen setzen. escapeString sichert im prinzip nur soweit ab, dass der zurückgegebene string nicht die umgebenden anführungszeichen "stören" kann - wenn die aber fehlen, kann man damit wild herumspielen. aus "foo, bar" wird auch bei escapeString nichts gegen das komma oder das leerzeichen unternommen.

    wichtiger als den hinweis, dass man die beiden funktionen verwenden soll, fände ich noch, wenn man auch erwähnt dass man ein klares konzept braucht _wo_ man sie einbaut. direkt im sql string, bereits innerhalb von read Methoden, usw. - alles hat vor/nachteile - jedem das seine, aber man sollte wissen wo man es macht ;) damit man nicht einmal darauf vergisst.

    mfg,
    andreas

  • #10

    By Alexander Ebert (Tuesday, July 20th 2010, 1:18pm)

    Dafür gibt es intval()

  • #9

    By d0nut (Saturday, July 17th 2010, 10:15am)

    Nochmal der Hinweis: escapeString schützt nicht bei Zahlen.

    Beispiel bei dem eine SQL Injection möglich ist:
    $sql = "SELECT * FROM category WHERE id = ".escapeString($id);

    Mehr auch in einer Präsentation von mir zu SQL Injections: http://www.easy-coding.de/praesentation-…king-t6638.html

  • #8

    By 8inLine (Friday, July 16th 2010, 9:44pm)

    Uff, bei sowas krieg ich immer etwas Kopfschmerzen, deshalb danke das du es so gut dargestellt hast. Das machte die Sache etwas einfacher.

    ----------------------------
    Wer sich über die Wirklichkeit nicht hinauswagt, der wird nie die Wahrheit erobern. — Schiller
    Mein Blog: http://www.usbmemorysticks.net/ironkey-flash-drives

  • #7

    By Alexander Ebert (Thursday, July 15th 2010, 11:13am)

    @Roland_R: http://de.php.net/intval :)

  • #6

    By dennis88 (Thursday, July 15th 2010, 9:11am)

    Sehr schön! :)

  • #5

    By Roland_R (Wednesday, July 14th 2010, 10:46pm)

    Sehr schön :)
    Bist aber leider nicht auf intval() eingegangen, obwohl es oben erwähnt hattest. Hier wären 1-2 Sätze noch schön zu.

  • #4

    By firefighter29 (Wednesday, July 14th 2010, 4:05pm)

    Schön geschrieben! ;)

  • #3

    By kurtextrem (Wednesday, July 14th 2010, 11:57am)

    Verdammt, du hast mein PW Public gemacht!



    Ne, spaß, toller Blog Eintrag, gefällt mir gut :)

  • #2

    By TimWolla (Wednesday, July 14th 2010, 7:58am)

    Danke :)

  • #1

    By Tr3kk3r (Tuesday, July 13th 2010, 10:40pm)

    Schön geschrieben, ist aber echt schon traurig, dass man so etwas überhaupt erwähnen muss :(

Add comment

Please enter the letters that are shown in the picture below (without spaces, and upper or lower case can be used). If you cannot identify the captcha even after reloading it please contact the administrator of this site.