This site is the archived OWASP Foundation Wiki and is no longer accepting Account Requests.
To view the new OWASP Foundation website, please visit https://owasp.org

Difference between revisions of "OWASP Backend Security Project PHP Preventing SQL Injection"

From OWASP
Jump to: navigation, search
(Examples)
 
(9 intermediate revisions by one other user not shown)
Line 69: Line 69:
  
 
?></nowiki>
 
?></nowiki>
 
 
=== Source Code Exposure ===
 
 
As you can see ''login.php'' include ''db.inc'' to use ''iMysqlConnect'' whose aims is to
 
return a resource link to backend MySQL engine. Since ''.inc'' files are not rendered
 
by WEB Server through the ''PHP Module'' an evil user may retrieve it's content as shown
 
in the following images:
 
 
[[Image:Owasp_bsp_php_2.jpg]]
 
 
 
=== Authentication Bypass ===
 
 
 
On our examples user credentials are passed to ''login.php'' wich in turns call the following
 
PHP function:
 
 
 
<nowiki>
 
function sAuthenticateUser($username, $password){
 
  $authenticatedUserName="";
 
  if ($link = iMysqlConnect()) {
 
 
    $query  = "SELECT username FROM users";
 
    $query .=                " WHERE username = '".$username."'";
 
    $query .=                " AND  password = md5('".$password."')";
 
    $result = mysql_query($query);
 
 
    if ($result) {
 
      if ($row = mysql_fetch_row($result)) {
 
      $authenticatedUserName =  $row[0];
 
      }
 
    }
 
  }
 
 
  return $authenticatedUserName;
 
 
}
 
</nowiki>
 
 
When user ''larry'' authenticate the following SQL Query it's executed:
 
* SELECT username FROM users WHERE username='larry' AND password=md5('larry')
 
 
Breaking such an authentication schema is quite simple, since we need to :
 
 
* truncate backend authentication query
 
* injection a boolean expression to override WHERE clausole
 
 
 
* On MySQL ''#'' is used as a comment character then whatever follows is discarderd from the engine.
 
* Since our WHERE clausole is something like ''expr AND expr'' we can override it by adding an identity expresssion (E.g.: OR 1=1)
 
 
 
It follows that authentication can be bypassed by supplying the following credentials:
 
* username: ''' OR 1=1#''
 
* password: ''password''
 
 
* username: ''username''
 
* password: ''') OR 1=1 #''
 
 
 
=== User Enumeration ===
 
 
We learned on previous section that an evil user can bypass authentication schema by supplying
 
the following credentials:
 
 
* username: '''OR 1=1#''
 
* password: ''password''
 
 
Let'say again what does ''sAuthenticateUser'' performs:
 
 
<nowiki>
 
function sAuthenticateUser($username, $password){
 
  $authenticatedUserName="";
 
  if ($link = iMysqlConnect()) {
 
 
    $query  = "SELECT username FROM users";
 
    $query .=                " WHERE username = '".$username."'";
 
    $query .=                " AND  password = md5('".$password."')";
 
    $result = mysql_query($query);
 
 
    if ($result) {
 
      if ($row = mysql_fetch_row($result)) {
 
      $authenticatedUserName =  $row[0];
 
      }
 
    }
 
  }
 
 
  return $authenticatedUserName;
 
 
}
 
</nowiki>
 
 
 
As you can see $query will contains the following SQL statement:
 
* SELECT username FROM users WHERE username = '' OR 1=1#' AND  password = md5('password')
 
 
wich in turns will be executed in:
 
 
<nowiki>
 
  $result = mysql_query($query); 
 
</nowiki>
 
 
By adding a ''LIMIT'' operator after the ''OR'' clausole we can index every valid user with the following
 
queries:
 
 
* SELECT username FROM users WHERE username = '' OR 1=1 LIMIT 0,1
 
* SELECT username FROM users WHERE username = '' OR 1=1 LIMIT 1,1
 
* SELECT username FROM users WHERE username = '' OR 1=1 LIMIT 2,1
 
* ''.... and so on''
 
 
We can accomplish the above task by supplying the following ''username/password'' pairs:
 
* username: ''' OR 1=1 LIMIT 0,1#''
 
* password: ''password''
 
 
 
* username: ''' OR 1=1 LIMIT 1,1#''
 
* password: ''password''
 
 
 
* username: ''' OR 1=1 LIMIT 2,1#''
 
* password: ''password''
 
 
  
 
== Online Catalog ==
 
== Online Catalog ==
Line 235: Line 111:
 
As in ''Login Form'' no input validation is performed and SQL Query can be manipulated to returns
 
As in ''Login Form'' no input validation is performed and SQL Query can be manipulated to returns
 
arbitrary data and DBMS stored relations/records/functions as well.
 
arbitrary data and DBMS stored relations/records/functions as well.
 
=== UNION SELECT Injection ===
 
 
Since our Application is vulnerable to SQL Injection attacks we can injection a ''UNION SELECT'' statement
 
to execute arbitrary expression agains remote backend system. Our first attempt will show how to retrieve
 
DBMS Fingerprint.
 
 
To this aim we need to set up a UNION SELECT injection wich in turns need to know how many expression are evaluated on original SELECT statement. Let'try:
 
 
* ''<nowiki>id=1 UNION ALL SELECT NULL# </nowiki>'' differs from original page (id=1)
 
* ''<nowiki>id=1 UNION ALL SELECT NULL,NULL# </nowiki>'' differs from original page (id=1)
 
* ''<nowiki>id=1 UNION ALL SELECT NULL,NULL,NULL# </nowiki>'' differs from original page (id=1)
 
* ''<nowiki>id=1 UNION ALL SELECT NULL,NULL,NULL,NULL# </nowiki>'' differs from original page (id=1)
 
* ''<nowiki>id=1 UNION ALL SELECT NULL,NULL,NULL,NULL,NULL# </nowiki>'' equals to original page (id=1)
 
 
Well we just guessed that original page (''id=1'') evaluates 5 expression on ''SELECT'' statement.
 
 
* Retrieve DBMS banner
 
*: ''id=1 UNION ALL SELECT NULL,version(),NULL,NULL,NULL LIMIT 1,1#"'
 
* Retrieve current user
 
*: ''id=1 UNION ALL SELECT NULL,user(),NULL,NULL,NULL LIMIT 1,1#''
 
 
 
=== BLIND SQL Injection ===
 
 
=== Backend Database Enumeration ===
 
 
 
 
== Message Board ==
 
  
 
= Application Security strategies =
 
= Application Security strategies =
Line 284: Line 130:
 
== Online Catalog ==
 
== Online Catalog ==
  
== Message Board ==
+
= Defeating Automated Tools =
  
 +
= References =
  
= Defeating Automated Tools =
+
= Tools =

Latest revision as of 08:41, 19 May 2008

Examples

To better understand how to secure code a PHP application some examples of vulnerable code is provided in this paragraph.

Login Form

On this example we're going to see a tipical Login Form. On our example WEB SITE user need to supply a username/password pair in order to be authenticated.


Here follows the authentcation form:

Owasp bsp php 1.jpg

Such a login page well call login.php with supplied user credentials.

 
<?php
include('./db.inc');

function sAuthenticateUser($username, $password){
  $authenticatedUserName="";
  if ($link = iMysqlConnect()) {

    $query  = "SELECT username FROM users";
    $query .=                " WHERE username = '".$username."'";
    $query .=                " AND   password = md5('".$password."')";
    $result = mysql_query($query);

    if ($result) {
      if ($row = mysql_fetch_row($result)) {
	$authenticatedUserName =  $row[0];
      }
    }
  }

  return $authenticatedUserName;

}

if ($sUserName = sAuthenticateUser($_POST["username"], 
				   $_POST["password"])) {
  echo "Wellcome ".$sUserName;
 } else {
  die('Unauthorized Access');
 }

?>

db.inc:

 

<?php

define('DB_HOST',     "localhost");
define('DB_USERNAME', "user");
define('DB_PASSWORD', "password");
define('DB_DATABASE', "owasp");


function iMysqlConnect(){
  $link = mysql_connect(DB_HOST,
  	  DB_USERNAME,
			DB_PASSWORD);

  if ($link && mysql_select_db(DB_DATABASE))
    return $link;
  return FALSE;
}

?>

Online Catalog

Let take another example: an Online Book Store:

Owasp bsp php 3.jpg



catalog.php:

 
function aGetBookEntry($id) {
  $aBookEntry = NULL;
  $link = iMysqlConnect();

  $query = "SELECT * FROM books WHERE id = $id";
  $result = mysql_query($query);

  if ($result) {
    if ($row = mysql_fetch_array($result)) {
      $aBookEntry = $row;
    }
  }

  return $aBookEntry;

}


$id = $_GET['id'];
$aBookEntry = aGetBookEntry($id);

showBook($aBookEntry);

Basicaly it retrieves id parameter on GET query string and perform the following SQL query:

  • SELECT * FROM book WHERE id = $_GET['id']

As in Login Form no input validation is performed and SQL Query can be manipulated to returns arbitrary data and DBMS stored relations/records/functions as well.

Application Security strategies

Hiding DBMS connection strings

Single Quotes Escape

Prepared Statement

Data Validation

Security in Depth

Examples Revisited

Login Form

Online Catalog

Defeating Automated Tools

References

Tools