SQL Injection in PHP


Published on

Mike Creuzer's presentation from the December, 2009 Suburban Chicago PHP & Web Dev Meetup. The topic is SQL injection in PHP and common PHP content management systems.

Visit Mike's blog at http://mike.creuzer.com/

Published in: Technology
  • Be the first to comment

SQL Injection in PHP

  1. 1. SQL Injection What it is, how it happens, and how to prevent it.
  2. 2. What is SQL Injection? <ul><li>According to WIKIPEDIA: </li></ul><ul><li>SQL injection  is a  code injection  technique that exploits a  security vulnerability  occurring in the  database  layer of an  application .  </li></ul><ul><li>The vulnerability is present when user input is either incorrectly filtered for  string literalescape characters  embedded in  SQL  statements or user input is not  strongly typed  and thereby unexpectedly executed.  </li></ul><ul><li>It is an instance of a more general class of vulnerabilities that can occur whenever one programming or scripting language is embedded inside another. SQL injection attacks are also known as SQL insertion attacks. </li></ul>
  3. 3. What can it do? <ul><ul><li>Allow logging in as another use, such as the administrator </li></ul></ul><ul><ul><li>Cause extra DB records to be displayed </li></ul></ul><ul><ul><li>Allow vandalism of the database </li></ul></ul><ul><ul><li>Allow destruction of the database </li></ul></ul><ul><ul><li>Ruin your day... or night... or weekend... </li></ul></ul><ul><li>The recent theft of 130 million credit card numbers involved SQL Injection. </li></ul>
  4. 4. How does it work? <ul><li>By passing un-filtered user data into a SQL query, a user can cause un-intended SQL queries to be executed. </li></ul><ul><li>$SQL = &quot;SELECT * FROM users  WHERE name = '{$_GET['name']}'&quot; </li></ul><ul><li>$_GET['name']  =  &quot; a' or 't'='t &quot; ; </li></ul><ul><li>SELECT * FROM users  WHERE name = 'a' OR 't' = 't' ; </li></ul>
  5. 5. How do you stop SQL Injection? <ul><li>Do not allow direct user input into the database. </li></ul><ul><li>Parameterized statements </li></ul><ul><ul><li>Use a library that uses parameters </li></ul></ul><ul><ul><li>Use a built in functionality that supports Parametization such as MySQLi in PHP5 </li></ul></ul><ul><li>$db = new mysqli ( &quot;localhost&quot; , &quot;user&quot; , &quot;pass&quot; , &quot;database&quot; ) ; $stmt = $db -> prepare ( &quot;SELECT * FROM Usrs WHERE usrnm=? AND psswrd=?&quot; ) ; $stmt -> bind_param ( &quot;ss&quot; , $user , $pass ) ; $stmt -> execute () ; </li></ul><ul><li>Escaping </li></ul><ul><ul><li>Escape the query using a built in or library function </li></ul></ul><ul><li>$ Password = mysql_real_escape_string ( $Password ) ; </li></ul>
  6. 6. Why does this work? <ul><li>$ name = mysql_real_escape_string ( $_GET['name'] ) ; </li></ul><ul><li>$SQL = &quot;SELECT * FROM users  WHERE name = '{$name}'&quot; </li></ul><ul><li>$_GET['name']  =  &quot; a' or 't'='t &quot; ; </li></ul><ul><li>$name  =  &quot; a' or 't'='t &quot; ; </li></ul><ul><li>SELECT   *   FROM  users  WHERE  name  =   'a' OR 't'='t' ; </li></ul>
  7. 7. Preventing SQL injection in CMSes <ul><li>ALWAYS keep all your modules, themes, components etc. current. </li></ul><ul><li>The CMS communities stay on top of security issues with their software. </li></ul><ul><li>ALWAYS keep all your modules, themes, components etc. current. </li></ul><ul><li>When a compromise is announced, the 'bad people' get just as busy as the 'good people'. </li></ul><ul><li>ALWAYS keep all your modules, themes, components etc. current. </li></ul>
  8. 8. Preventing SQL Injection in JOOMLA! <ul><li>Use JOOMLA!'s JRequest functionality to get typed data from the user.   </li></ul><ul><li>JRequest:: get(), getBool(), getCmd(), getFloat(), getInt(), getString(), getVar() </li></ul><ul><li>Use JOOMLA!'s database quoting and escaping functions. </li></ul><ul><li>$sql = 'UPDATE #__mytable SET `string` = ' . $db -> quote ( $db -> getEscaped ( $string ), false   ); </li></ul><ul><li>JOOMLA!'s database quoting will escape for you automatically </li></ul><ul><li>$sql = 'UPDATE #__mytable SET `string` = ' . $db -> quote ( $string   ); </li></ul><ul><li>JOOMLA!'s database escaping for 'LIKE' escapes '%' </li></ul><ul><li>$sql = 'UPDATE #__mytable SET .... WHERE `string` LIKE ' . $db -> quote ( $db -> getEscaped ( $string , true ), false ); </li></ul>
  9. 9. Preventing SQL Injection in Drupal <ul><li>Drupal has a database layer as well which uses and escapes placeholders:  </li></ul><ul><li>%s, %d, %f, %b, %% </li></ul><ul><li>So, instead of: </li></ul><ul><li>db_query(&quot;SELECT * FROM {users} WHERE name = '$username' &quot;); </li></ul><ul><li>You would want to write this: </li></ul><ul><li>db_query(&quot;SELECT * FROM {users} WHERE name = '%s' &quot;, $username); </li></ul><ul><li>Also, use db_rewrite_sql to respect node access restrictions: </li></ul><ul><li>$result = db_query(db_rewrite_sql(&quot;SELECT n.nid, n.title FROM {node} n&quot;)); </li></ul>
  10. 10. Prevent SQL Injection in Wordpress <ul><li>Wordpress has a database object that supports prepared statements and will escape the values for you. </li></ul><ul><li>$sql  =  $wpdb -> prepare (  'query' [,  value_parameter ,  value_parameter  ... ] );   </li></ul><ul><li>Additionally,  the $wpdb object will escape data for you. </li></ul><ul><li>$wpdb -> insert ( $table, (array) $data ); </li></ul><ul><li>$wpdb -> update (  $table, (array) $data, (array) $where ); </li></ul><ul><li>$data should be unescaped. Keys are columns, Values are values.  $where should be unescaped. Multiple WHERE conditions are ANDed together. </li></ul>
  11. 11. Any Questions?