[SQL Injektion]Maqic Quotes - der ultimative Schutz?

Einen schönen guten Tag,
Ich befasse mich momentan gerade mit der SQL-Injektion und habe aus Spaß mal ein wenig damit auf meinem Server rumgetestet. Dafür habe ich nen table "users" erstellt, ein paar Datensätze eingetragen und ein Profil-viewer geschrieben. Hierbei wird die Id des Users als GET Parameter übergeben
Code:
profile.php?user_id=0
Die SQL-Abfrage machte ich zuerst so
PHP:
$sql = "SELECT * FROM users WHERE id=".$_GET['user_id']."";
So war es sehr einfach den query irgendwie zu manipulieren (Der Sinn dahinter sei jetz mal zurückgestellt)
Anschließend hab ich Hochkommata in die SQL-Abfrage reingebracht
PHP:
$sql = "SELECT * FROM users WHERE id='".$_GET['user_id']."'";
So ist es für mich nun unmöglich den Query in irgend einer Art und Weise zu manipulieren, da es einfach nicht möglich ist aus dem Query "auszubrechen", da Maqic Quotes eingeschaltet sind, d.h. jedes ' wird mit einem \' ersetzt. Meine Frage ist nun, ist Maqic Quotes wirklich der ultimative Schutz, der SQL-Injektionen unmöglich macht? Würde mich wundern, weil warum gibt es dann mysql_real_escape_string? Gibt es irgendeinen Weg Maqic Quotes zu umgehen?
 
Was würde denn passieren, wenn die Eingabe nicht aus Chars besteht sondern ein Hexwert ist?

http://www.google.de/search?hl=de&q=hexadecimal+sql+injection&btnG=Suche&meta=

In diesem Artikel ist auch ein schönes Beispiel aufgeführt wieso man lieber mysql_real_escape_string zum Maskieren von Sonderzeichen verwenden sollte (oder ab PHP5 Prepared-SQL-Statements), statt sich auf die magic_quotes-Option(en) zu verlassen. ;)
 
Hallo Knoxx,
Erst einmal, vielen Dank für deine Antwort. Allerdings versteh ich nicht so ganz genau wie du das mit dem hex-wert meinst. Meinst du so etwas?:
Code:
profile.php?user_id=0x27
Falls ja, das würde dann so interpretiert werden
PHP:
$sql = "SELECT * FROM users WHERE id='0x27'";
Also '0x27' als String würde interpretiert werden .. und der User mit der Id = 0 wird ausgegeben werden.
 
Hallo,
naja warum gibt es mysql_real_escape_string:
1. Weil nicht alle magic_quotes aktiviert haben
2. Weil magic_quotes ab PHP6 deaktiviert wird (zumindest nach aktuellen Infos).

Ebenso erwischt magic quotes nicht alle kritischen Variablen, über die SQL Injections möglich sind.

Ein Beispiel:
//Login
$_SESSION['username'] = $mysql_row['username'];
//...

//Seite2
$sql = "SELECT * FROM table WHERE username = '".$_SESSION['username']."'";


Wenn ich mich nun mit dem Username " abc' OR '1'='1" registiere, sieht die SQL Anweisung auf einmal so aus:
SELECT * FROM table WHERE username = 'abc' OR '1'='1'

Zack, hat man eine verwundbare Stelle.


Auch arbeitet magic quotes (ebenso addslashes) nicht bei allen Charsets von MySQL korrekt. Bei UTF8 und ISO-8859 ist es kein Problem, es gibt aber Charsets, bei denen eine SQL Injection möglich ist, obwohl man magic_quotes_gpc bzw. addslashes nutzt.

Dort hilft dann mysql_real_escape_string, da dieses auch das Charset von MySQL berücksichtigt.
 
Hallo Elderan,
Auch dir vielen Dank für die Antwort. Ich habe jedoch noch eine Frage bezüglich deines Beispiels mit dem Usernamen "abc' OR '1'='1", würde bei der Anmeldung ein derartiger Username nicht ebenfalls von maqic quotes kastriert werden und dann erst in die db eingetragen werden? Heisst das jetz eigentlich, dass in dem von mir beschriebenen fall es keine Möglichkeit gibt den query zu manipulieren?
 
Hallo,
ja, " abc' OR '1'='1 " würde bei der Anmeldung per magic_quotes_gpc betroffen werden, aber der Eintrag sieht ja so aus:
INSERT INTO users VALUES ('$username', ...)

Dies wird zu:
INSERT INTO users VALUES ('abc\' OR \'1\'=\'1 ', ...)

Wenn man nun aus users den Username ausliest, dann hat man wirklich den String:
abc' OR '1'='1
ohne das Escapen von '.

Hier im Forum kann man ja auch Problemlos ein ' posten ;)


Also kann man darüber eine SQL Injection ausführen.
 
Hallo Elderan,
Erneut danke für die Antwort. Ich muss schon sagen, dass das zwar ne geschickte aber doch leicht behebbare Schwachstelle wäre, indem man einfach bei der Anmeldung diese "bösen" Zeichen nicht erlaubt oder etwas derartiges. Es ist irgendwie schon extrem wie übel mir diese doofen Maqic Quotes die Tour versauen^^. Eigentlich ist dieser von mir erwähnte profile viewer bzw. diese Anweisung
PHP:
$sql = "SELECT * FROM users WHERE id='".$_GET['user_id']."'";
unmöglich zu manipulieren, das will Ich irgendwie net glauben. Es kann doch net so einfach sein sich gegen Angriffe zu schützen :D
 
Hallo,
Original von PHRoZeNCReW
Es kann doch net so einfach sein sich gegen Angriffe zu schützen :D
Ist es auch nicht...

Nur gegen die ganz dummen Fehler hilft magic_quotes_gpc.

Und ja:
"SELECT * FROM users WHERE id='".$_GET['user_id']."'";

ist bei eingestelltem magic_quotes_gpc und einem unproblematischem Zeichensatz sicher vor SQL Injections.
Zu dem Thema gehört aber noch viel mehr als solch eine einfache Abfrage und bei komplexen Systemen kann es schwierig werden zu überprüfen ob man auch alle Abfragen geschützt hat.
 
Sehe ich das falsch oder haben prepaired Statements "automatisch" keine solchen 'escape' Probleme? In 90% aller Fälle lassen sich doch die ganzen Queries mit prepaired ersetzen (sind die PHPler einfach zu faul für ;) ? )
 
Hmm du Brauchst auch nicht immer quotes,
id ist in der Regel kein VARCHAR, also zb:
Code:
index.php?id=1
 index.php?id= 1 ORDER BY x --   //eg 22 columns 
index.php?id= -1 AND 1=0+UNION ALL SELECT 1,2,3,4...22 -- //returns 4 
index.php?id= -1 AND 1=0+UNION ALL SELECT 1,2,3,schema_name,....,22 from information_schema.schemata --
Geht auch oft.

Hallo, Zitat: Original von PHRoZeNCReW Es kann doch net so einfach sein sich gegen Angriffe zu schützen großes Grinsen
Ist es auch nicht...
Nein bloss nicht.
->mysql_real_escape_string<-
Problem bei magic quotes ist es, das oft auch gewollte quotes, die nicht grad an denn Sql Server weitergeleitet werden unnutze gemacht werden.

Wenn die Leute zu blöd sind sowas einfaches wie mysql_real_escape_string zu nutzen,
dann sollten sie die Finger von Datenbanken mit empfindlichen Inhalt lassen.
Mann könnte zb ne Wrapper-Funktion nutzen:
mysql_query_2($query)
die dann mysql_query(mysql_real_escape_string($query)) aufruft.

Beim Microsoft-Sql Server bzw Oracle gibts auch genug Möglichkeiten das zu verhindern, also ist wirklich nicht schwer sich vor Sql-Injections zu schützen.
 
Original von CDW
Sehe ich das falsch oder haben prepaired Statements "automatisch" keine solchen 'escape' Probleme? In 90% aller Fälle lassen sich doch die ganzen Queries mit prepaired ersetzen (sind die PHPler einfach zu faul für ;) ? )
Ja, das stimmt schon. Prepared Statements haben in dieser Hinsicht absolut keine Probleme mit SQL-Injections.
Leider werden Prepared Statements von der MySQL-Standarderweiterung "mysql" nicht unterstützt. Nur das neuere "mysqli" (ab PHP 5/MySQL 4.1.3) oder die abstrakte Datenbankbibliothek PDO (PHP Data Objects, ab PHP 5) können bereits Prepared Statements. Daher werden Prepared Statements wahrscheinlich recht selten (auch wegen Abwärtskompatibilität) eingesetzt.

mfg, metax.
 
@metax: gut zu wissen. Hab bis jetzt entweder mit Embedded DBs (hsql) oder DB2 gearbeitet. Da gibt keine Probleme mit Prepaired Statements.
Btw: 4.1 wurde doch schon 2004 freigegeben - wird es da Entwicklungstechnisch nicht langsam Zeit, mit der Abwärtskompatibilität zu brechen - vor allem wenn es um ein deutliches Sicherheitsplus geht? Auch bietet MySQL < 4.1 viele Dinge nicht (B-Trees,Subqueries usw) die inzwischen doch recht fröhlich und munter eingesetzt werden. Oder geht es hier auch ein wenig nach dem Prinzip zu: "was der Bauer nicht kennt, das frisst er nicht!".
 
@CDW

Die meisten Proggen einfach vor sich hin und wollen nur das das Script läuft und ich bin mir sehr sicher, dass andere auch meiner Meinung sind und deshalb wird es sich nicht bei jedem Programmierer ankommen sag ich mal :).
Für z.B große Boardsoftware wie VBulletin es ist, wären Prepared Statements sehr angebracht, da man auch sieht das bei der Boardsoftware aufjedenfall auf Sicherheit geachtet wird, denn ich glaub nicht das WBB3 bei CSRF standhalten kann...

Gruß
Keci
 
Original von CDW
Sehe ich das falsch oder haben prepaired Statements "automatisch" keine solchen 'escape' Probleme? In 90% aller Fälle lassen sich doch die ganzen Queries mit prepaired ersetzen (sind die PHPler einfach zu faul für ;) ? )
Ich wüsste nicht einmal, was gegen die 100% sprechen sollte. Bei wiederholter Ausführung kriegt man damit sogar noch Performance-Optimierung geschenkt.
Allerdings glaube ich, dass das Problem ganz woanders liegt: Die meisten haben einfach keine Ahnung / denken nicht nach. Vor einer guten Woche hatte ich einen Freund auf das Problem aufmerksam gemacht, heute sehe ich überall Prepared Statements, dafür bietet das Gästebuch und das PM-System eine tolle Angriffsfläche für XSS. Beides ensteht durch unerwünscht Benutzereingaben, beide Male ist es die gleiche Unachtsamkeit, die für die Probleme verantwortlich ist.
So wie ich das mitkriege, versteht fast jeder "kleine" Features wie Prepared Statements, denkt aber nie nach, was er da eigentlich fabriziert.
 
Original von PHRoZeNCReW
Hallo Knoxx,
Erst einmal, vielen Dank für deine Antwort. Allerdings versteh ich nicht so ganz genau wie du das mit dem hex-wert meinst. Meinst du so etwas?:
Code:
profile.php?user_id=0x27
Falls ja, das würde dann so interpretiert werden
PHP:
$sql = "SELECT * FROM users WHERE id='0x27'";
Also '0x27' als String würde interpretiert werden .. und der User mit der Id = 0 wird ausgegeben werden.

Hex-werte werden in der URL ja auch nicht mit 0x27 sondern mit %27 übergeben...
Code:
profile.php?user_id=%27

kritisch ist hierbei insbesondere das Null-Byte - also %00, womit das Ende eines Strings markiert wird,
Das ist eigentlich so einer der wichtigsten Schlüssel für SQL-Injections, um eben z.B. die darauffolgenden Vergleiche im WHERE einer Query abzuschneiden...


bsp:
http://www.google.com/search?q=Hier%20ist%20der%20String%00zuende


und zum Thema Abwärtskompatibilität:
seit dem ich in PHP hauptsächlich objektorientiert programmiere, habe ich jegliche Abwärtskompatibilität zu PHP4 aufgegeben - denn OOP in PHP4 war einfach Kacke (keine Destruktoren, keine Sichtbarkeits-Schlüsselwörter (private/protected/public))
meine Scripte laufen mit etwas Glück ab PHP 5.0 (es wurden auch in PHP 5.2 noch einige Funktionen um nützliche Parameter erweitert - da muss ich mich schon manchmal zusammenreisen, dass ich nicht sag 'Pech gehabt für alle, die < PHP 5.2 nutzen...')
 
Zurück
Oben