Owasp SQL Injection en 100317143725 Phpapp02
Transcript of Owasp SQL Injection en 100317143725 Phpapp02
![Page 1: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/1.jpg)
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
OWASP
http://www.owasp.org
SQL injection: complete walkthrough (not only) for PHP developers
Krzysztof Kotowicz
PHP Developer
http://web.eskot.pl
Medycyna Praktyczna
10.03.2010
![Page 2: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/2.jpg)
OWASP 2
Plan
What is SQL injection?
Why is it so dangerous (demo)?
How to defend?
• Prepared statements
• Escaping
• Stored procedures
• Additional methods
Summary
![Page 3: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/3.jpg)
OWASP 3
Discussed databases (RDBMS)
MySQL
Oracle
MS SQL Server
To some extent:
• PostgreSQL
• SQLite
![Page 4: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/4.jpg)
OWASP 4
Discussed PHP projects
PDO – PHP data objects
• Common interface for various RDBMS
Doctrine 1.2
• ORM (Object Relational Mapper) used e.g. in Symfony framework
Propel 1.4
• ORM, like Doctrine
• Used in Symfony
Zend Framework 1.10
• Popular framework MVC for PHP
MDB2 2.4.1 • Database abstraction layer (DBAL)
• Distributed through PEAR
![Page 5: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/5.jpg)
OWASP 5
What is SQL injection?
![Page 6: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/6.jpg)
OWASP 6
SQL injection – short definition
It is a kind of web application attack, where user-supplied input coming from: URL: www.example.com?id=1
Forms: [email protected]
Other elements: e.g. cookie, HTTP headers
is manipulated so that vulnerable application executes SQL commands injected by attacker.
![Page 7: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/7.jpg)
OWASP 7
Example – login form
User logs in without knowing the login nor password
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') // but server interprets it as SELECT * FROM users WHERE login = '' or 1=1 -- ' and password_hash = MD5('anything')
SELECT * FROM users WHERE login = '{$login}' and password_hash = MD5('{$password}') $login = "' or 1=1 -- "; $password = "dowolne"; // you wanted to achieve this (code \ data) SELECT * FROM users WHERE login = '' or 1=1 -- ' and password_hash = MD5('anything')
SELECT * FROM users WHERE login = '{$login}' and password_hash = MD5('{$password}') $login = "' or 1=1 -- "; $password = "anything";
SELECT * FROM users WHERE login = '{$login}' and password_hash = MD5('{$password}')
![Page 8: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/8.jpg)
OWASP 8
Why is it so dangerous?
DEMO
![Page 9: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/9.jpg)
OWASP 9
What are the possible threats?
Unauthorized access to application
Access to whole database / databases on the server
Denial of service
Database modification
Read / write files on server's filesystem
Code execution
![Page 10: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/10.jpg)
OWASP 10
A few facts
Injection vulnerabilities are the 1st on OWASP Top 10 2010 RC
SQLi is responsible for 40–60% cases of data breach [1] [2]
Modern attack techniques are advanced and automated
• Vulnerability is not only in WHERE part
• Sometimes it is enough to break a query
Vulnerabilities are found on a daily basis, even in new applications
![Page 11: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/11.jpg)
OWASP 11
How to defend?
![Page 12: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/12.jpg)
OWASP 12
How to defend against SQL injection?
Source of vulnerability is mixing code with data
Defense methods
Separating code from data
prepared statements
stored procedures
Escaping
SELECT * FROM users WHERE login = 'login'
![Page 13: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/13.jpg)
OWASP 13
How to defend?
Prepared statements
![Page 14: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/14.jpg)
OWASP 14
Prepared statements – how to use?
1. Preparing SQL command (string)
Put placeholders where data should be
2. Send command to server
3. Attach data to command
4. Execute command
5. Fetch results 3, 4, 5 could be repeated...
6. Clear the command
WHERE a = ? ... WHERE a = :col
PREPARE
EXECUTE
![Page 15: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/15.jpg)
OWASP 15
Prepared statements - example
PDO
// prepare command $stmt = $dbh->prepare("INSERT INTO SUMMARIES (name, sum) VALUES (:name, :sum)"); // attach data variables - WITH ITS TYPES! $stmt->bindParam(':name', $name, PDO::PARAM_STR); $stmt->bindParam(':sum', $sum, PDO::PARAM_INT); // bind values $name = 'something'; $value = 1234; // execute command $stmt->execute(); $stmt = null; //free memory
![Page 16: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/16.jpg)
OWASP 16
Prepared statements - advantages
Commands are completely separated from data they operate on
Injection is not possible
Command is compiled only once - potential speedup
$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(); }
![Page 17: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/17.jpg)
OWASP 17
Prepared statements - caveats
Not all commands may be parametrised
You cannot put parameters everywhere
Just using PS does not enforce using parameters in them
Sometimes they're emulated (it's a good thing!)
-- error SELECT * FROM :table SELECT :function(:column) FROM :view -- not what you expect SELECT * FROM table WHERE :column = 1 SELECT * FROM table GROUP BY :column
![Page 18: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/18.jpg)
OWASP 18
Prepared statements in Doctrine
Uses PDO (emulated for Oracle) and prepared statements
Uses own DQL language instead of SQL
$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();
![Page 19: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/19.jpg)
OWASP 19
Prepared statements in Doctrine cont.
It can still bite you
Correct this to:
NEVER put input data directly into SQL commands
$q = Doctrine_Query::create() ->update('Account') ->set('amount', 'amount + 200') ->where("id > {$_GET['id']}");
->where("id > ?", (int) $_GET['id']);
![Page 20: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/20.jpg)
OWASP 20
Prepared statements in Propel
Uses PDO, like Doctrine
// through Criteria $c = new Criteria(); $c->add(AuthorPeer::FIRST_NAME, "Karl"); $authors = AuthorPeer::doSelect($c); // through custom SQL (sometimes it's more convenient) $pdo = Propel::getConnection(BookPeer::DATABASE_NAME); $sql = "SELECT * FROM complicated_sql JOIN some_big_join USING something WHERE column = :col)”; $stmt = $pdo->prepare($sql); $stmt->execute(array('col' => 'Bye bye SQLi!');
![Page 21: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/21.jpg)
OWASP 21
Prepared statements in 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 in one step $stmt = $db->query('SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?', array('goofy', 'FIXED')); while ($row = $stmt->fetch()) echo $row['bug_description'];
![Page 22: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/22.jpg)
OWASP 22
Prepared statements in MDB2
Based on different database drivers (mysql, oci8, mssql, ...)
Emulates PS, if database doesn't support them
$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();
![Page 23: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/23.jpg)
OWASP 23
Prepared statements - summary
They offer very good protection (if used properly)
Easy to use, small changes in code
Good support in frameworks
They have their limits
Sometimes they have to be used with other defense methods
![Page 24: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/24.jpg)
OWASP 24
How to defend?
Escaping data
![Page 25: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/25.jpg)
OWASP 25
Escaping – how does it work?
Data and commands are still kept in a single variable, but we try to separate them inline
Numbers
• Cast to (int) / (float) – don't use is_numeric [1]!
Texts are surrounded with single quotes : '
• If quote is inside the text, you need a way to distinguish it from the ending quote
• Prepend a special character e.g. "\" to a quote
• Escaping rules depend on context!
.. WHERE col = 'TEXT DATA' AND ...
![Page 26: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/26.jpg)
OWASP 26
Escaping – context
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). / Source: php.net manual /
Are you safe?
$user = addslashes($_GET['u']); $pass = addslashes($_GET['p']); $sql = "SELECT * FROM users WHERE username = '{$user}' AND password = '{$pass}'"; $ret = exec_sql($sql);
![Page 27: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/27.jpg)
OWASP
NO
![Page 28: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/28.jpg)
OWASP 28
Escaping – context cont.
Different RDBMS have different ways of escaping data (it also depends on configuration)
addslashes() works just like MySQL only „by chance”
RBDMS PHP function i've got quotes
PDO $pdo->quote($val, $type) n/a (it depends)
MySQL (mysql) mysql_real_escape_string i\'ve got quotes
MySQL (mysqli) mysqli_real_escape_string i\'ve got quotes
Oracle (oci8) n/d - str_replace() i''ve got quotes
SQLite sqlite_escape_string i''ve got quotes
MS SQL (mssql) n/d - str_replace() i''ve got quotes
PostgreSQL pg_escape_string() i''ve got quotes
![Page 29: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/29.jpg)
OWASP 29
Escaping – context cont.
Don't use addslashes(), use PHP functions for your
RBDMS
Are you safe now?
// SELECT * FROM users WHERE username = // '{$user}' AND password = '{$pass}' $_GET['u'] = "anything'"; $_GET['p'] = " or 1=1 -- "; // MySQL sees it as : SELECT * FROM users WHERE username = 'anything\'' AND password = ' or 1=1 -- ' // SQLite / MS SQL / Oracle / PostgreSQL: SELECT * FROM users WHERE username = 'anything\'' AND password = ' or 1=1 -- '
![Page 30: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/30.jpg)
OWASP
ALMOST
![Page 31: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/31.jpg)
OWASP 31
Escaping gotchas – charsets
Errors discovered in 2006 in PostgreSQL and MySQL [1] [2]
In some multibyte charsets despite escaping you can cause SQL injection
\ is „swallowed” by multibyte character
Example:
• BF 27 [ ¬ ' ] BF 5C 27 [ ¬ \ ' ]
• First 2 bytes are character ¿ in GBK charset
• Server will see ¿'
![Page 32: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/32.jpg)
OWASP 32
Escaping gotchas – charsets
Some Asian charsets are vulnerable
Luckily - not UTF-8!
In PostgreSQL '' escaping was used (instead of \')
In mysql_real_escape_string() escaping is done with respect to current connection charset
• Doesn't always work! [1] [2]
Charset also defines context
![Page 33: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/33.jpg)
OWASP 33
Escaping gotchas – object names
Colum, table, database etc. names
• No common good rule to escape them
• Different reserved words, different maximum name lengths etc.
If you need to get those names from the user - use whitelisting (blacklisting if you really can't do otherwise)
![Page 34: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/34.jpg)
OWASP 34
Escaping gotchas – object names cont.
Example - sorting by column
There's a vuln. in $order, but you can't
escape there
$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()) { ... }
![Page 35: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/35.jpg)
OWASP 35
Escaping gotchas – object names cont.
Whitelisting
Blacklisting
$columns = array( // list of allowed columns 'product_name','cid','price', ); if (!in_array($order, $columns, true)) $order = 'product_name'; // default column
// only a-z and _ $order = preg_replace('/[^a-z_]/', '', $order); // max 40 characters $order = substr($order, 0, 40);
![Page 36: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/36.jpg)
OWASP
Escaping in PDO
PDO::quote($value, $type, $len)
Length and type are sometimes ignored!
• Cast numbers to (int), (float)
• Texts – cut them manually
36
$quoted = $pdo->quote($input, PDO::PARAM_STR, 40);
![Page 37: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/37.jpg)
OWASP 37
Escaping in Doctrine
Careful with Doctrine quote()!
$q = Doctrine_Query::create(); // not like this!!! $quoted = $q->getConnection()->quote($input, 'text'); $q->update('User')->set('username', $quoted); // quote() only changes ' to '' - exploit (MySQL): $input = 'anything\\\' where 1=1 -- '; // escape through PDO - getDbh(): $quoted = $q->getConnection() ->getDbh() ->quote($input, PDO::PARAM_STR); // 'anything \\\\\\\' where 1=1 -- '
![Page 38: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/38.jpg)
OWASP 38
Escaping in Propel
Through PDO::quote()
$pdo = Propel::getConnection(UserPeer::DATABASE_NAME); $c = new Criteria(); $c->add(UserPeer::PASSWORD, "MD5(".UserPeer::PASSWORD.") " ." = " . $pdo->quote($password), Criteria::CUSTOM);
![Page 39: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/39.jpg)
OWASP 39
Escaping in Zend Framework
Functions quote(), quoteInto()
$name = $db->quote("O'Reilly"); // 'O\'Reilly' // simplified escaping for a single value $sql = $db->quoteInto("SELECT * FROM products WHERE product_name = ?", 'any string');
![Page 40: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/40.jpg)
OWASP 40
Escaping in MDB
// quote() function - give type $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);
quote()
![Page 41: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/41.jpg)
OWASP 41
Escaping - summary
Looks easy - search and replace
Just looks
• You need to know the context (database, charset)
• There are invalid implementations
Encourages invalid practices
• concatenating strings to form a SQL command
• ignoring numeric parameters
Use only if
• You program for a single RDBMS
• There is no other way
![Page 42: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/42.jpg)
OWASP 42
How to defend?
Stored procedures
![Page 43: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/43.jpg)
OWASP 43
Stored procedures
SQL command(s) is moved to database server and stored there under a name
Client executes a procedure with input and output parameters
In output parameters client receives results
Data is formally separated from code
It's NOT enough
![Page 44: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/44.jpg)
OWASP 44
Stored procedures cont.
Example for MS SQL – a vulnerable procedure
It's just like eval()!
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) ...
![Page 45: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/45.jpg)
OWASP 45
Stored procedures cont.
Same vulnerability in 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;
![Page 46: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/46.jpg)
OWASP 46
Stored procedures – Dynamic SQL
Vulnerability lies in Dynamic SQL
• Data is again mixed with code in one variable
How to defend?
• Separate the code from data
• Escape
![Page 47: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/47.jpg)
OWASP 47
Stored procedures in MS SQL
Separating code from data
• use sp_executesql with parameter list
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
![Page 48: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/48.jpg)
OWASP 48
Stored procedures in MS SQL cont.
Escaping character data
Example:
Escape only when you must! (use sp_executesql with parameters)
Object name QUOTENAME(@v)
Text <= 128 chars QUOTENAME(@v,'''')
Text > 128 chars REPLACE(@v,'''','''''')
SET @cmd = N'select * from authors where lname=''' + REPLACE(@lname, '''', '''''') + N''''
![Page 49: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/49.jpg)
OWASP 49
Stored procedures in Oracle
Oracle - use EXECUTE IMMEDIATE .. USING
Escaping - DBMS_ASSERT package
CREATE PROCEDURE SP_ProductSearch @prodname varchar(400) = NULL AS DECLARE @sql nvarchar(4000) SELECT @sql = 'SELECT ProductID, ProductName, Category, Price FROM Product Where ProductName LIKE @prodname' EXEC sp_executesql @sql, N'@prodname varchar(400)', @prodname
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;
![Page 50: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/50.jpg)
OWASP 50
Stored procedures in MySQL
Support for Dynamic SQL only through prepared statements
It's actually harder to make vulnerable procedure
Just use placeholders
![Page 51: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/51.jpg)
OWASP 51
Stored procedures in MySQL cont.
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 ;
![Page 52: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/52.jpg)
OWASP 52
Stored procedures in MySQL cont.
Or, even simpler
Escaping – QUOTE() function
DELIMITER $$ CREATE PROCEDURE get_users_like ( IN contains VARCHAR(40)) BEGIN SET @like = CONCAT("%", contains, "%"); SELECT * FROM users WHERE uname LIKE @like; END$$ DELIMITER ;
![Page 53: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/53.jpg)
OWASP 53
Stored procedures in PHP
Different support level, depending on RDBMS
Common API (e.g. PDO) only for simple calls
• No return from procedure
• Returns scalar value in OUT parameter
Different API (or none at all) for advanced calls
• e.g. cursors, fetching records sets
Almost no support in frameworks
Still some errors...
![Page 54: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/54.jpg)
OWASP 54
Stored procedures in PDO
Calling a procedure
// 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);
![Page 55: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/55.jpg)
OWASP 55
Stored procedures in Doctrine/Propel/Zend Framework
Doctrine - no support (use PDO)
Propel – likewise
Zend Framework – likewise
$pdo = Doctrine_Manager::connection()->getDbh();
$pdo = Propel::getConnection(UserPeer::DATABASE_NAME);
$pdo = $db::getConnection();
![Page 56: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/56.jpg)
OWASP 56
Stored procedures in MDB2
You need to manually escape all parameters!
$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()); }
![Page 57: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/57.jpg)
OWASP 57
Stored procedures - gotchas
Data length
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
![Page 58: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/58.jpg)
OWASP 58
Stored procedures - summary
Moving SQL logic to server takes time
Code is not easily ported to other RDBMS
You need to use prepared statements or escaping to write safe stored procedures anyway
If done poorly, you're even more vulnerable
• Both SP code and statement calling SP could be vulnerable
• SP usually has greater permissions than code calling it
Bad support in PHP and frameworks
![Page 59: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/59.jpg)
OWASP 59
Stored procedures - summary
SPs have many advantages outside our scope
Could be used with different clients (Java/.NET + PHP)
Could have better berformance
and many more...
Conclusion:
You can write secure stored procedures, but they usually increase the application cost considerably
It is vital to write stored procedures protected against SQL injection
![Page 60: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/60.jpg)
OWASP 60
How to defend?
Additional methods
![Page 61: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/61.jpg)
OWASP 61
Validation and filtering
Validate all external data
Validate before processing
Filter INPUT - escape OUTPUT
Different validation rules for each parameter - check e.g.
• Type
• Scalar / array
• Min / max values
• Character data length! [1]
![Page 62: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/62.jpg)
OWASP 62
Additional methods
Complementary to all previously mentioned!
Principle of least privilege when connecting to DB
Removing unused functions, accounts, packages shipped with database
Routinely updating the system and database software
Correct PHP and database configuration • magic_quotes_* = false
• display_errors = false
Good database design
![Page 63: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/63.jpg)
OWASP 63
Summary
Pay attention to SQL injection - even a single mistake could cost you!
Prefer complete solutions - e.g. frameworks
Filter and validate all input data
Remeber about data types and lengths
Prefer whitelisting to blacklisting - the latter will fail one day!
Use prepared statements whenever you can
Try to avoid escaping
In stored procedures double check your Dynamic SQL
![Page 64: Owasp SQL Injection en 100317143725 Phpapp02](https://reader034.fdocuments.in/reader034/viewer/2022052301/547ada97b4795995098b4b72/html5/thumbnails/64.jpg)
OWASP 64
Links
Discussed projects
• 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
About 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
[email protected] http://blog.kotowicz.net