0
SQL INJECTION
MYTHS AND FALLACIES
Bill Karwin
ME
• Software developer
• C, Java, Perl, PHP, Ruby, SQL
• Author of SQL Antipatterns: 

Avoiding the Pitfalls of Database ...
WHAT IS SQL INJECTION?
http://example.com/show.php?bugid=1234
SELECT * FROM Bugs 

WHERE bug_id = $_GET['bugid']
user input
WHAT IS SQL INJECTION?
http://example.com/show.php?bugid=1234 ORTRUE
SELECT * FROM Bugs 

WHERE bug_id = 1234 ORTRUE
unint...
WORSE SQL INJECTION
http://example.com/changepass.php?acctid=1234

&pass=xyzzy
UPDATE Accounts 

SET password = SHA2('$pas...
WORSE SQL INJECTION
http://example.com/changepass.php?acctid=1234 ORTRUE

&pass=xyzzy'), admin=('1
UPDATE Accounts 

SET p...
MYTHS AND FALLACIES
Based on a grain of truth, 

but derives a wrong conclusion
Based on a false assumption, 

but derives...
MYTH
“SQL Injection is an old
problem―so I don’t have to
worry about it.”
MYTH
ARCHOS
• Christmas 2014
• “French smartphone maker Archos was
compromised by a SQL injection attack last
Christmas, result...
WORDPRESS
• February 2015
• “One Million WordPress WebsitesVulnerable to
SQL Injection Attack”
• http://www.tripwire.com/s...
DRUPAL
• March 2015
• “Drupal SQL injection vulnerability attacks
persist, despite patch release”
• http://www.scmagazine....
MYTH
“Escaping input 

prevents SQL injection.”
MYTH
ESCAPING & FILTERING
http://example.com/changepass.php?acctid=1234 ORTRUE

&pass=xyzzy'), admin=('1
UPDATE Accounts 

SET ...
ESCAPING & FILTERING
FUNCTIONS
<?php
$password = $_POST["password"];

$password_escaped = mysqli_real_escape_string($passw...
ESCAPING & FILTERING
FUNCTIONS
<?php
$password = $_POST["password"];

$password_quoted = $pdo->quote($password);
$id = filt...
IDENTIFIERS AND KEYWORDS
<?php
$column = $_GET["order"];

$column_delimited = $pdo->FUNCTION?($column);
$direction = $_GET...
MYTH
“If some escaping is good, more
must be better.”
MYTH
OVERKILL?
<?php
function sanitize($string){     

  $string = strip_tags($string); 

  $string = htmlspecialchars($string)...
“FIRE EVERYTHING!!”
JUSTTHE ONE WILL DO
<?php
$password = mysqli_real_escape_string( 

$_POST["password"] );
mysqli_query("UPDATE Users 

SET ...
MYTH
“I can write my own 

escaping function.”
MYTH
PLEASE DON’T
• http://example.org/login.php?account=%bf%27 OR 'x'='x
• $account = addslashes($_REQUEST(“account”));
• adds...
GRANT ACCESSTO ANY
ACCOUNT
• Interpolating:
SELECT * FROM Accounts 

WHERE account = '{$account}' 

AND password = '{$pass...
SOLUTIONS
• Use driver-provided escaping functions:
• mysqli::real_escape_string()
• PDO::quote()
• Use API functions to s...
MYTH
“Unsafe data comes from
users―if it’s already in the
database, then it’s safe.”
MYTH
NOT NECESSARILY
$sql = "SELECT product_name FROM Products";

$prodname = $pdo->query($sql)->fetchColumn();
$sql = "SELECT ...
FALLACY
“Using stored procedures
prevents SQL Injection.”
FALLACY
STATIC SQL IN PROCEDURES
CREATE PROCEDURE FindBugById (IN bugid INT)

BEGIN

SELECT * FROM Bugs WHERE bug_id = bugid;

END...
DYNAMIC SQL IN
PROCEDURES
CREATE PROCEDURE BugsOrderBy

(IN column_nameVARCHAR(100), 

IN directionVARCHAR(4))

BEGIN

SET...
WORTHY OFTHEDAILYWTF
CREATE PROCEDURE QueryAnyTable

(IN table_nameVARCHAR(100))

BEGIN

SET @query = CONCAT(

'SELECT * F...
MYTH
“Conservative SQL privileges
limit the damage.”
MYTH
DENIAL OF SERVICE
SELECT * FROM Bugs JOIN Bugs 

JOIN Bugs JOIN Bugs JOIN Bugs 

JOIN Bugs

100 bugs = 1 trillion rows
DENIAL OF SERVICE
SELECT * FROM Bugs JOIN Bugs 

JOIN Bugs JOIN Bugs JOIN Bugs 

JOIN Bugs 

ORDER BY 1
still requires onl...
JUST ASKING FOR IT
http://www.example.com/show.php?

query=SELECT%20*%20FROM%20Bugs
FALLACY
“It’s just an intranet
application―it doesn’t 

need to be secure.”
FALLACY
JUST ASKTHIS MANAGER
WHAT STAYS ONTHE
INTRANET?
• You could be told to give business partners access
to an internal application
UPDATE Accounts...
WHAT STAYS ONTHE
INTRANET?
• Your casual code could be copied & pasted into
external applications
UPDATE Accounts 

SET pa...
WHAT STAYS ONTHE
INTRANET?
• It’s hard to argue for a security review or rewrite
for a “finished” application
$$$
UPDATE Ac...
MYTH
“My framework 

prevents SQL Injection.”
MYTH
ORMS ALLOW CUSTOM SQL
• Dynamic SQL always risks SQL Injection, 

for example Rails ActiveRecord:
Bugs.all(

:joins => "JO...
WHOSE RESPONSIBILITY?
• Security is the application developer’s job
• No database, connector, or framework can
prevent SQL...
FALLACY
“Query parameters do quoting
for you.”
FALLACY
INTERPOLATING DYNAMIC
VALUES
• Query needs a dynamic value:
SELECT * FROM Bugs 

WHERE bug_id = $_GET['bugid']
user input
USING A PARAMETER
• Query parameter takes the place of a dynamic
value:
SELECT * FROM Bugs 

WHERE bug_id = ?
parameter
pl...
HOWTHE DATABASE PARSES IT
query
SELECT
FROM
WHERE
expr-list *
simple-
table
expr
bugs
parameter

placeholder
?
bug_id
=equ...
HOWTHE DATABASE EXECUTES IT
query
SELECT
FROM
WHERE
expr-list *
simple-
table
expr
bugs
1234
bug_id
=
parameter

value
equ...
INTERPOLATION
query
SELECT
FROM
WHERE
expr-list *
simple-
table
expr
1234
bugs
bug_id
=
TRUE
OR
SQL injection
equality
PARAMETERIZATION
query
SELECT
FROM
WHERE
expr-list *
simple-
table
expr
bugs
1234
OR
TRUE
bug_id
=
no parameter

can chang...
PREPARE & EXECUTE
Client Server
parse query
send parameters
send SQL
optimize query
execute query
return results
prepare q...
MYTH
“Query parameters prevent
SQL Injection.”
MYTH
ONE PARAMETER = ONEVALUE
SELECT * FROM Bugs 

WHERE bug_id = ?
NOT A LIST OFVALUES
SELECT * FROM Bugs 

WHERE bug_id IN ( ? )
NOT ATABLE NAME
SELECT * FROM ? 

WHERE bug_id = 1234
NOT A COLUMN NAME
SELECT * FROM Bugs 

ORDER BY ?
NOT AN SQL KEYWORD
SELECT * FROM Bugs 

ORDER BY date_reported ?
INTERPOLATIONVS. PARAMETERS
Scenario Example Value Interpolation Parameter
single value ‘1234’
SELECT * FROM Bugs 

WHERE ...
SOLUTION
Whitelist Maps
SOLUTION
EXAMPLE SQL INJECTION
http://www.example.com/?order=date_reported&dir=ASC
<?php
$sortorder = $_GET["order"];

$direction =...
FIX WITH A WHITELIST MAP
<?php
$sortorders = array( "DEFAULT" => "bug_id",

"status" => "status",

"date" => "date_reporte...
MAP USER INPUTTO SAFE
SQL
<?php
$direction = $directions[ $_GET["dir"] ] ?: $directions["DEFAULT"];
INTERPOLATE SAFE SQL
http://www.example.com/?order=date&dir=up
<?php
$sql = "SELECT * FROM Bugs 

ORDER BY {$sortorder} {$...
BENEFITS OF WHITELIST MAPS
•Protects against SQL injection in cases where
escaping and parameterization doesn’t help.
•Dec...
FALLACY
“Queries parameters 

hurt SQL performance.”
FALLACY
SIMPLE QUERY
Profiled Elapsed
COMPLEX QUERY
Profiled Elapsed
MYTH
“A proxy/firewall solution 

prevents SQL injection.”
MYTH
ORACLE DATABASE FIREWALL
• Reverse proxy between application and Oracle
•Whitelist of known SQL queries
•Learns legitimate...
GREENSQL
• Reverse proxy for MySQL, PostgreSQL, Microsoft SQL Server
• Detects / reports / blocks “suspicious” queries:
•A...
STILL NOT PERFECT
• Vipin Samar, Oracle vice president of Database Security:
• “Database Firewall is a good first layer of ...
LIMITATIONS OF PROXY
SOLUTIONS
•False sense of security; discourages code review
•Gating factor for emergency code deploym...
FALLACY
“NoSQL databases are immune
to SQL injection.”
FALLACY
“NOSQL INJECTION”
http://www.example.com?column=password
<?php
$map = new MongoCode("function() { 

emit(this." . $_GET["c...
NOSQL INJECTION INTHE
WILD
• Diaspora wrote MongoDB map/reduce functions dynamically from Ruby on Rails:
• def self.search...
MYTHS AND FALLACIES
• I don’t have to worry anymore
• Escaping is the fix
• More escaping is better
• I can code an escapin...
SQL ANTIPATTERNS
http://www.pragprog.com/titles/bksqla/
LICENSE AND COPYRIGHT
Copyright 2010-2015 Bill Karwin
www.slideshare.net/billkarwin
Released under a Creative Commons 3.0 ...
Upcoming SlideShare
Loading in...5
×

Sql Injection Myths and Fallacies

81,748

Published on


The most massive crime of identity theft in history was perpetrated in 2007 by exploiting an SQL Injection vulnerability. This issue is one of the most common and most serious threats to web application security. In this presentation, you'll see some common myths busted and you'll get a better understanding of defending against SQL injection.

Published in: Technology
9 Comments
87 Likes
Statistics
Notes
  • While I agree with the limitations of parameters (can't be used for table names, ordering etc) it feels like it's a different level of 'not a fix' to the others (such as escaping). Unless I'm wrong - and I'm *not* a database expert - query parameters really are *the* way to go in situations where they're applicable (i.e. when you don't need to dynamically choose the table name, build a list etc). There aren't all the 'gotchas' to be really careful with that there are with escaping (which always feels like a losing battle to me).

    Of course there are other benefits of query parameters anyway - simpler to read SQL and avoiding error-prone conversions (especially for date/time types) for example.

    Is this a fair statement, or are there downsides to query parameters beyond the limitations? The good part of the limitations is that when you bump into them, you *know* you've bumped into them, because the query simply doesn't work - so with query parameters you're either working safely, or you're broken. Again, that's assuming I'm not missing something.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • the 20th slide, story of my life
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • very good
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Awesome PPT and very knowledgeable
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Slide 27 - Why does QueryAnyTable have a table_name IN parameter when we pass the 'SELECT * FROM' to the procedure? Won't that execute 'SELECT * FROM SELECT * FROM ...' ?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
81,748
On Slideshare
0
From Embeds
0
Number of Embeds
22
Actions
Shares
0
Downloads
1,768
Comments
9
Likes
87
Embeds 0
No embeds

No notes for slide

Transcript of "Sql Injection Myths and Fallacies"

  1. 1. SQL INJECTION MYTHS AND FALLACIES Bill Karwin
  2. 2. ME • Software developer • C, Java, Perl, PHP, Ruby, SQL • Author of SQL Antipatterns: 
 Avoiding the Pitfalls of Database Programming
  3. 3. WHAT IS SQL INJECTION? http://example.com/show.php?bugid=1234 SELECT * FROM Bugs 
 WHERE bug_id = $_GET['bugid'] user input
  4. 4. WHAT IS SQL INJECTION? http://example.com/show.php?bugid=1234 ORTRUE SELECT * FROM Bugs 
 WHERE bug_id = 1234 ORTRUE unintended logic
  5. 5. WORSE SQL INJECTION http://example.com/changepass.php?acctid=1234
 &pass=xyzzy UPDATE Accounts 
 SET password = SHA2('$password')
 WHERE account_id = $account_id
  6. 6. WORSE SQL INJECTION http://example.com/changepass.php?acctid=1234 ORTRUE
 &pass=xyzzy'), admin=('1 UPDATE Accounts 
 SET password = SHA2('xyzzy'), admin=('1')
 WHERE account_id = 1234 ORTRUE changes password for all accounts changes account to administrator
  7. 7. MYTHS AND FALLACIES Based on a grain of truth, 
 but derives a wrong conclusion Based on a false assumption, 
 but derives a logical conclusion MYTH FALLACY
  8. 8. MYTH “SQL Injection is an old problem―so I don’t have to worry about it.” MYTH
  9. 9. ARCHOS • Christmas 2014 • “French smartphone maker Archos was compromised by a SQL injection attack last Christmas, resulting in the leak of up to 100,000 customer details.” • http://www.scmagazineuk.com/up-to-100k-archos-customers-compromised-by-sql-injection-attack/article/395642/
  10. 10. WORDPRESS • February 2015 • “One Million WordPress WebsitesVulnerable to SQL Injection Attack” • http://www.tripwire.com/state-of-security/latest-security-news/one-million-wordpress-websites-vulnerable-to-sql-injection-attack/
  11. 11. DRUPAL • March 2015 • “Drupal SQL injection vulnerability attacks persist, despite patch release” • http://www.scmagazine.com/trustwave-details-drupal-sql-injection-attack/article/404719/
  12. 12. MYTH “Escaping input 
 prevents SQL injection.” MYTH
  13. 13. ESCAPING & FILTERING http://example.com/changepass.php?acctid=1234 ORTRUE
 &pass=xyzzy'), admin=('1 UPDATE Accounts 
 SET password = SHA2('xyzzy'), admin=('1')
 WHERE account_id = 1234 coerced to 
 integer backslash escapes special characters
  14. 14. ESCAPING & FILTERING FUNCTIONS <?php $password = $_POST["password"];
 $password_escaped = mysqli_real_escape_string($password); $id = (int) $_POST["account"]; $sql = "UPDATE Accounts
 SET password = SHA2(‘{$password_escaped}’)
 WHERE account_id = {$id}"; mysql_query($sql);
  15. 15. ESCAPING & FILTERING FUNCTIONS <?php $password = $_POST["password"];
 $password_quoted = $pdo->quote($password); $id = filter_input(INPUT_POST, "account", 
 FILTER_SANITIZE_NUMBER_INT); $sql = "UPDATE Accounts
 SET password = SHA2( {$password_quoted} )
 WHERE account_id = {$id}"; $pdo->query($sql);
  16. 16. IDENTIFIERS AND KEYWORDS <?php $column = $_GET["order"];
 $column_delimited = $pdo->FUNCTION?($column); $direction = $_GET["dir"]; $sql = "SELECT * FROM Bugs
 ORDER BY {$column_delimited} {$direction}"; $pdo->query($sql); no API to support delimited identifiers keywords get no quoting
  17. 17. MYTH “If some escaping is good, more must be better.” MYTH
  18. 18. OVERKILL? <?php function sanitize($string){     
   $string = strip_tags($string); 
   $string = htmlspecialchars($string);
   $string = trim(rtrim(ltrim($string))); 
   $string = mysql_real_escape_string($string);
   return $string;
 } $password = sanitize( $_POST["password"] ); real function from 
 a user’s project
  19. 19. “FIRE EVERYTHING!!”
  20. 20. JUSTTHE ONE WILL DO <?php $password = mysqli_real_escape_string( 
 $_POST["password"] ); mysqli_query("UPDATE Users 
 SET password = '$password' 
 WHERE user_id = $user_id");
  21. 21. MYTH “I can write my own 
 escaping function.” MYTH
  22. 22. PLEASE DON’T • http://example.org/login.php?account=%bf%27 OR 'x'='x • $account = addslashes($_REQUEST(“account”)); • addslashes() sees a single-quote (%27) and inserts backslash (%5c). Result:
 %bf%5c%27 OR 'x'='x valid multi-byte character in GBK: 縗 single-quote
  23. 23. GRANT ACCESSTO ANY ACCOUNT • Interpolating: SELECT * FROM Accounts 
 WHERE account = '{$account}' 
 AND password = '{$passwd}' • Results in: SELECT * FROM Accounts 
 WHERE account = '縗' OR 'x'= 'x' 
 AND password = 'xyzzy' • http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string • http://bugs.mysql.com/bug.php?id=8378
  24. 24. SOLUTIONS • Use driver-provided escaping functions: • mysqli::real_escape_string() • PDO::quote() • Use API functions to set the client character set: • mysqli::set_charset() • http://ilia.ws/archives/103-mysql_real_escape_string-versus-Prepared-Statements.html • Use UTF-8 instead of GBK, SJIS, etc.
  25. 25. MYTH “Unsafe data comes from users―if it’s already in the database, then it’s safe.” MYTH
  26. 26. NOT NECESSARILY $sql = "SELECT product_name FROM Products";
 $prodname = $pdo->query($sql)->fetchColumn(); $sql = "SELECT * FROM Bugs 
 WHERE MATCH(summary, description) 
 AGAINST ('{$prodname}')"; not safe input
  27. 27. FALLACY “Using stored procedures prevents SQL Injection.” FALLACY
  28. 28. STATIC SQL IN PROCEDURES CREATE PROCEDURE FindBugById (IN bugid INT)
 BEGIN
 SELECT * FROM Bugs WHERE bug_id = bugid;
 END CALL FindByBugId(1234) filtering by data type is a good thing
  29. 29. DYNAMIC SQL IN PROCEDURES CREATE PROCEDURE BugsOrderBy
 (IN column_nameVARCHAR(100), 
 IN directionVARCHAR(4))
 BEGIN
 SET @query = CONCAT(
 'SELECT * FROM Bugs ORDER BY ', 
 column_name, ' ', direction);
 PREPARE stmt FROM @query;
 EXECUTE stmt;
 END CALL BugsOrderBy('date_reported', 'DESC') interpolating arbitrary strings = SQL injection
  30. 30. WORTHY OFTHEDAILYWTF CREATE PROCEDURE QueryAnyTable
 (IN table_nameVARCHAR(100))
 BEGIN
 SET @query = CONCAT(
 'SELECT * FROM ', table_name);
 PREPARE stmt FROM @query;
 EXECUTE stmt;
 END CALL QueryAnyTable( '(SELECT * FROM ...)' ) http://thedailywtf.com/Articles/For-the-Ease-of-Maintenance.aspx
  31. 31. MYTH “Conservative SQL privileges limit the damage.” MYTH
  32. 32. DENIAL OF SERVICE SELECT * FROM Bugs JOIN Bugs 
 JOIN Bugs JOIN Bugs JOIN Bugs 
 JOIN Bugs
 100 bugs = 1 trillion rows
  33. 33. DENIAL OF SERVICE SELECT * FROM Bugs JOIN Bugs 
 JOIN Bugs JOIN Bugs JOIN Bugs 
 JOIN Bugs 
 ORDER BY 1 still requires only SELECT privilege
  34. 34. JUST ASKING FOR IT http://www.example.com/show.php?
 query=SELECT%20*%20FROM%20Bugs
  35. 35. FALLACY “It’s just an intranet application―it doesn’t 
 need to be secure.” FALLACY
  36. 36. JUST ASKTHIS MANAGER
  37. 37. WHAT STAYS ONTHE INTRANET? • You could be told to give business partners access to an internal application UPDATE Accounts 
 SET password = SHA2('$password')
 WHERE account_id = $account_id
  38. 38. WHAT STAYS ONTHE INTRANET? • Your casual code could be copied & pasted into external applications UPDATE Accounts 
 SET password = SHA2('$password')
 WHERE account_id = $account_id UPDATE Accounts 
 SET password = SHA2('$password')
 WHERE account_id = $account_id
  39. 39. WHAT STAYS ONTHE INTRANET? • It’s hard to argue for a security review or rewrite for a “finished” application $$$ UPDATE Accounts 
 SET password = SHA2('$password')
 WHERE account_id = $account_id ?
  40. 40. MYTH “My framework 
 prevents SQL Injection.” MYTH
  41. 41. ORMS ALLOW CUSTOM SQL • Dynamic SQL always risks SQL Injection, 
 for example Rails ActiveRecord: Bugs.all(
 :joins => "JOIN Accounts 
 ON reported_by = account_id",
 
 :order => "date_reported DESC"
 ) any custom SQL can carry SQL injection
  42. 42. WHOSE RESPONSIBILITY? • Security is the application developer’s job • No database, connector, or framework can prevent SQL injection all the time
  43. 43. FALLACY “Query parameters do quoting for you.” FALLACY
  44. 44. INTERPOLATING DYNAMIC VALUES • Query needs a dynamic value: SELECT * FROM Bugs 
 WHERE bug_id = $_GET['bugid'] user input
  45. 45. USING A PARAMETER • Query parameter takes the place of a dynamic value: SELECT * FROM Bugs 
 WHERE bug_id = ? parameter placeholder
  46. 46. HOWTHE DATABASE PARSES IT query SELECT FROM WHERE expr-list * simple- table expr bugs parameter
 placeholder ? bug_id =equality
  47. 47. HOWTHE DATABASE EXECUTES IT query SELECT FROM WHERE expr-list * simple- table expr bugs 1234 bug_id = parameter
 value equality
  48. 48. INTERPOLATION query SELECT FROM WHERE expr-list * simple- table expr 1234 bugs bug_id = TRUE OR SQL injection equality
  49. 49. PARAMETERIZATION query SELECT FROM WHERE expr-list * simple- table expr bugs 1234 OR TRUE bug_id = no parameter
 can change the tree equality
  50. 50. PREPARE & EXECUTE Client Server parse query send parameters send SQL optimize query execute query return results prepare query execute query repeat with 
 different 
 parameters bind parameters convert to machine- readable form
  51. 51. MYTH “Query parameters prevent SQL Injection.” MYTH
  52. 52. ONE PARAMETER = ONEVALUE SELECT * FROM Bugs 
 WHERE bug_id = ?
  53. 53. NOT A LIST OFVALUES SELECT * FROM Bugs 
 WHERE bug_id IN ( ? )
  54. 54. NOT ATABLE NAME SELECT * FROM ? 
 WHERE bug_id = 1234
  55. 55. NOT A COLUMN NAME SELECT * FROM Bugs 
 ORDER BY ?
  56. 56. NOT AN SQL KEYWORD SELECT * FROM Bugs 
 ORDER BY date_reported ?
  57. 57. INTERPOLATIONVS. PARAMETERS Scenario Example Value Interpolation Parameter single value ‘1234’ SELECT * FROM Bugs 
 WHERE bug_id = $id SELECT * FROM Bugs 
 WHERE bug_id = ? multiple values ‘1234, 3456, 5678’ SELECT * FROM Bugs 
 WHERE bug_id IN ($list) SELECT * FROM Bugs 
 WHERE bug_id IN ( ?, ?, ? ) table name ‘Bugs’ SELECT * FROM $table 
 WHERE bug_id = 1234 NO column name ‘date_reported’ SELECT * FROM Bugs 
 ORDER BY $column NO other syntax ‘DESC’ SELECT * FROM Bugs 
 ORDER BY date_reported $direction NO
  58. 58. SOLUTION Whitelist Maps SOLUTION
  59. 59. EXAMPLE SQL INJECTION http://www.example.com/?order=date_reported&dir=ASC <?php $sortorder = $_GET["order"];
 $direction = $_GET["dir"]; $sql = "SELECT * FROM Bugs 
 ORDER BY {$sortorder} {$direction}"; $stmt = $pdo->query($sql); unsafe inputs SQL Injection
  60. 60. FIX WITH A WHITELIST MAP <?php $sortorders = array( "DEFAULT" => "bug_id",
 "status" => "status",
 "date" => "date_reported" ); $directions = array( "DEFAULT" => "ASC",
 "up" => "ASC",
 "down" => "DESC" ); application request values SQL identifiers and keywords
  61. 61. MAP USER INPUTTO SAFE SQL <?php $direction = $directions[ $_GET["dir"] ] ?: $directions["DEFAULT"];
  62. 62. INTERPOLATE SAFE SQL http://www.example.com/?order=date&dir=up <?php $sql = "SELECT * FROM Bugs 
 ORDER BY {$sortorder} {$direction}"; $stmt = $pdo->query($sql); whitelisted values
  63. 63. BENEFITS OF WHITELIST MAPS •Protects against SQL injection in cases where escaping and parameterization doesn’t help. •Decouples web interface from database schema. •Uses simple, declarative technique. •Works independently of any framework.
  64. 64. FALLACY “Queries parameters 
 hurt SQL performance.” FALLACY
  65. 65. SIMPLE QUERY Profiled Elapsed
  66. 66. COMPLEX QUERY Profiled Elapsed
  67. 67. MYTH “A proxy/firewall solution 
 prevents SQL injection.” MYTH
  68. 68. ORACLE DATABASE FIREWALL • Reverse proxy between application and Oracle •Whitelist of known SQL queries •Learns legitimate queries from application traffic •Blocks unknown SQL queries •Also supports Microsoft SQL Server, IBM DB2, Sybase ASE, SQL Anywhere • http://www.oracle.com/technetwork/database/database-firewall/overview/index.html
  69. 69. GREENSQL • Reverse proxy for MySQL, PostgreSQL, Microsoft SQL Server • Detects / reports / blocks “suspicious” queries: •Access to sensitive tables •Comments inside SQL commands •An ‘or’ token inside a query •An SQL expression that always returns true • http://www.greensql.net/about
  70. 70. STILL NOT PERFECT • Vipin Samar, Oracle vice president of Database Security: • “Database Firewall is a good first layer of defense for databases but it won't protect you from everything,” 
 http://www.databasejournal.com/features/oracle/article.php/3924691/article.htm • GreenSQL Architecture • “GreenSQL can sometimes generate false positive and false negative errors.As a result, some legal queries may be blocked or the GreenSQL system may pass through an illegal query undetected.”
 http://www.greensql.net/about
  71. 71. LIMITATIONS OF PROXY SOLUTIONS •False sense of security; discourages code review •Gating factor for emergency code deployment •Constrains application from writing dynamic SQL •Doesn’t stop SQL injection in Stored Procedures
  72. 72. FALLACY “NoSQL databases are immune to SQL injection.” FALLACY
  73. 73. “NOSQL INJECTION” http://www.example.com?column=password <?php $map = new MongoCode("function() { 
 emit(this." . $_GET["column"] . ",1); 
 } "); $data = $db->command( array(
 "mapreduce" => "Users",
 "map" => $map
 ) ); any string-interpolation of untrusted content
 is Code Injection
  74. 74. NOSQL INJECTION INTHE WILD • Diaspora wrote MongoDB map/reduce functions dynamically from Ruby on Rails: • def self.search(query)
 Person.all('$where' => "function() { 
 return this.diaspora_handle.match(/^#{query}/i) ||
 this.profile.first_name.match(/^#{query}/i) ||
 this.profile.last_name.match(/^#{query}/i); }")
 end • http://www.kalzumeus.com/2010/09/22/security-lessons-learned-from-the-diaspora-launch/ did query come from a trusted source?
  75. 75. MYTHS AND FALLACIES • I don’t have to worry anymore • Escaping is the fix • More escaping is better • I can code an escaping function • Only user input is unsafe • Stored procs are the fix • SQL privileges are the fix • My app doesn’t need security • Frameworks are the fix • Parameters quote for you • Parameters are the fix • Parameters make queries slow • SQL proxies are the fix • NoSQL databases are the fix there is no single silver bullet—
 use all defenses when appropriate
  76. 76. SQL ANTIPATTERNS http://www.pragprog.com/titles/bksqla/
  77. 77. LICENSE AND COPYRIGHT Copyright 2010-2015 Bill Karwin www.slideshare.net/billkarwin Released under a Creative Commons 3.0 License: 
 http://creativecommons.org/licenses/by-nc-nd/3.0/ You are free to share - to copy, distribute and 
 transmit this work, under the following conditions: Attribution. 
 You must attribute this work to Bill Karwin. Noncommercial. 
 You may not use this work for commercial purposes. No Derivative Works. 
 You may not alter, transform, or build upon this work.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×