[フレーム]

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

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.

Embed presentation

Downloaded 185 times
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

More Related Content

Open Day Presentation ENG 2016
PDF
Open Day Presentation ENG 2016
Oracle - SQL-PL/SQL context switching
PPT
Oracle - SQL-PL/SQL context switching
plsql.ppt
PPT
plsql.ppt
Web ARChive (WARC) File Format
PDF
Web ARChive (WARC) File Format
Getting started with agile database migrations for java flywaydb
PPTX
Getting started with agile database migrations for java flywaydb
A tutorial on C++ Programming
PDF
A tutorial on C++ Programming
05_AP_GP_HP (1).pdf
PDF
Displaying information within a window.68
PPT
Displaying information within a window.68
Open Day Presentation ENG 2016
Open Day Presentation ENG 2016
Oracle - SQL-PL/SQL context switching
Oracle - SQL-PL/SQL context switching
plsql.ppt
plsql.ppt
Web ARChive (WARC) File Format
Web ARChive (WARC) File Format
Getting started with agile database migrations for java flywaydb
Getting started with agile database migrations for java flywaydb
A tutorial on C++ Programming
A tutorial on C++ Programming
05_AP_GP_HP (1).pdf
Displaying information within a window.68
Displaying information within a window.68

What's hot

Asp objects
PPTX
Asp objects
Presentation of awk
PPTX
Presentation of awk
SystemVerilog Assertion.pptx
PPTX
SystemVerilog Assertion.pptx
Creating an 86,000 Hour Speech Dataset with Apache Spark and TPUs
PDF
Creating an 86,000 Hour Speech Dataset with Apache Spark and TPUs
Oracle: Cursors
PPTX
Oracle: Cursors
Programming in c#
PPT
Programming in c#
Los scripts de linux
PPT
Los scripts de linux
Android Architecture.pptx
PPTX
Android Architecture.pptx
MySQL Views
PPT
MySQL Views
Validation Controls in asp.net
PPTX
Validation Controls in asp.net
Aircraft maintenance program
PPTX
Aircraft maintenance program
Docker Hub: Past, Present and Future by Ken Cochrane & BC Wong
PPTX
Docker Hub: Past, Present and Future by Ken Cochrane & BC Wong
Principles of flight
PPT
Principles of flight
Keeping a Secret with HashiCorp Vault
PPTX
Keeping a Secret with HashiCorp Vault
Stored procedure
PPTX
Mechanism Of Polymorphic And Metamorphic Virus
PDF
Mechanism Of Polymorphic And Metamorphic Virus
Flyway
PDF
Shorten Device Boot Time for Automotive IVI and Navigation Systems
PDF
Shorten Device Boot Time for Automotive IVI and Navigation Systems
Asp objects
Asp objects
Presentation of awk
Presentation of awk
SystemVerilog Assertion.pptx
SystemVerilog Assertion.pptx
Creating an 86,000 Hour Speech Dataset with Apache Spark and TPUs
Creating an 86,000 Hour Speech Dataset with Apache Spark and TPUs
Oracle: Cursors
Oracle: Cursors
Programming in c#
Programming in c#
Los scripts de linux
Los scripts de linux
Android Architecture.pptx
Android Architecture.pptx
MySQL Views
MySQL Views
Validation Controls in asp.net
Validation Controls in asp.net
Aircraft maintenance program
Aircraft maintenance program
Docker Hub: Past, Present and Future by Ken Cochrane & BC Wong
Docker Hub: Past, Present and Future by Ken Cochrane & BC Wong
Principles of flight
Principles of flight
Keeping a Secret with HashiCorp Vault
Keeping a Secret with HashiCorp Vault
Stored procedure
Mechanism Of Polymorphic And Metamorphic Virus
Mechanism Of Polymorphic And Metamorphic Virus
Flyway
Shorten Device Boot Time for Automotive IVI and Navigation Systems
Shorten Device Boot Time for Automotive IVI and Navigation Systems

Viewers also liked

Ms Sql Server
PPTX
Ms Sql Server
Excel Zaawansowany - Lekcja 3
PPTX
Excel Zaawansowany - Lekcja 3
Tester Warszawa
PDF
Tester Warszawa
Jerzy proficz -_programowanie_w_java
PDF
Jerzy proficz -_programowanie_w_java
Programowanie w języku Scala
PPTX
Programowanie w języku Scala
Crowdsourcing testowania aplikacji i serwisów webowych, czyli testowanie 2.0
PDF
Crowdsourcing testowania aplikacji i serwisów webowych, czyli testowanie 2.0
Wprowadzenie do C# i platformy .NET
PPTX
Wprowadzenie do C# i platformy .NET
Kurs MySQL i SQL, bazy danych - prezentacja ppt, pdf, porady, trening, kurs i...
PPT
Kurs MySQL i SQL, bazy danych - prezentacja ppt, pdf, porady, trening, kurs i...
Przetestuj swoje CV
PDF
Przetestuj swoje CV
Refaktoryzacja kodu w języku PHP
PPTX
Refaktoryzacja kodu w języku PHP
Matryca śledzenia - Traceability Matrix
PPTX
Matryca śledzenia - Traceability Matrix
Grywalizacja (gamification) w testowaniu
PPT
Grywalizacja (gamification) w testowaniu
JavaStart - kurs Java Podstawy
PPTX
JavaStart - kurs Java Podstawy
Tester.pl - Numer 4
PDF
ISTQB REX BLACK book
PDF
ISTQB REX BLACK book
Ms Sql Server
Ms Sql Server
Excel Zaawansowany - Lekcja 3
Excel Zaawansowany - Lekcja 3
Tester Warszawa
Tester Warszawa
Jerzy proficz -_programowanie_w_java
Jerzy proficz -_programowanie_w_java
Programowanie w języku Scala
Programowanie w języku Scala
Crowdsourcing testowania aplikacji i serwisów webowych, czyli testowanie 2.0
Crowdsourcing testowania aplikacji i serwisów webowych, czyli testowanie 2.0
Wprowadzenie do C# i platformy .NET
Wprowadzenie do C# i platformy .NET
Kurs MySQL i SQL, bazy danych - prezentacja ppt, pdf, porady, trening, kurs i...
Kurs MySQL i SQL, bazy danych - prezentacja ppt, pdf, porady, trening, kurs i...
Przetestuj swoje CV
Przetestuj swoje CV
Refaktoryzacja kodu w języku PHP
Refaktoryzacja kodu w języku PHP
Matryca śledzenia - Traceability Matrix
Matryca śledzenia - Traceability Matrix
Grywalizacja (gamification) w testowaniu
Grywalizacja (gamification) w testowaniu
JavaStart - kurs Java Podstawy
JavaStart - kurs Java Podstawy
Tester.pl - Numer 4
ISTQB REX BLACK book
ISTQB REX BLACK book

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

"Jak ocalić swoje dane przed SQL injection?" - Krzysztof Kotowicz na KrakSpot...
PDF
"Jak ocalić swoje dane przed SQL injection?" - Krzysztof Kotowicz na KrakSpot...
Jak ocalić swoje dane przed SQL injection?
PDF
Jak ocalić swoje dane przed SQL injection?
Jak włamałem się do banku
PDF
Jak włamałem się do banku
Sql z perspektywy hakera czy twoje dane są bezpieczne ? - Sqlday 2016 Wrocław
PDF
Sql z perspektywy hakera czy twoje dane są bezpieczne ? - Sqlday 2016 Wrocław
Praktyczne ataki na aplikacje webowe (TAPT 2015)
PPTX
Praktyczne ataki na aplikacje webowe (TAPT 2015)
Owasp Top10 2010 RC1 PL
PDF
Owasp Top10 2010 RC1 PL
Zhakuj swojego Wordpressa, WordUP Trojmiasto
ODP
Zhakuj swojego Wordpressa, WordUP Trojmiasto
Testowanie poziomu bezpieczeństwa aplikacji internetowych
PDF
Testowanie poziomu bezpieczeństwa aplikacji internetowych
Owasp top 10 2010 final PL Beta
PPTX
Owasp top 10 2010 final PL Beta
Hackowanie webaplikacji – ofensywa programisty na przykładzie OWASP TOP 10
PPTX
Hackowanie webaplikacji – ofensywa programisty na przykładzie OWASP TOP 10
10 przykazań bezpiecznego programowania
PPTX
10 przykazań bezpiecznego programowania
4Developers 2015: 10 przykazań bezpiecznego kodowania - Wojciech Dworakowski
PPTX
4Developers 2015: 10 przykazań bezpiecznego kodowania - Wojciech Dworakowski
Co warto wiedzieć o bazach danych
PPSX
Co warto wiedzieć o bazach danych
Wybrane podatności aplikacji webowych - Michał Sajdak
PDF
Wybrane podatności aplikacji webowych - Michał Sajdak
PHP, MySQL i Apache dla każdego. Wydanie II
PDF
PHP, MySQL i Apache dla każdego. Wydanie II
Bezpieczenstwo Portali Spolecznosciowych W Ujeciu Robakow Web 20 Pingwinaria2009
PDF
Bezpieczenstwo Portali Spolecznosciowych W Ujeciu Robakow Web 20 Pingwinaria2009
4Developers 2015: Frameworki jee vs cross-site scripting (xss) - Piotr Bucki
PDF
4Developers 2015: Frameworki jee vs cross-site scripting (xss) - Piotr Bucki
Bezpieczeństwo aplikacji czy musi być aż tak źle
PPTX
Bezpieczeństwo aplikacji czy musi być aż tak źle
4Developers 2015: Wybrane podatności w aplikacjach webowych - Michał Sajdak
PDF
4Developers 2015: Wybrane podatności w aplikacjach webowych - Michał Sajdak
Drobne błędy w portalach WWW -- prawdziwe studium przypadku
PDF
Drobne błędy w portalach WWW -- prawdziwe studium przypadku
"Jak ocalić swoje dane przed SQL injection?" - Krzysztof Kotowicz na KrakSpot...
"Jak ocalić swoje dane przed SQL injection?" - Krzysztof Kotowicz na KrakSpot...
Jak ocalić swoje dane przed SQL injection?
Jak ocalić swoje dane przed SQL injection?
Jak włamałem się do banku
Jak włamałem się do banku
Sql z perspektywy hakera czy twoje dane są bezpieczne ? - Sqlday 2016 Wrocław
Sql z perspektywy hakera czy twoje dane są bezpieczne ? - Sqlday 2016 Wrocław
Praktyczne ataki na aplikacje webowe (TAPT 2015)
Praktyczne ataki na aplikacje webowe (TAPT 2015)
Owasp Top10 2010 RC1 PL
Owasp Top10 2010 RC1 PL
Zhakuj swojego Wordpressa, WordUP Trojmiasto
Zhakuj swojego Wordpressa, WordUP Trojmiasto
Testowanie poziomu bezpieczeństwa aplikacji internetowych
Testowanie poziomu bezpieczeństwa aplikacji internetowych
Owasp top 10 2010 final PL Beta
Owasp top 10 2010 final PL Beta
Hackowanie webaplikacji – ofensywa programisty na przykładzie OWASP TOP 10
Hackowanie webaplikacji – ofensywa programisty na przykładzie OWASP TOP 10
10 przykazań bezpiecznego programowania
10 przykazań bezpiecznego programowania
4Developers 2015: 10 przykazań bezpiecznego kodowania - Wojciech Dworakowski
4Developers 2015: 10 przykazań bezpiecznego kodowania - Wojciech Dworakowski
Co warto wiedzieć o bazach danych
Co warto wiedzieć o bazach danych
Wybrane podatności aplikacji webowych - Michał Sajdak
Wybrane podatności aplikacji webowych - Michał Sajdak
PHP, MySQL i Apache dla każdego. Wydanie II
PHP, MySQL i Apache dla każdego. Wydanie II
Bezpieczenstwo Portali Spolecznosciowych W Ujeciu Robakow Web 20 Pingwinaria2009
Bezpieczenstwo Portali Spolecznosciowych W Ujeciu Robakow Web 20 Pingwinaria2009
4Developers 2015: Frameworki jee vs cross-site scripting (xss) - Piotr Bucki
4Developers 2015: Frameworki jee vs cross-site scripting (xss) - Piotr Bucki
Bezpieczeństwo aplikacji czy musi być aż tak źle
Bezpieczeństwo aplikacji czy musi być aż tak źle
4Developers 2015: Wybrane podatności w aplikacjach webowych - Michał Sajdak
4Developers 2015: Wybrane podatności w aplikacjach webowych - Michał Sajdak
Drobne błędy w portalach WWW -- prawdziwe studium przypadku
Drobne błędy w portalach WWW -- prawdziwe studium przypadku

More from Krzysztof Kotowicz

Trusted Types - Securing the DOM from the bottom up (JSNation Amsterdam)
PDF
Trusted Types - Securing the DOM from the bottom up (JSNation Amsterdam)
Trusted Types @ W3C TPAC 2018
PDF
Trusted Types @ W3C TPAC 2018
Trusted Types and the end of DOM XSS
PDF
Trusted Types and the end of DOM XSS
Biting into the forbidden fruit. Lessons from trusting Javascript crypto.
PDF
Biting into the forbidden fruit. Lessons from trusting Javascript crypto.
Hacking HTML5 offensive course (Zeronights edition)
PDF
Hacking HTML5 offensive course (Zeronights edition)
I'm in ur browser, pwning your stuff - Attacking (with) Google Chrome Extensions
PDF
I'm in ur browser, pwning your stuff - Attacking (with) Google Chrome Extensions
HTML5: Atak i obrona
PDF
HTML5: Atak i obrona
I'm in your browser, pwning your stuff
PDF
I'm in your browser, pwning your stuff
Advanced Chrome extension exploitation
PDF
Advanced Chrome extension exploitation
Html5: Something wicked this way comes (Hack in Paris)
PDF
Html5: Something wicked this way comes (Hack in Paris)
Something wicked this way comes - CONFidence
PDF
Something wicked this way comes - CONFidence
Html5: something wicked this way comes - HackPra
PDF
Html5: something wicked this way comes - HackPra
Html5: something wicked this way comes
PDF
Html5: something wicked this way comes
Creating, obfuscating and analyzing malware JavaScript
PDF
Creating, obfuscating and analyzing malware JavaScript
Tworzenie, zaciemnianie i analiza złośliwego kodu JavaScript
PDF
Tworzenie, zaciemnianie i analiza złośliwego kodu JavaScript
SQL Injection: complete walkthrough (not only) for PHP developers
PDF
SQL Injection: complete walkthrough (not only) for PHP developers
Trusted Types - Securing the DOM from the bottom up (JSNation Amsterdam)
Trusted Types - Securing the DOM from the bottom up (JSNation Amsterdam)
Trusted Types @ W3C TPAC 2018
Trusted Types @ W3C TPAC 2018
Trusted Types and the end of DOM XSS
Trusted Types and the end of DOM XSS
Biting into the forbidden fruit. Lessons from trusting Javascript crypto.
Biting into the forbidden fruit. Lessons from trusting Javascript crypto.
Hacking HTML5 offensive course (Zeronights edition)
Hacking HTML5 offensive course (Zeronights edition)
I'm in ur browser, pwning your stuff - Attacking (with) Google Chrome Extensions
I'm in ur browser, pwning your stuff - Attacking (with) Google Chrome Extensions
HTML5: Atak i obrona
HTML5: Atak i obrona
I'm in your browser, pwning your stuff
I'm in your browser, pwning your stuff
Advanced Chrome extension exploitation
Advanced Chrome extension exploitation
Html5: Something wicked this way comes (Hack in Paris)
Html5: Something wicked this way comes (Hack in Paris)
Something wicked this way comes - CONFidence
Something wicked this way comes - CONFidence
Html5: something wicked this way comes - HackPra
Html5: something wicked this way comes - HackPra
Html5: something wicked this way comes
Html5: something wicked this way comes
Creating, obfuscating and analyzing malware JavaScript
Creating, obfuscating and analyzing malware JavaScript
Tworzenie, zaciemnianie i analiza złośliwego kodu JavaScript
Tworzenie, zaciemnianie i analiza złośliwego kodu JavaScript
SQL Injection: complete walkthrough (not only) for PHP developers
SQL Injection: complete walkthrough (not only) for PHP developers

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

  • 1.
    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
  • 2.
    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
  • 3.
    Omawiane bazy danych (RDBMS)  MySQL  Oracle  MS SQL Server  W mniejszym stopniu: • PostgreSQL • SQLite OWASP 3
  • 4.
    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
  • 5.
    Co to jest SQL injection? OWASP 5
  • 6.
    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
  • 7.
    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
  • 8.
  • 9.
    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
  • 10.
    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
  • 11.
  • 12.
    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
  • 13.
    Jak się bronić? Prepared statements OWASP 13
  • 14.
    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
  • 15.
    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
  • 16.
    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
  • 17.
    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
  • 18.
    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
  • 19.
    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
  • 20.
    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
  • 21.
    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
  • 22.
    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
  • 23.
    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
  • 24.
  • 25.
    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
  • 26.
    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
  • 27.
    NIE OWASP
  • 28.
    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
  • 29.
    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
  • 30.
    PRAWIE OWASP
  • 31.
    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
  • 32.
    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
  • 33.
    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
  • 34.
    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
  • 35.
    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
  • 36.
    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
  • 37.
    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
  • 38.
    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
  • 39.
    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
  • 40.
    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
  • 41.
    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
  • 42.
    Jak się bronić? Procedury składowane OWASP 42
  • 43.
    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
  • 44.
    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
  • 45.
    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
  • 46.
    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
  • 47.
    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
  • 48.
    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
  • 49.
    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
  • 50.
    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
  • 51.
    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
  • 52.
    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
  • 53.
    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
  • 54.
    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
  • 55.
    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
  • 56.
    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
  • 57.
    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
  • 58.
    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
  • 59.
    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
  • 60.
    Jak się bronić? Metody uzupełniające OWASP 60
  • 61.
    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
  • 62.
    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
  • 63.
    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
  • 64.
    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

Editor's Notes

  • #29 Sprawdzic ansi mode
  • #51 pO tym dodac slajd, jak wywolac procedure w SQL (call / exec)

AltStyle によって変換されたページ (->オリジナル) /