{"id":416,"date":"2010-11-28T18:56:02","date_gmt":"2010-11-28T17:56:02","guid":{"rendered":"https:\/\/d-mueller.de\/blog\/?p=416"},"modified":"2016-01-11T23:10:35","modified_gmt":"2016-01-11T22:10:35","slug":"angriffe-auf-webanwendungen-teil-3-sql-injection","status":"publish","type":"post","link":"https:\/\/d-mueller.de\/blog\/angriffe-auf-webanwendungen-teil-3-sql-injection\/","title":{"rendered":"Angriffe auf Webanwendungen \u2013 Teil 3: SQL-Injection"},"content":{"rendered":"<h3>Vorherige Teile der Serie<\/h3>\n<ul>\n<li><a href=\"https:\/\/d-mueller.de\/blog\/angriffe-auf-webanwendungen-teil-1-xss-beispielangriff\/\">Teil 1: XSS<\/a><\/li>\n<li><a href=\"https:\/\/d-mueller.de\/blog\/angriffe-auf-webanwendungen-teil-2-session-highjacking-und-session-fixation\/\">Teil 2: Session-Highjacking und Session-Fixation<\/a><\/li>\n<\/ul>\n<p>Okay, ich sch\u00e4me mich fast, dar\u00fcber noch was zu schreiben. Man m\u00f6chte doch meinen, dass SQL Injection <b>DER<\/b> bekannteste Angriff \u00fcberhaupt ist. M\u00f6chte 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.<\/p>\n<h3>Was ist SQL-Inection?<\/h3>\n<p>Wenn ein Benutzer der Anwendung die M\u00f6glichkeit hat, selbst SQL einzuschleusen spricht man von SQL-Injection. Besonders beliebt sind (gerade in \u00e4lteren Webanwendungen) das Einschleusen von SQL per $_GET. Beispiel gef\u00e4llig?<\/p>\n<h3>Angriffsszenario 1: Der Login<\/h3>\n<p>Eigentlich das Musterbeispiel daf\u00fcr: Folgender Code wird zum validieren eines Login-Formulars verwendet:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n&lt;?php\r\n$conn = new MySQLi(&quot;localhost&quot;, &quot;root&quot;, &quot;&quot;, &quot;userdb&quot;);\r\n\r\n$sql = &quot;SELECT COUNT(*) AS c FROM users WHERE username=&#039;&quot;.$_POST[&#039;username&#039;].&quot;&#039; AND password=&#039;&quot;.$_POST[&#039;password&#039;].&quot;&#039;&quot;;\r\n$res = $conn-&gt;query($sql);\r\n$rec = $res-&gt;fetch_assoc();\r\n$valid = ($rec[&#039;c&#039;] == 1);\r\n\r\nif ($valid)\r\n{\r\n\t\/\/do session stuff...\r\n\theader(&quot;Location: profile.php&quot;);\r\n}\r\nelse\r\n{\r\n\tprint &quot;Nope, incorrect&quot;;\r\n}\r\n?&gt;\r\n<\/pre>\n<p>Das Formular (trivial) sieht so aus:<\/p>\n<pre data-enlighter-language=\"html\" class=\"EnlighterJSRAW\">\r\n&lt;form action=&quot;&lt;?php echo $_SERVER[&#039;PHP_SELF&#039;]; ?&gt;&quot; method=&quot;POST&quot;&gt;\r\n\t&lt;input type=&quot;text&quot; name=&quot;username&quot; \/&gt;\r\n\t&lt;input type=&quot;password&quot; name=&quot;password&quot; \/&gt;\r\n\t&lt;input type=&quot;submit&quot; value=&quot;Anmelden&quot; \/&gt;\r\n&lt;\/form&gt;\r\n<\/pre>\n<p>Der Benutzer tippt in beide Felder <\/p>\n<pre data-enlighter-language=\"enlighter\" class=\"EnlighterJSRAW\">&#039; OR &#039;1=1<\/pre>\n<p>, womit die SQL-Abfrage so aussieht: <\/p>\n<pre data-enlighter-language=\"sql\" class=\"EnlighterJSRAW\">SELECT COUNT(*) AS c FROM users WHERE username=&#039;&#039; OR &#039;1=1&#039; AND password=&#039;&#039; OR &#039;1=1&#039;<\/pre>\n<p>Das ist immer wahr, somit kann sich der Angreifer einloggen, ohne korrekte Zugangsdaten angegeben zu haben.<\/p>\n<h3>Angriffsszenario 1: Die Kategorieansicht<\/h3>\n<p>Man stelle sich eine Seite vor, die zu einer angegebenen Kategorie-ID den Kategorie-Titel anzeigt. Der Abruf l\u00e4uft nach dem Schema <b>page.php?catid=3<\/b>, der Code sieht wie folgt aus:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n&lt;?php\r\n$conn = new MySQLi(&quot;localhost&quot;, &quot;root&quot;, &quot;&quot;, &quot;userdb&quot;);\r\n\r\n$sql = &quot;SELECT title FROM category WHERE catid = &quot;.$_GET[&#039;id&#039;];\r\n$res = $conn-&gt;query($sql);\r\n\r\nwhile ($rec = $res-&gt;fetch_assoc())\r\n{\r\n\tprint $rec[&#039;title&#039;];\r\n}\r\n<\/pre>\n<p>Ein Angreifer k\u00f6nnte durch den Aufruf von <b>page.php?id=1 UNION SELECT password AS title FROM users<\/b> mal wieder SQL einschleusen. Damit sieht die Abfrage wie folgt aus:<\/p>\n<pre data-enlighter-language=\"sql\" class=\"EnlighterJSRAW\">\r\nSELECT title FROM category WHERE catid = 1 UNION SELECT password AS title FROM users\r\n<\/pre>\n<p>Damit werden User-Passw\u00f6rter gleich zur Kategorie mit dazugeliefert &#8211; Nat\u00fcrlich muss der Angreifer hier etwas umherexperimentieren, um die korrekten Feld-Namen und Tabellennamen ausfindig zu machen.<\/p>\n<h3>Was kann man gegen SQL-Injection tun<\/h3>\n<p>Die wirkungsvollste Waffe sind <a href=\"http:\/\/de.wikipedia.org\/wiki\/Prepared_Statement\">prepared Statements<\/a>. Diese definieren Platzhalter f\u00fcr erwarteten Input samt erwartetem Datentyp f\u00fcr diesen Platzhalter. So k\u00f6nnte beim Beispiel der Kategorieanzeige von oben kein String eingeschleust werden, weil wir eine Zahl als Datentyp erwarten. Bezogen auf PHP empfiehlt es sich, mit <a href=\"http:\/\/php.net\/manual\/de\/book.pdo.php\">PDO<\/a> oder <a href=\"http:\/\/php.net\/manual\/de\/book.mysqli.php\">mysqli<\/a> zu arbeiten, die prepared Statements unterst\u00fctzen. Falls noch wer mit &#8222;nacktem&#8220; MySQL arbeitet, sei zu <a href=\"http:\/\/php.net\/manual\/de\/function.mysql-real-escape-string.php\">mysql_real_escape_string()<\/a> geraten. Am Beispiel von mysqli w\u00fcrde eine &#8222;Entsch\u00e4rfung&#8220; des ersten Beispiels von oben (Login-Seite) wie folgt aussehen:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n$stmt = $conn-&gt;prepare(&quot;SELECT COUNT(*) AS c FROM users WHERE username=? AND password=?&quot;); \/\/placeholders!\r\n$stmt-&gt;bind_param(&#039;ss&#039;, $_POST[&#039;username&#039;],$_POST[&#039;password&#039;]); \/\/two strings are expected -&gt; &#039;ss&#039;\r\n$stmt-&gt;bind_result($count); \/\/we expect the result in $count\r\n$stmt-&gt;execute();\r\n$stmt-&gt;fetch();\r\n$valid = ($count == 1);\r\n<\/pre>\n<p>Mysqli k\u00fcmmert sich dann auch freundlicherweise ums korrekte entsch\u00e4rfen der Strings, sodass es keine sql-injection-M\u00f6glichkeit mehr gibt. Abschlie\u00dfend m\u00f6chte ich noch zur deutschen Wikipedia raten, die <a href=\"http:\/\/de.wikipedia.org\/wiki\/SQL-Injection#Vorgang\">hier<\/a> noch weitere sch\u00f6ne Beispielattacken auff\u00fchrt.<\/p>\n<h3>Weitere Teile der Serie<\/h3>\n<ul>\n<li><a href=\"https:\/\/d-mueller.de\/blog\/angriffe-auf-webanwendungen-teil-4-csrf\/\">Teil 4: CSRF<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Vorherige Teile der Serie Teil 1: XSS Teil 2: Session-Highjacking und Session-Fixation Okay, ich sch\u00e4me mich fast, dar\u00fcber noch was zu schreiben. Man m\u00f6chte doch meinen, dass SQL Injection DER bekannteste Angriff \u00fcberhaupt ist. M\u00f6chte man meinen. Bisher hat sichs &hellip; <a href=\"https:\/\/d-mueller.de\/blog\/angriffe-auf-webanwendungen-teil-3-sql-injection\/\">Weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,6,3],"tags":[],"class_list":["post-416","post","type-post","status-publish","format-standard","hentry","category-php","category-security","category-webdev"],"_links":{"self":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts\/416","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/comments?post=416"}],"version-history":[{"count":0,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts\/416\/revisions"}],"wp:attachment":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/media?parent=416"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/categories?post=416"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/tags?post=416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}