IT tutorials
 
Database
 

SQL Injection : Code-Level Defenses - Using Parameterized Statements

2/14/2012 4:31:03 PM
- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
One of the root causes of SQL injection is the creation of SQL queries as strings that are then sent to the database for execution. This behavior, commonly known as dynamic string building or dynamic SQL, is one of the primary causes of an application being vulnerable to SQL injection.

As a more secure alternative to dynamic string building, most modern programming languages and database access application program interfaces (APIs) allow you to provide parameters to an SQL query through the use of placeholders, or bind variables, instead of working directly with the user input. Commonly known as parameterized statements, these are a safer alternative that can avoid or solve many of the common SQL injection issues you will see within an application, and you can use them in most common situations to replace an existing dynamic query. They also have the advantage of being very efficient on modern databases, as the database can optimize the query based on the supplied prepared statement, increasing the performance of subsequent queries.

I should note, however, that parameterized statements are a method of supplying potentially insecure parameters to the database, usually as a query or stored procedure call. They do not alter the content of the values that are passed to the database, though, so if the database functionality being called uses dynamic SQL within the stored procedure or function implementation it is still possible for SQL injection to occur. This has historically been a problem with Microsoft SQL Server and Oracle, both of which have shipped with a number of built-in stored procedures that were vulnerable to SQL injection in the past, and it is a danger that you should be aware of with any database stored procedures or functions that use dynamic SQL in their implementation. An additional issue to consider is that malicious content could have been stored in the database at this point that may then be used elsewhere in the application, causing SQL injection at another point in the application.

Here is an example of a vulnerable piece of login page pseudocode using dynamic SQL. We will discuss how to parameterize this code in Java, C#, and PHP in the following sections.

Username = request(“username”)
Password = request(“password”)
Sql = “SELECT * FROM users WHERE username='” + Username + “' AND password='”
+ Password + “'”
Result = Db.Execute(Sql)
If (Result) /* successful login */


Tools & Traps…

What Can Be Parameterized, and What Can't?

Not all dynamic SQL statements can be parameterized. In particular, you can parameterize only data values, and not SQL identifiers or keywords. Therefore, you can't have parameterized statements such as the following:

SELECT * FROM ? WHERE username = 'john'
SELECT ? FROM users WHERE username = 'john'
SELECT * FROM users WHERE username LIKE 'j%' ORDER BY ?

Unfortunately, a common solution presented in online forums to solve this problem is to use dynamic SQL in the string that is then used to parameterize the query, as in the following example:

String sql = “SELECT * FROM ” + tblName + “ WHERE user =?”;

In this case, you can end up introducing an SQL injection issue where there previously wasn't one by trying to parameterize a statement.

In general, if you're trying to supply an SQL identifier as a parameter, you should look at your SQL and how you're accessing your database first, and then look at whether it is possible to rewrite the query using a fixed identifier. Although it may be possible to solve this through the use of dynamic SQL, this is also likely to adversely affect the performance of the query, as the database will not be able to optimize the query.


Parameterized Statements in Java

Java provides the Java Database Connectivity (JDBC) framework (implemented in the java.sql and javax.sql namespaces) as a vendor-independent method of accessing databases. JDBC supports a rich variety of data access methods, including the ability to use parameterized statements through the PreparedStatement class.

Here is the earlier vulnerable example rewritten using a JDBC prepared statement. Note that when the parameters are added (through the use of the various set<type> functions, such as setString), the index position (starting at 1) of the placeholder question mark is specified.

Connection con = DriverManager.getConnection(connectionString);
String sql = “SELECT * FROM users WHERE username=? AND password=?”;
PreparedStatement lookupUser = con.prepareStatement(sql);
// Add parameters to SQL query
lookupUser.setString(1, username); // add String to position 1
lookupUser.setString(2, password); // add String to position 2
rs = lookupUser.executeQuery();

In addition to the JDBC framework that is provided with Java, additional packages are often used to access databases efficiently within J2EE applications. A commonly used persistence framework for accessing databases is Hibernate.

Although it is possible to utilize native SQL functionality, as well as the JDBC functionality shown earlier, Hibernate also provides its own functionality for binding variables to a parameterized statement. Methods are provided on the Query object to use either named parameters (specified using a colon; e.g., :parameter) or the JDBC-style question mark placeholder (?).

The following example demonstrates the use of Hibernate with named parameters:

String sql = “SELECT * FROM users WHERE username=:username AND” +
“password=:password”;
Query lookupUser = session.createQuery(sql);
// Add parameters to SQL query
lookupUser.setString(“username”, username); // add username
lookupUser.setString(“password”, password); // add password
List rs = lookupUser.list();

The next example shows the use of Hibernate with JDBC-style question mark placeholders for the parameters. Note that Hibernate indexes parameters from 0, and not 1, as does JDBC. Therefore, the first parameter in the list will be 0 and the second will be 1.

String sql = “SELECT * FROM users WHERE username=? AND password=?”;
Query lookupUser = session.createQuery(sql);
// Add parameters to SQL query
lookupUser.setString(0, username); // add username
lookupUser.setString(1, password); // add password
List rs = lookupUser.list();

Parameterized Statements in .NET (C#)

Microsoft .NET provides access to a number of different ways to parameterize statements by using the ADO.NET Framework. ADO.NET also provides additional functionality, allowing you to further check the parameters supplied, such as by type-checking the data you are passing in.

ADO.NET provides four different data providers, depending on the type of database that is being accessed: System.Data.SqlClient for Microsoft SQL Server, System.Data.OracleClient for Oracle databases, and System.Data.OleDb and System.Data.Odbc for OLE DB and ODBC data sources, respectively. Which provider you use will depend on the database server and drivers being used to access the database. Unfortunately, the syntax for utilizing parameterized statements differs among the providers, notably in how the statement and parameters are specified. Table 1 shows how parameters are specified in each provider.

Table 1. ADO.NET Data Providers, and Parameter Naming Syntax
Data ProviderParameter Syntax
System.Data.SqlClient@parameter
System.Data.OracleClient:parameter (only in parameterized SQL command text)
System.Data.OleDbPositional parameters with a question mark placeholder (?)
System.Data.OdbcPositional parameters with a question mark placeholder (?)

The following example shows the vulnerable example query rewritten as a parameterized statement in .NET using the SqlClient provider:

SqlConnection con = new SqlConnection(ConnectionString);
string Sql = “SELECT * FROM users WHERE username=@username” +
“AND password=@password”;
cmd = new SqlCommand(Sql, con);
// Add parameters to SQL query
cmd.Parameters.Add(“@username”, // name
SqlDbType.NVarChar, // data type
16); // length
cmd.Parameters.Add(“@password”,
SqlDbType.NVarChar,
16);
cmd.Parameters.Value[“@username”] = username; // set parameters
cmd.Parameters.Value[“@password”] = password; // to supplied values
reader = cmd.ExecuteReader();

The next example shows the same parameterized statement in .NET using the OracleClient provider. Note that the parameters are preceded by a colon in the command text (the Sql string), but not elsewhere in the code.

OracleConnection con = new OracleConnection(ConnectionString);
string Sql = “SELECT * FROM users WHERE username=:username” +
“AND password=:password”;
cmd = new OracleCommand(Sql, con);
// Add parameters to SQL query
cmd.Parameters.Add(“username”, // name
OracleType.VarChar, // data type
16); // length
cmd.Parameters.Add(“password”,
OracleType.VarChar,
16);
cmd.Parameters.Value[“username”] = username; // set parameters
cmd.Parameters.Value[“password”] = password; // to supplied values
reader = cmd.ExecuteReader();

The final example shows the same parameterized statement in .NET using the OleDbClient provider. When using the OleDbClient provider, or the Odbc provider, you must add parameters in the correct order for the placeholder question marks.

OleDbConnection con = new OleDbConnection(ConnectionString);
string Sql = “SELECT * FROM users WHERE username=? AND password=?”;
cmd = new OleDbCommand(Sql, con);
// Add parameters to SQL query
cmd.Parameters.Add(“@username”, // name
OleDbType.VarChar, // data type
16); // length
cmd.Parameters.Add(“@password”,
OleDbType.VarChar,
16));
cmd.Parameters.Value[“@username”] = username; // set parameters
cmd.Parameters.Value[“@password”] = password; // to supplied values
reader = cmd.ExecuteReader();

Tip

When using parameterized statements with ADO.NET, it is possible to specify less or more detail about the statement than I did in the preceding example. For instance, you can specify just the name and the value in the parameter constructor. In general, it is a good security practice to specify parameters as I did, including the data size and type, because this provides an additional level of coarse-grained validation over the data that is being passed to the database.


Parameterized Statements in PHP

PHP also has a number of frameworks that you can use to access a database. I'll demonstrate three of the most common frameworks in this section: the mysqli package for accessing MySQL databases, the PEAR::MDB2 package (which superseded the popular PEAR::DB package), and the new PHP Data Objects (PDO) framework, all of which provide facilities for using parameterized statements.

The mysqli package, available with PHP 5.x and able to access MySQL 4.1 and later databases, is one of the most commonly used database interfaces, and supports parameterized statements through the use of placeholder question marks. The following example shows a parameterized statement using the mysqli package:

$con = new mysqli(“localhost”, “username”, “password”, “db”);
$sql = “SELECT * FROM users WHERE username=? AND password=?”;
$cmd = $con->prepare($sql);
// Add parameters to SQL query
$cmd->bind_param(“ss”, $username, $password); // bind parameters as strings
$cmd->execute();


The PEAR::MDB2 package is a widely used and vendor-independent framework for accessing databases. MDB2 supports named parameters using the colon character and using placeholder question marks. The following example demonstrates the use of MDB2 with placeholder question marks to build a parameterized statement. Note that the data and types are passed in as an array which maps to the placeholders in the query.

$mdb2 =& MDB2::factory($dsn);
$sql = “SELECT * FROM users WHERE username=? AND password=?”;
$types = array('text', 'text'); // set data types
$cmd = $mdb2->prepare($sql, $types, MDB2_PREPARE_MANIP);
$data = array($username, $password); // parameters to be passed
$result = $cmd->execute($data);


The PDO package, which is included with PHP 5.1 and later, is an object-oriented vendor-independent data layer for accessing databases. PDO supports both named parameters using the colon character and the use of placeholder question marks. The following example demonstrates the use of PDO with named parameters to build a parameterized statement:

$sql = “SELECT * FROM users WHERE username=:username AND” +
“password=:password”;
$stmt = $dbh->prepare($sql);
// bind values and data types
$stmt->bindParam(':username', $username, PDO::PARAM_STR, 12);
$stmt->bindParam(':password', $password, PDO::PARAM_STR, 12);
$stmt->execute();

Parameterized Statements in PL/SQL

Oracle PL/SQL offers also the possibility of using parameterized queries in database-level code. PL/SQL supports binding parameters using the colon character with an index (e.g., :1). The following example demonstrates the use of PL/SQL with bound parameters to build a parameterized statement in an anonymous PL/SQL block:

DECLARE
username varchar2(32);
password varchar2(32);
result integer;
BEGIN
Execute immediate 'SELECT count(*) FROM users where username=:1 and
password=:2' into result using username,password;
END;
 
Others
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
Technology FAQ
- Is possible to just to use a wireless router to extend wireless access to wireless access points?
- Ruby - Insert Struct to MySql
- how to find my Symantec pcAnywhere serial number
- About direct X / Open GL issue
- How to determine eclipse version?
- What SAN cert Exchange 2010 for UM, OA?
- How do I populate a SQL Express table from Excel file?
- code for express check out with Paypal.
- Problem with Templated User Control
- ShellExecute SW_HIDE
programming4us programming4us