64
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 [email protected] 10.03.2010

SQL Injection: complete walkthrough (not only) for PHP developers

Embed Size (px)

DESCRIPTION

Learn what is SQL injection, how to use prepared statements, how to escape and write secure stored procedures. Many PHP projects are covered - PDO, Propel, Doctrine, Zend Framework and MDB2. Multiple gotchas included.

Citation preview

Page 1: SQL Injection: complete walkthrough (not only) for PHP developers

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

[email protected]

10.03.2010

Page 2: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP 3

Discussed databases (RDBMS)

MySQL

Oracle

MS SQL Server

To some extent:

• PostgreSQL

• SQLite

Page 4: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP 5

What is SQL injection?

Page 6: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP 8

Why is it so dangerous?

DEMO

Page 9: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP 11

How to defend?

Page 12: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP 13

How to defend?

Prepared statements

Page 14: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP 24

How to defend?

Escaping data

Page 25: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP

NO

Page 28: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP

ALMOST

Page 31: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP 42

How to defend?

Stored procedures

Page 43: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

OWASP 60

How to defend?

Additional methods

Page 61: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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: SQL Injection: complete walkthrough (not only) for PHP developers

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