• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Kompletny przewodnik po SQL injection dla developerów PHP (i nie tylko)
 

Kompletny przewodnik po SQL injection dla developerów PHP (i nie tylko)

on

  • 15,816 views

W trakcie prezentacji zademonstrujemy szkody, na jesteście narażeni nie myśląc o SQL injection. Dowiecie się, jak się przed nim bronić - zarówno w teorii, jak i na konkretnych przykładach. ...

W trakcie prezentacji zademonstrujemy szkody, na jesteście narażeni nie myśląc o SQL injection. Dowiecie się, jak się przed nim bronić - zarówno w teorii, jak i na konkretnych przykładach. Nauczymy się pisać bezpiecznie w PHP 5 - sprawdzimy Zend Framework i Symfony, przenalizujemy Propel, Doctrine, PDO i mdb2. Omówimy wszystkie kruczki i różnice między różnymi systemami baz danych (Oracle, MS SQL Server, MySQL) oraz nauczymy się pisać procedury składowane odporne na SQL injection.

Statistics

Views

Total Views
15,816
Views on SlideShare
10,619
Embed Views
5,197

Actions

Likes
7
Downloads
162
Comments
1

13 Embeds 5,197

http://niebezpiecznik.pl 3988
http://blog.kotowicz.net 1020
http://www.slideshare.net 69
http://static.slidesharecdn.com 57
http://zagorski.im.pwr.wroc.pl 18
http://www.linkedin.com 16
http://www.sfexception.com 14
http://www.imagineblog.pl 7
http://translate.googleusercontent.com 3
url_unknown 2
http://webcache.googleusercontent.com 1
http://translate.yandex.net 1
https://www.linkedin.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Sprawdzic ansi mode
  • pO tym dodac slajd, jak wywolac procedure w SQL (call / exec)

Kompletny przewodnik po SQL injection dla developerów PHP (i nie tylko) Kompletny przewodnik po SQL injection dla developerów PHP (i nie tylko) Presentation Transcript

  • Kompletny przewodnik po SQL injection dla developerów PHP (i nie tylko) Krzysztof Kotowicz PHP Developer http://web.eskot.pl OWASP Medycyna Praktyczna krzysztof@kotowicz.net 10.03.2010 Copyright © The OWASP Foundation Permission is granted to copy, distribute and/or modify this document under the terms of the OWASP License. The OWASP Foundation http://www.owasp.org
  • Plan prezentacji  Co to jest SQL injection?  Dlaczego SQL injection jest groźne (demo)?  Jak się bronić? • Prepared statements • Escape'owanie • Procedury składowane • Metody uzupełniające  Podsumowanie OWASP 2
  • Omawiane bazy danych (RDBMS)  MySQL  Oracle  MS SQL Server  W mniejszym stopniu: • PostgreSQL • SQLite OWASP 3
  • Omawiane projekty PHP  PDO – PHP data objects • Wspólny interfejs dla różnych RDBMS  Doctrine 1.2 • ORM (Object Relational Mapper) używany m.in. we frameworku Symfony  Propel 1.4 • ORM konkurencyjny dla Doctrine • Używany we frameworku Symfony  Zend Framework 1.10 • Popularny framework MVC dla PHP  MDB2 2.4.1 • Warstwa abstrakcji bazy danych (DBAL) • Dystrybuowany przez PEAR OWASP 4
  • Co to jest SQL injection? OWASP 5
  • SQL injection – krótka definicja Jest to rodzaj ataku na aplikacje internetowe. Polega na tym, że dane od użytkownika pochodzące z: URL: www.example.com?id=1 Formularzy: email=a@example.com Innych elementów: np. cookie, nagłówki HTTP zostają zmanipulowane tak, że w podatnej aplikacji zostaje wykonane „wstrzyknięte” przez atakującego polecenie SQL. OWASP 6
  • Przykład – formularz logowania SELECT * FROM users WHERE login = '{$login}' and password_hash = MD5('{$password}') $login = "' or 1=1 -- "; $password = "dowolne"; // zamierzalismy osiagnac to (kod dane) SELECT * FROM users WHERE login = '' or 1=1 -- ' and password_hash = MD5('dowolne') // serwer interpretuje to tak SELECT * FROM users WHERE login = '' or 1=1 -- ' and password_hash = MD5('dowolne') Użytkownik jest zalogowany bez znajomości loginu ani hasła OWASP 7
  • Dlaczego jest groźne? DEMO OWASP 8
  • Czym grozi podatność na SQL injection?  Nieuprawniony dostęp do aplikacji  Dostęp do całej zawartości bazy / baz na serwerze  Denial of service  Możliwość modyfikacji danych w bazie  Przeczytanie / zapisanie pliku na serwerze  Wykonanie kodu na serwerze OWASP 9
  • Kilka faktów  Podatności na injection na pierwszym miejscu OWASP Top 10 2010 RC  Odpowiada za 40–60% przypadków wycieku danych [1] [2]  Obecne techniki ataku są bardzo zaawansowane i często automatyzowane • Podatność nie tylko w części WHERE • Czasem celem jest zepsucie zapytania  Codziennie znajdowane podatności, nawet w nowych aplikacjach OWASP 10
  • Jak się bronić? OWASP 11
  • Jak się bronić przed SQL injection?  Źródło podatności - łączenie kodu z danymi SELECT * FROM users WHERE login = 'login' Metody obrony Oddzielenie kodu od danych prepared statements stored procedures Escape'owanie danych OWASP 12
  • Jak się bronić? Prepared statements OWASP 13
  • Prepared statements – zasada działania 1. Przygotowujemy polecenie SQL (string) W miejsce danych wstawiamy znaczniki WHERE a = ? ... WHERE a = :col 2. Przesyłamy polecenie na serwer PREPARE 3. Podajemy zestaw danych do polecenia 4. Wykonujemy polecenie EXECUTE 5. Odbieramy rezultat 3, 4, 5 można powtarzać... 6. Czyścimy polecenie OWASP 14
  • Prepared statements - przykład  Przykład działania (PDO) // przygotowujemy zapytanie $stmt = $dbh->prepare("INSERT INTO SUMMARIES (name, sum) VALUES (:name, :sum)"); // podajemy wartosci zmiennych – RAZEM Z TYPAMI! $stmt->bindParam(':name', $name, PDO::PARAM_STR); $stmt->bindParam(':sum', $sum, PDO::PARAM_INT); // podajemy wartości zmiennych $name = 'something'; $value = 1234; // wykonujemy zapytanie $stmt->execute(); $stmt = null; //zwalniamy pamiec OWASP 15
  • Prepared statements - zalety  Polecenia SQL są całkowicie oddzielone od przetwarzanych danych  Brak możliwości wstrzyknięcia kodu SQL  Polecenie SQL jest przez serwer kompilowane tylko raz – potencjalne zwiększenie wydajności zapytań $stmt->bindParam(':name', $name, PDO::PARAM_STR); $stmt->bindParam(':sum', $sum, PDO::PARAM_INT); // petla po danych... foreach ($do_bazy as $name => $value) { $stmt->execute(); } OWASP 16
  • Prepared statements - uwagi  Nie wszystkie typy poleceń można parametryzować  Nie w każdym miejscu polecenia można wstawić parametr -- blad SELECT * FROM :tabela SELECT :funkcja(:kolumna) FROM :widok -- nie tego się spodziewacie SELECT * FROM tabela WHERE :kolumna = 1 SELECT * FROM tabela GROUP BY :kolumna  Samo ich użycie nie wymusza stosowania parametrów  Czasem są emulowane (ale to dobrze!) OWASP 17
  • Prepared statements w Doctrine  Używa PDO (emulacja dla Oracle) i prepared statements  Zamiast SQL używa własnego języka – DQL $q = Doctrine_Query::create() ->select('u.id') ->from('User u') ->where('u.login = ?', ‘mylogin'); echo $q->getSqlQuery(); // SELECT u.id AS u__id FROM user u // WHERE (u.login = ?) $users = $q->execute(); OWASP 18
  • Prepared statements w Doctrine cd.  Wciąż można „wpaść” $q = Doctrine_Query::create() ->update('Account') ->set('amount', 'amount + 200') ->where("id > {$_GET['id']}");  Trzeba poprawić na: ->where("id > ?", (int) $_GET['id']);  NIGDY nie umieszczaj danych wejściowych bezpośrednio w treści zapytań OWASP 19
  • Prepared statements w Propel  Podobnie jak Doctrine, oparty na PDO // poprzez Criteria $c = new Criteria(); $c->add(AuthorPeer::FIRST_NAME, "Karl"); $authors = AuthorPeer::doSelect($c); // poprzez customowy SQL (czasem jest latwiej) $pdo = Propel::getConnection(BookPeer::DATABASE_NAME); $sql = "SELECT * FROM skomplikowany_sql JOIN cos_jeszcze_gorszego USING cos_tam WHERE kolumna = :col)”; $stmt = $pdo->prepare($sql); $stmt->execute(array('col' => 'Bye bye SQLi!'); OWASP 20
  • Prepared statements w Zend Framework  PDO (+ mysqli + oci8 + sqlsrv) // prepare + execute $stmt = $db->prepare('INSERT INTO server (key, value) VALUES (:key,:value)'); $stmt->bindParam('key', $k); $stmt->bindParam('value', $v); foreach ($_SERVER as $k => $v) $stmt->execute(); // prepare + execute w jednym kroku $stmt = $db->query('SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?', array('goofy', 'FIXED')); while ($row = $stmt->fetch()) echo $row['bug_description']; OWASP 21
  • MDB2  Oparty na konkretnych sterownikach baz danych (mysql, oci8, mssql, ...)  Emuluje PS, jeśli baza ich nie wspiera $types = array('integer', 'text', 'text'); $stmt = $mdb2->prepare('INSERT INTO numbers VALUES (:id, :name, :lang)', $types); $data = array('id' => 1, 'name' => 'one', 'lang' => 'en'); $affectedRows = $stmt->execute($data); $stmt->free(); OWASP 22
  • Prepared statements - podsumowanie  Oferują bardzo dobre zabezpieczenie (jeśli użyte poprawnie)  Łatwe w użyciu, niewielkie zmiany w kodzie  Dobre wsparcie we frameworkach  Mają swoje ograniczenia  Czasem muszą być uzupełniane innymi metodami zabezpieczeń OWASP 23
  • Jak się bronić? Escape'owanie danych OWASP 24
  • Escape'owanie – zasada działania  Dane i polecenia wciąż trzymamy w jednej zmiennej, ale zabezpieczamy je  Liczby • Rzutowanie na (int) / (float) – nie is_numeric [1]!  Teksty - zwykle otoczone apostrofami: ' .. WHERE pole = 'DANE TEKSTOWE' AND ... • Jeśli w tekście również są apostrofy, trzeba je odróżnić od apostrofu „kończącego” • Apostrof wewnątrz danych jest poprzedzany znakiem specjalnym, np. "" • Reguły escape'owania zależą od kontekstu! OWASP 25
  • Escape'owanie – kontekst addslashes() Returns a string with backslashes before characters that need to be quoted in database queries etc. These characters are single quote ('), double quote ("), backslash () and NUL (the NULL byte). / Źródło: php.net manual / $user = addslashes($_GET['u']); $pass = addslashes($_GET['p']); $sql = "SELECT * FROM users WHERE username = '{$user}' AND password = '{$pass}'"; $ret = exec_sql($sql);  Czy jesteś bezpieczny? OWASP 26
  • NIE OWASP
  • Escape'owanie – kontekst cd.  Różne RDBMS mają różne sposoby escape'owania danych (zależy to też od konfiguracji bazy)  addslashes() tylko „przypadkiem” działa dla MySQL RBDMS Funkcja mam 'apostrofy' PDO $pdo->quote($val, $type) n/d (różnie) MySQL (mysql) mysql_real_escape_string mam 'apostrofy' MySQL (mysqli) mysqli_real_escape_string mam 'apostrofy' Oracle (oci8) n/d - str_replace() mam ''apostrofy'' SQLite sqlite_escape_string mam ''apostrofy'' MS SQL (mssql) n/d - str_replace() mam ''apostrofy'' PostgreSQL pg_escape_string() mam ''apostrofy'' OWASP 28
  • Escape'owanie – kontekst cd. // SELECT * FROM users WHERE username = // '{$user}' AND password = '{$pass}' $_GET['u'] = "cokolwiek'"; $_GET['p'] = " or 1=1 -- "; // MySQL widzi to tak: SELECT * FROM users WHERE username = 'cokolwiek'' AND password = ' or 1=1 -- ' // SQLite / MS SQL / Oracle / PostgreSQL - tak: SELECT * FROM users WHERE username = 'cokolwiek'' AND password = ' or 1=1 -- '  Nie używaj addslashes(), używaj funkcji konkretnej bazy  Czy teraz jesteś bezpieczny? OWASP 29
  • PRAWIE OWASP
  • Pułapki escape'owania – zestawy znaków  Błędy wykryte w 2006 r. w PostgreSQL i MySQL [1] [2]  W niektórych wielobajtowych zestawach znaków pomimo escape’owania można doprowadzić do SQL injection  zostaje „połknięty” przez wielobajtowy znak  Przykład: • BF 27 [ ¬ ' ]  BF 5C 27 [ ¬ ' ] • Pierwsze dwa bajty to w charsecie GBK znak ¿ • Serwer „zobaczy” ciąg ¿' OWASP 31
  • Pułapki escape'owania – zestawy znaków  Podatne są różne azjatyckie zestawy znaków  Na szczęście nie UTF-8!  W PostgreSQL zastosowano escape'owanie poprzez '' (zamiast ')  W mysql_real_escape_string() zastosowano uwzględnianie bieżącego zestawu znaków • Nie zawsze zadziała! [1] [2]  Kontekst to również zestaw znaków OWASP 32
  • Escape'owanie – nazwy obiektów  Nazwy kolumn, tabel, baz • Nie ma dobrej ogólnej metody na ich escape'owanie • W różnych bazach różne listy słów zarezerwowanych, różne długości nazw itp. Jeśli musisz pobierać te nazwy od użytkownika, zastosuj whitelisting (blacklisting w ostateczności) OWASP 33
  • Escape'owanie – nazwy obiektów cd.  Przykład – sortowanie po kolumnie  Jest podatność w $order, ale nie możesz użyć escape'owania $cat_id = (int) $_GET['cid']; $order = $_GET['column']; $stmt = $pdo->prepare("SELECT * FROM products WHERE cid = :cid ORDER BY $order"); $stmt->bindParam(':cid', $cat_id, PDO::PARAM_INT); if ($stmt->execute()) { ... } OWASP 34
  • Escape'owanie – nazwy obiektów cd.  Whitelisting $columns = array( // lista dozwolonych kolumn 'product_name','cid','price', ); if (!in_array($order, $columns, true)) $order = 'product_name'; // wartosc domyslna  Blacklisting // tylko znaki a-z i _ $order = preg_replace('/[^a-z_]/', '', $order); // max 40 znakow $order = substr($order, 0, 40); OWASP 35
  • Escape'owanie w PDO  PDO::quote($value, $type, $len)  Długość i typ bywają ignorowane! • Liczby najlepiej rzutuj na (int), (float) • Teksty – obcinaj ręcznie $quoted = $pdo->quote($input, PDO::PARAM_STR, 40); OWASP 36
  • Escape'owanie w Doctrine  Uwaga na Doctrine'owe quote()! $q = Doctrine_Query::create(); // nie tak!!! $quoted = $q->getConnection()->quote($input, 'text'); $q->update('User')->set('username', $quoted); // quote() zamienia ' na '' - exploit (MySQL): $input = 'anything' where 1=1 -- '; // trzeba escape'owac poprzez PDO - getDbh(): $quoted = $q->getConnection() ->getDbh() ->quote($input, PDO::PARAM_STR); // 'anything ' where 1=1 -- ' OWASP 37
  • Escape'owanie w Propel  Poprzez PDO::quote() $pdo = Propel::getConnection(UserPeer::DATABASE_NAME); $c = new Criteria(); $c->add(UserPeer::PASSWORD, "MD5(".UserPeer::PASSWORD.") " ." = " . $pdo->quote($password), Criteria::CUSTOM); OWASP 38
  • Escape'owanie w Zend Framework  Funkcje quote(), quoteInto() $name = $db->quote("O'Reilly"); // 'O'Reilly' // uproszczone escape'owanie dla jednej zmiennej $sql = $db->quoteInto("SELECT * FROM products WHERE product_name = ?", 'any string'); OWASP 39
  • Escape'owanie w MDB  Funkcja quote() // funkcja quote()- trzeba określić typ $query = 'INSERT INTO table (id, itemname, saved_time) VALUES (' . $mdb2->quote($id, 'integer') .', ' . $mdb2->quote($name, 'text') .', ' . $mdb2->quote($time, 'timestamp') .')'; $res = $mdb2->exec($query); OWASP 40
  • Escape'owanie danych - podsumowanie  Wydaje się proste – zastępowanie tekstu  Niestety, tylko się wydaje • Musimy znać kontekst (baza danych, charset) • Istnieją błędne implementacje  Skłania do stosowania niebezpiecznych konstrukcji • sklejanie poleceń • ignorowanie zmiennych numerycznych  Stosowanie dopuszczalne tylko, jeśli • Programujemy pod konkretną bazę • Nie ma innej możliwości OWASP 41
  • Jak się bronić? Procedury składowane OWASP 42
  • Procedury składowane  Polecenie SQL (lub seria poleceń) zostaje przeniesione na serwer bazy danych i zapisane jako procedura  Po stronie klienta procedura zostaje wywołana z określonymi parametrami (danymi) wejściowymi i wyjściowymi  W parametrach wyjściowych klient otrzymuje wyniki procedury  Dane są formalnie oddzielone od kodu  To NIE wystarcza OWASP 43
  • Procedury składowane  Przykład w MS SQL – fragment podatnej procedury CREATE PROCEDURE SP_ProductSearch @prodname varchar(400) AS DECLARE @sql nvarchar(4000) SELECT @sql = 'SELECT ProductID, ProductName, Category, Price FROM Product Where ProductName LIKE ''' + @prodname + '''' EXEC (@sql) ...  To eval() w kolejnym wcieleniu! OWASP 44
  • Procedury składowane cd.  Przykład tej samej podatności w Oracle CREATE OR REPLACE PROCEDURE SP_ProductSearch(Prodname IN VARCHAR2) AS sqltext VARCHAR2(80); BEGIN sqltext := 'SELECT ProductID, ProductName, Category, Price FROM Product WHERE ProductName LIKE ''' || Prodname || ''''; EXECUTE IMMEDIATE sqltext; ... END; OWASP 45
  • Procedury składowane – Dynamic SQL  Źródło podatności – Dynamic SQL • Dane znów „przemieszane” z kodem w jednej zmiennej, która zostaje wykonana jako polecenie SQL  Jak się obronić? • Oddziel kod od danych • Escape'uj OWASP 46
  • Procedury składowane w MS SQL  Oddzielenie danych od kodu • użyj sp_executesql razem z listą parametrów CREATE PROCEDURE SP_ProductSearch @prodname varchar(400) = NULL AS DECLARE @sql nvarchar(4000) SELECT @sql = N'SELECT ProductID, ProductName, Category, Price FROM Product Where ProductName LIKE @p' EXEC sp_executesql @sql, N'@p varchar(400)', @prodname OWASP 47
  • Procedury składowane w MS SQL cd.  Escape'owanie zmiennych tekstowych Nazwa obiektu QUOTENAME(@v) Tekst <= 128 znaków QUOTENAME(@v,'''') Tekst > 128 znaków REPLACE(@v,'''','''''')  Przykład: SET @cmd = N'select * from authors where lname=''' + REPLACE(@lname, '''', '''''') + N''''  Escape'uj tylko wtedy, kiedy musisz! (używaj sp_executesql z parametrami) OWASP 48
  • Procedury składowane w Oracle  Oracle - użyj EXECUTE IMMEDIATE .. USING CREATE OR REPLACE PROCEDURE SP_ProductSearch(Prodname IN VARCHAR2) AS sqltext VARCHAR2(80); BEGIN sqltext := 'SELECT ProductID, ProductName, Category, Price WHERE ProductName=:p'; EXECUTE IMMEDIATE sqltext USING Prodname; ... END;  Escape'owanie - pakiet DBMS_ASSERT OWASP 49
  • Procedury składowane w MySQL  Wsparcie dla Dynamic SQL tylko poprzez prepared statements  Napisanie podatnych procedur jest trudniejsze niż procedur zabezpieczonych!  Wystarczy używać placeholderów zamiast doklejać wartości zmiennych OWASP 50
  • Procedury składowane w MySQL cd.  PREPARE / EXECUTE USING / DEALLOCATE PREPARE DELIMITER $$ CREATE PROCEDURE get_users_like ( IN contains VARCHAR(40)) BEGIN SET @like = CONCAT("%", contains, "%"); SET @sql = "SELECT * FROM users WHERE uname LIKE ?"; PREPARE get_users_stmt from @sql; EXECUTE get_users_stmt USING @like; DEALLOCATE PREPARE get_users_stmt; END$$ DELIMITER ; OWASP 51
  • Procedury składowane w MySQL cd.  Lub jeszcze prościej (bezpośrednio) DELIMITER $$ CREATE PROCEDURE get_users_like ( IN contains VARCHAR(40)) BEGIN SET @like = CONCAT("%", contains, "%"); SELECT * FROM users WHERE uname LIKE @like; END$$ DELIMITER ;  Escape'owanie – funkcja QUOTE() OWASP 52
  • Procedury składowane w PHP  Różne wsparcie w zależności od RDBMS  Wsparcie zależy od konkretnego sterownika  Wspólne API (np. PDO) obsługuje tylko najprostsze wywołania • Procedura nic nie zwraca • Procedura zwraca prosty rezultat w parametrze OUT  Różna obsługa (lub brak) bardziej zaawansowanych wywołań • np. pobieranie rekordów z procedur, kursory  Wsparcie we frameworkach śladowe  Wciąż występują błędy OWASP 53
  • Procedury składowane w PDO  Wywołanie procedury // MySQL $sql = "CALL get_users_like(:contains)"; // MS SQL – EXEC get_users_like :contains $stmt = $pdo->prepare($sql); $ret = $stmt->execute(array('contains' => $input)); foreach($stmt->fetchAll() as $users) { var_dump($users); } unset($s); OWASP 54
  • Procedury składowane w Doctrine/Propel/Zend Framework  Doctrine - Brak wsparcia (użyj PDO) $pdo = Doctrine_Manager::connection()->getDbh();  Propel – jw. $pdo = Propel::getConnection(UserPeer::DATABASE_NAME);  Zend Framework – jw. $pdo = $db::getConnection(); OWASP 55
  • Procedury składowane w MDB2  Trzeba własnoręcznie escape'ować wszystkie parametry $mdb2->loadModule('Function'); $multi_query = $mdb2->setOption('multi_query', true); if (!PEAR::isError($multi_query)) { $result = $mdb2->executeStoredProc('get_users_like', array($mdb2->quote($contains, 'text'))); do { while ($row = $result->fetchRow()) { var_dump($row); } } while ($result->nextResult()); } OWASP 56
  • Procedury składowane - pułapki  Długość zmiennych CREATE PROCEDURE change_password @loginname varchar(50), @old varchar(50), @new varchar(50) AS DECLARE @command varchar(120) SET @command= 'UPDATE users SET password=' + QUOTENAME(@new, '''') + ' WHERE loginname=' + QUOTENAME(@loginname, '''') + ' AND password=' + QUOTENAME(@old, '''') EXEC (@command) GO OWASP 57
  • Procedury składowane - podsumowanie  Czasochłonne przenoszenie logiki SQL z aplikacji na serwer  Nie są łatwo przenośne pomiędzy RDBMS  Napisane bezpiecznych procedur i tak wymaga użycia prepared statements lub escape'owania danych  Źle zaimplementowane mogą zwiększyć podatność • Zarówno wywołanie procedury, jak i jej kod jest podatny • Procedura może mieć większe uprawnienia niż kod ją wywołujący  Złe wsparcie w PHP i we frameworkach OWASP 58
  • Procedury składowane - podsumowanie Mają dużo zalet poza naszym obszarem zainteresowania  Można precyzyjnie zarządzać uprawnieniami do procedur  Przydatne w wypadku stosowania różnych klientów (Java/.NET + PHP)  Mogą zwiększyć wydajność  I wiele innych... Wnioski: Pozwalają osiągnąć dobre zabezpieczenie przed SQL injection, ale przy dużych kosztach. Niezbędne jest zabezpieczanie samego kodu procedur przed SQL injection. OWASP 59
  • Jak się bronić? Metody uzupełniające OWASP 60
  • Walidacja i filtrowanie danych  Kontrola poprawności danych zewnętrznych  Odbywa się przed przetwarzaniem tych danych  Nie myl z escape'owaniem! Filter INPUT - escape OUTPUT  Osobne reguły walidacji dla każdego parametru - sprawdzaj m.in. • Typ zmiennej • Skalar / tablica • Wartości min / max • Długość danych tekstowych! [1] OWASP 61
  • Uzupełniające metody obrony Komplementarne do poprzednich!  Zasada najmniejszych uprawnień przy łączeniu się do bazy danych  Wyłączenie nieużywanych funkcji, kont, pakietów dostarczanych z bazą danych  Regularne aktualizowanie serwera bazy danych  Dobra konfiguracja PHP i bazy • magic_quotes_* = false • display_errors = false  Dobrze zaprojektowana baza danych OWASP 62
  • Podsumowanie  Zwracaj uwagę na SQL injection - pojedynczy błąd może wiele kosztować!  Preferuj rozwiązania kompleksowe - np. frameworki  Filtruj wszystkie dane wejściowe  Pamiętaj o typach i długościach zmiennych  Stosuj whitelisting zamiast blacklistingu - to drugie kiedyś zawiedzie!  Stosuj prepared statements wszędzie, gdzie możesz  Unikaj escape'owania  W procedurach składowanych uważaj na Dynamic SQL OWASP 63
  • Linki  Omawiane projekty • sqlmap.sourceforge.net • php.net/manual/en/book.pdo.php • www.doctrine-project.org • propel.phpdb.org/trac • framework.zend.com • pear.php.net/package/MDB2  O SQL injection • www.owasp.org/index.php/SQL_Injection • unixwiz.net/techtips/sql-injection.html • delicious.com/koto/sql+injection  Hack me • threats.pl/bezpieczenstwo-aplikacji-internetowych • tinyurl.com/webgoat • mavensecurity.com/dojo.php  krzysztof@kotowicz.net http://blog.kotowicz.net OWASP 64