Hier im Forum bekommt ihr bei euren fragen schnelle hilfe.Hier geht es rund um das Web SeitenProgrammieren.Alles rund ums Javascript,Html,Php,Css und Sql.Auf fast allen Fragen haben wir eine Antwort.
Der Soforthilfe-chat verspricht das ,was sein Name sagt. Hier sind Leute Online die sofort ihre hilfe anbieten.Seht in der OnlineListe nach und wenn einer Online ist werdet ihr auch antwort bekommen. Admine ,Moderatoren und Helfer sind unsere Spezialisten in Sachen Web Programierung
71 Unwetterwarnungen in Deutschland
Die Datenbank wurde zuletzt am 02.08.2020 17:34:28 aktualiesiert
71

Angriffe auf Webanwendungen – Teil 3: SQL-Injection

Vorherige Teile der Serie

Okay, ich schäme mich fast, darüber noch was zu schreiben. Man möchte doch meinen, dass SQL Injection DER bekannteste Angriff überhaupt ist. Möchte man meinen. Bisher hat sichs aber immer noch nicht bis zum letzten Webentwickler rumgesprochen, weswegen ich hier mal 2 konkrete Beispiele liefere, an denen man herumexperimentieren kann.

Was ist SQL-Inection?

Wenn ein Benutzer der Anwendung die Möglichkeit hat, selbst SQL einzuschleusen spricht man von SQL-Injection. Besonders beliebt sind (gerade in älteren Webanwendungen) das Einschleusen von SQL per $_GET. Beispiel gefällig?

Angriffsszenario 1: Der Login

Eigentlich das Musterbeispiel dafür: Folgender Code wird zum validieren eines Login-Formulars verwendet:

<?php $conn = new MySQLi("localhost", "root", "", "userdb");  $sql = "SELECT COUNT(*) AS c FROM users WHERE username='".$_POST['username']."' AND password='".$_POST['password']."'"; $res = $conn->query($sql); $rec = $res->fetch_assoc(); $valid = ($rec['c'] == 1);  if ($valid) { 	//do session stuff... 	header("Location: profile.php"); } else { 	print "Nope, incorrect"; } ?> 

Das Formular (trivial) sieht so aus:

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST"> 	<input type="text" name="username" /> 	<input type="password" name="password" /> 	<input type="submit" value="Anmelden" /> </form> 

Der Benutzer tippt in beide Felder ' OR '1=1, womit die SQL-Abfrage so aussieht: SELECT COUNT(*) AS c FROM users WHERE username='' OR '1=1' AND password='' OR '1=1'

Das ist immer wahr, somit kann sich der Angreifer einloggen, ohne korrekte Zugangsdaten angegeben zu haben.

Angriffsszenario 1: Die Kategorieansicht

Man stelle sich eine Seite vor, die zu einer angegebenen Kategorie-ID den Kategorie-Titel anzeigt. Der Abruf läuft nach dem Schema page.php?catid=3, der Code sieht wie folgt aus:

<?php $conn = new MySQLi("localhost", "root", "", "userdb");  $sql = "SELECT title FROM category WHERE catid = ".$_GET['id']; $res = $conn->query($sql);  while ($rec = $res->fetch_assoc()) { 	print $rec['title']; } 

Ein Angreifer könnte durch den Aufruf von page.php?id=1 UNION SELECT password AS title FROM users mal wieder SQL einschleusen. Damit sieht die Abfrage wie folgt aus:

SELECT title FROM category WHERE catid = 1 UNION SELECT password AS title FROM users 

Damit werden User-Passwörter gleich zur Kategorie mit dazugeliefert – Natürlich muss der Angreifer hier etwas umherexperimentieren, um die korrekten Feld-Namen und Tabellennamen ausfindig zu machen.

Was kann man gegen SQL-Injection tun

Die wirkungsvollste Waffe sind prepared Statements. Diese definieren Platzhalter für erwarteten Input samt erwartetem Datentyp für diesen Platzhalter. So könnte beim Beispiel der Kategorieanzeige von oben kein String eingeschleust werden, weil wir eine Zahl als Datentyp erwarten. Bezogen auf PHP empfiehlt es sich, mit PDO oder mysqli zu arbeiten, die prepared Statements unterstützen. Falls noch wer mit „nacktem“ MySQL arbeitet, sei zu mysql_real_escape_string() geraten. Am Beispiel von mysqli würde eine „Entschärfung“ des ersten Beispiels von oben (Login-Seite) wie folgt aussehen:

$stmt = $conn->prepare("SELECT COUNT(*) AS c FROM users WHERE username=? AND password=?"); //placeholders! $stmt->bind_param('ss', $_POST['username'],$_POST['password']); //two strings are expected -> 'ss' $stmt->bind_result($count); //we expect the result in $count $stmt->execute(); $stmt->fetch(); $valid = ($count == 1); 

Mysqli kümmert sich dann auch freundlicherweise ums korrekte entschärfen der Strings, sodass es keine sql-injection-Möglichkeit mehr gibt. Abschließend möchte ich noch zur deutschen Wikipedia raten, die hier noch weitere schöne Beispielattacken aufführt.

Weitere Teile der Serie