4. What is it?
• Indirect way of attacking an application
• Malicious SQL gets saved into the database
• SQL is used in another query elsewhere
• Example:
1. Create a user
2. Change the users password
7. Recommendations
• Perform InputValidation on all user-supplied data w/Whitelist
• Use parameterized queries
• Use stored procedures instead of dynamic SQL
• Consider using an Object-Relational Mapping tool
8. Action #1: InputValidation with Whitelist
• Code Example
<?php
//function should be a white list of only input that is known to be good
$safeValue = $check_if_value_is_permitted($_GET[‘name’);
if(!$safeValue)
$stmt = $dbh->prepare("INSERT INTO CustomersDB (name, value)VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
// insert one row
$name = ’1’;
$value = $safeValue;
$stmt->execute();
9. Action #2: Use Parameterized Queries
• Code Example
<?php
$stmt = $dbh->prepare("INSERT INTO CustomersDB (name, value)VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
// insert one row
$name = 'one';
$value = 1;
$stmt->execute();
//By using this method the parameters are never bound directly to the query but sent
after the execute method is called
10. Action #3: Use Stored Procedures
• Code Example
<?php
$stmt = $dbh->prepare("CALL sp_returns_cust_count (?)");
$stmt->bindParam(1, $return_value, PDO::PARAM_INT, 1);
// call the stored procedure
$stmt->execute();
print "procedure returned $return_valuen";
?>
//Parameters must still be bound in this example and will prevent the same type of
SQL injection attack
12. Exploit
Code Review: SQL InjectionVuln
6 $query = "SELECT * FROM listings WHERE id = ".$_GET['id'];
7 //Vulnerability exists at line 8
8 $result = mysql_query($query);
• SQL injection occurs when:
1. Data enters an application from an untrusted source
2. The data is used to dynamically construct a SQL query
• An attacker could pass: 1’ OR 1=1 -> to id variable would be
the same as returning all the listings
• Even worse, an attacker could pass 1’; DROP table listings
which would delete the listing table
13. Code Review: Remediation Steps
6 $_GET['id'] = str_replace("/", "", $_SERVER['PATH_INFO']);
7 // Step 1: InputValidation: Check id against allowed whitelist if possible
8 $safeValue = $validateInput($_GET[‘id’];
6 // Step 2: Use positional parameter in query
5 $listing_id = intval($safeValue);
6 $query = "SELECT * FROM listings WHERE id = ?
7 //Step 3: Use mysqli() instead of mysql_query()
8 $stmt = $mysqli - > prepare($query);
9 //Step 4: Bind parameter
10 $stmt -> bind_param(1, $listing_id);
11 $stmt -> execute();
✔
✔
✔
✔
14. Email (1/2)
Dear Customer XYZ,
My name is Joshua Clark and I will be assisting you with the review of your scan. After reviewing the source code we identified a
SQL injection vulnerability within the code that you provided.The vulnerability exists on line 7 of source_file.php. See below:
7: $result = mysql_query($query);
SQL injection occurs when:
1) Data enters an application from an untrusted source
2)The data is used to dynamically construct a SQL query
In this case data is passed to mysql_query() on line 7 from an untrusted source such as $_GET[‘id’]. An attacker could pass in
value of “1’ OR 1=1 into the id value which would result in the following query being executed:
SELECT * FROM listingsWHERE id = 1’ OR 1=1
This would result in returning all the rows from the database instead of just 1 record as expected.The attacker could also try to
do execute dangerous SQL commands by entering: 1’; DROP table listing;-- which would delete the listings table all together.
15. Email (2/2)
In order to prevent SQL injection we have the following recommendations for your code:
1) Perform InputValidation on all user-supplied variables
-> In the case above simply adding the ‘intval($_GET[‘id’]);’ will remove the SQL injection vulnerability but there may also be an
access control check needed here as well.
2) Use parameterized queries for dynamic queries
->When using dynamic SQL prepared statements eliminate SQL injection vulnerabilities
3) Use Stored Procedures when possible
4) Use the updated/recommended mysqli() function instead of mysql_query() function because it has many advantage over the
previous function such as:
-> Prepared Statements
-> Object-Oriented Interface
-> Enhanced Debugging Support
Regards,
Joshua S. Clark, CISSP
Application Security Consultant