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 "Injection Prevention Cheat Sheet"

From OWASP
Jump to: navigation, search
m (d)
m (Edit)
Line 50: Line 50:
 
!How to identify the issue during code review
 
!How to identify the issue during code review
 
!Remediation
 
!Remediation
!Example code
+
!Example code - Java
 
|-
 
|-
 
|SQL Injection
 
|SQL Injection
Line 83: Line 83:
 
|During code review please check for any queries to the database are not done via prepared statements.
 
|During code review please check for any queries to the database are not done via prepared statements.
 
If dynamic statements are being made please check if the data is sanitized before used as par of the statement.
 
If dynamic statements are being made please check if the data is sanitized before used as par of the statement.
 +
 +
Auditors should always look for uses of sp_execute, execute or exec within SQL Server stored procedures. Similar audit guidelines are necessary for similar functions for other vendors.
 
|<u>'''Defense Option 1: Prepared Statements (with Parameterized Queries)'''</u>
 
|<u>'''Defense Option 1: Prepared Statements (with Parameterized Queries)'''</u>
  
The use of prepared statements with variable binding (aka parameterized queries) is how all developers should first be taught how to write database queries. They are simple to write, and easier to understand than dynamic queries. Parameterized queries force the developer to first define all the SQL code, and then pass in each parameter to the query later. This coding style allows the database to distinguish between code and data, regardless of what user input is supplied.
+
Prepared statements ensure that an attacker is not able to change the intent of a query, even if SQL commands are inserted by an attacker. In the safe example below, if an attacker were to enter the userID of tom' or '1'='1, the parameterized query would not be vulnerable and would instead look for a username which literally matched the entire string tom' or '1'='1.
  
Prepared statements ensure that an attacker is not able to change the intent of a query, even if SQL commands are inserted by an attacker. In the safe example below, if an attacker were to enter the userID of tom' or '1'='1, the parameterized query would not be vulnerable and would instead look for a username which literally matched the entire string tom' or '1'='1.
+
'''<u>Defense Option 2: Stored Procedures</u>'''
 +
 
 +
The difference between prepared statements and stored procedures is that the SQL code for a stored procedure is defined and stored in the database itself, and then called from the application. Both of these techniques have the same effectiveness in preventing SQL injection so your organization should choose which approach makes the most sense for you. Stored procedures are not always safe from SQL injection. However, certain standard stored procedure programming constructs have the same effect as the use of parameterized queries when implemented safely* which is the norm for most stored procedure languages.
 +
 
 +
'''*Note:''' 'Implemented safely' means the stored procedure does not include any unsafe dynamic SQL generation.  
  
Language specific recommendations:
+
'''<u>Defense Option 3: White List Input Validation</u>'''
* Java EE – use PreparedStatement() with bind variables
 
* .NET – use parameterized queries like SqlCommand() or OleDbCommand() with bind variables
 
* PHP – use PDO with strongly typed parameterized queries (using bindParam())
 
* Hibernate - use createQuery() with bind variables (called named parameters in Hibernate)
 
* SQLite - use sqlite3_prepare() to create a [http://www.sqlite.org/c3ref/stmt.html statement object]
 
In rare circumstances, prepared statements can harm performance. When confronted with this situation, it is best to either a) strongly validate all data or b) escape all user supplied input using an escaping routine specific to your database vendor as described below, rather than using a prepared statement.
 
  
'''<u>Defense Option 2: Stored Procedures</u>'''
+
Various parts of SQL queries aren't legal locations for the use of bind variables, such as the names of tables or columns, and the sort order indicator (ASC or DESC). In such situations, input validation or query redesign is the most appropriate defense. For the names of tables or columns, ideally those values come from the code, and not from user parameters. But if user parameter values are used to make different for table names and column names, then the parameter values should be mapped to the legal/expected table or column names to make sure unvalidated user input doesn't end up in the query. Please note, this is a symptom of poor design and a full re-write should be considered if time allows.
  
Stored procedures are not always safe from SQL injection. However, certain standard stored procedure programming constructs have the same effect as the use of parameterized queries when implemented safely* which is the norm for most stored procedure languages. They require the developer to just build SQL statements with parameters which are automatically parameterized unless the developer does something largely out of the norm. The difference between prepared statements and stored procedures is that the SQL code for a stored procedure is defined and stored in the database itself, and then called from the application. Both of these techniques have the same effectiveness in preventing SQL injection so your organization should choose which approach makes the most sense for you.
+
'''<u>Defense Option 4: Escaping All User-Supplied Input</u>'''
  
<nowiki>*</nowiki>Note: 'Implemented safely' means the stored procedure does not include any unsafe dynamic SQL generation. Developers do not usually generate dynamic SQL inside stored procedures. However, it can be done, but should be avoided. If it can't be avoided, the stored procedure must use input validation or proper escaping as described in this article to make sure that all user supplied input to the stored procedure can't be used to inject SQL code into the dynamically generated query. Auditors should always look for uses of sp_execute, execute or exec within SQL Server stored procedures. Similar audit guidelines are necessary for similar functions for other vendors.
+
This technique should only be used as a last resort, when none of the above are feasible. Input validation is probably a better choice as this methodology is frail compared to other defenses and we cannot guarantee it will prevent all SQL Injection in all situations.
  
There are also several cases where stored procedures can increase risk. For example, on MS SQL server, you have 3 main default roles: db_datareader, db_datawriter and db_owner. Before stored procedures came into use, DBA's would give db_datareader or db_datawriter rights to the webservice's user, depending on the requirements. However, stored procedures require execute rights, a role that is not available by default. Some setups where the user management has been centralized, but is limited to those 3 roles, cause all web apps to run under db_owner rights so stored procedures can work. Naturally, that means that if a server is breached the attacker has full rights to the database, where previously they might only have had read-access. More on this topic here. http://www.sqldbatips.com/showarticle.asp?ID=8
+
This technique is to escape user input before putting it in a query. It's usually only recommended to retrofit legacy code when implementing input validation isn't cost effective.  
  
 
|
 
|
Line 109: Line 109:
 
The following code example uses a PreparedStatement, Java's implementation of a parameterized query, to execute the same database query.
 
The following code example uses a PreparedStatement, Java's implementation of a parameterized query, to execute the same database query.
 
   String custname = request.getParameter("customerName"); // This should REALLY be validated too // perform input validation to detect attacks String query = "SELECT account_balance FROM user_data WHERE user_name = ? ";  '''PreparedStatement pstmt = connection.prepareStatement( query );''' '''pstmt.setString( 1, custname);'''  ResultSet results = pstmt.executeQuery( );  
 
   String custname = request.getParameter("customerName"); // This should REALLY be validated too // perform input validation to detect attacks String query = "SELECT account_balance FROM user_data WHERE user_name = ? ";  '''PreparedStatement pstmt = connection.prepareStatement( query );''' '''pstmt.setString( 1, custname);'''  ResultSet results = pstmt.executeQuery( );  
; Safe C# .NET Prepared Statement Example
+
We have shown examples in Java, but practically all other languages, including Cold Fusion, and Classic ASP, support parameterized query interfaces.  
With .NET, it's even more straightforward. The creation and execution of the query doesn't change. All you have to do is simply pass the parameters to the query using the Parameters.Add() call as shown here.
 
  String query =  "SELECT account_balance FROM user_data WHERE user_name = ?"; try { OleDbCommand command = new OleDbCommand(query, connection); '''command.Parameters.Add(new OleDbParameter("customerName", CustomerName Name.Text));''' OleDbDataReader reader = command.ExecuteReader(); // … } catch (OleDbException se) { // error handling }
 
We have shown examples in Java and .NET but practically all other languages, including Cold Fusion, and Classic ASP, support parameterized query interfaces. Even SQL abstraction layers, like the [http://www.hibernate.org/ Hibernate Query Language] (HQL) have the same type of injection problems (which we call [http://cwe.mitre.org/data/definitions/564.html HQL Injection]). HQL supports parameterized queries as well, so we can avoid this problem:
 
; Hibernate Query Language (HQL) Prepared Statement (Named Parameters) Examples
 
  First is an unsafe HQL Statement  Query unsafeHQLQuery = session.createQuery("from Inventory where productID='"+userSuppliedParameter+"'");  Here is a safe version of the same query using named parameters  Query safeHQLQuery = session.createQuery("from Inventory where productID=:productid"); safeHQLQuery.setParameter("productid", userSuppliedParameter);
 
For examples of parameterized queries in other languages, including Ruby, PHP, Cold Fusion, and Perl, see the [[Query Parameterization Cheat Sheet]] or http://bobby-tables.com/.
 
 
 
Developers tend to like the Prepared Statement approach because all the SQL code stays within the application. This makes your application relatively database independent.
 
 
 
 
; Safe Java Stored Procedure Example
 
; Safe Java Stored Procedure Example
 
The following code example uses a CallableStatement, Java's implementation of the stored procedure interface, to execute the same database query. The "sp_getAccountBalance" stored procedure would have to be predefined in the database and implement the same functionality as the query defined above.
 
The following code example uses a CallableStatement, Java's implementation of the stored procedure interface, to execute the same database query. The "sp_getAccountBalance" stored procedure would have to be predefined in the database and implement the same functionality as the query defined above.
 
   String custname = request.getParameter("customerName"); // This should REALLY be validated try { '''CallableStatement cs = connection.prepareCall("{call sp_getAccountBalance(?)}");''' '''cs.setString(1, custname);''' ResultSet results = cs.executeQuery(); // … result set handling  } catch (SQLException se) { // … logging and error handling }  
 
   String custname = request.getParameter("customerName"); // This should REALLY be validated try { '''CallableStatement cs = connection.prepareCall("{call sp_getAccountBalance(?)}");''' '''cs.setString(1, custname);''' ResultSet results = cs.executeQuery(); // … result set handling  } catch (SQLException se) { // … logging and error handling }  
; Safe VB .NET Stored Procedure Example
 
The following code example uses a SqlCommand, .NET’s implementation of the stored procedure interface, to execute the same database query. The "sp_getAccountBalance" stored procedure would have to be predefined in the database and implement the same functionality as the query defined above.
 
  Try Dim command As SqlCommand = new SqlCommand("sp_getAccountBalance", connection) '''command.CommandType = CommandType.StoredProcedure''' '''command.Parameters.Add(new SqlParameter("@CustomerName", CustomerName.Text))''' Dim reader As SqlDataReader = command.ExecuteReader() ‘ … Catch se As SqlException  ‘ error handling End Try
 
  
 
|}
 
|}
Line 137: Line 125:
 
!Example code - Java
 
!Example code - Java
 
|-
 
|-
|Command Injection
+
|LDAP Injection
|Appending a semicolon to the end of a URL query parameter followed by an operating system command, will execute the command. %3B is url encoded and decodes to semicolon. This is because the ; is interpreted as a command separator.
+
|
Example: <nowiki>http://sensitive/something.php?dir=%3Bcat%20/etc/passwd</nowiki>
+
|
 
+
|
If the applucation responds with the output of the /etc/passwd file then you know the attack has been successful.
+
|
 
+
|
Many web application scanners can be used to test for this attack as they inject variations of command injections and test the response.
 
 
 
Equally Static Code Analysis tools check the data flow of untrusted user input into a web application and check if the data is then entered into a dangerous method which executes the user input as a command.
 
|Appending a semicolon to the end of a URL query parameter followed by an operating system command, will execute the command. %3B is url encoded and decodes to semicolon. This is because the ; is interpreted as a command separator.
 
Example: http://sensitive/something.php?dir=%3Bcat%20/etc/passwd
 
 
 
If the applucation responds with the output of the /etc/passwd file then you know the attack has been successful.
 
 
 
Many web application scanners can be used to test for this attack as they inject variations of command injections and test the response.
 
 
 
Equally Static Code Analysis tools check the data flow of untrusted user input into a web application and check if the data is then entered into a dangerous method which executes the user input as a command.
 
|During code review, check if any command execute methods are called and in unvalidated user input are taken as data for that command.
 
|If it is considered unavoidable the call to a system command incorporated with user-supplied, the following two layers of defense should be used within software in order to prevent attacks
 
# '''Parametrization''' - If available, use structured mechanisms that automatically enforce the separation between data and command. These mechanisms can help to provide the relevant quoting, encoding.
 
# '''Input validation''' - the values for commands and the relevant arguments should be both validated. There are different degrees of validation for the actual command and its arguments:
 
#* When it comes to the '''commands''' used, these must be validated against a whitelist of allowed commands.
 
#* In regards to the '''arguments''' used for these commands, they should be validated using the following options:
 
#** Positive or “whitelist” input validation - where are the arguments allowed explicitly defined
 
#** White list Regular Expression - where is explicitly defined a whitelist of good characters allowed and the maximum length of the string. Ensure that metacharacters like & |  ; $ > < ` \ ! and white-spaces are not part of the Regular Expression. For example, the following regular expression only allows lowercase letters and numbers, and does not contain metacharacters. The length is also being limited to 3-10 characters:
 
  ^[a-z0-9]{3,10}$
 
|'''''incorrect Usage'''''
 
ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe -arg1 -arg2");
 
In this example, the command together with the arguments are passed as a one string, making easy to manipulate that expression and inject malicious strings.
 
 
 
'''''Correct Usage'''''
 
 
 
Here is an example that starts a process with a modified working directory. The command and each of the arguments are passed separately. This make it easy to validated each term and reduces the risk to insert malicious strings.
 
ProcessBuilder pb = new ProcessBuilder("TrustedCmd", "TrustedArg1", "TrustedArg2"); Map<String, String> env = pb.environment(); pb.directory(new File("TrustedDir")); Process p = pb.start();
 
 
|}
 
|}
  
Line 182: Line 142:
 
!Example code - Java
 
!Example code - Java
 
|-
 
|-
|Command Injection
+
|XPath Injection
|Appending a semicolon to the end of a URL query parameter followed by an operating system command, will execute the command. %3B is url encoded and decodes to semicolon. This is because the ; is interpreted as a command separator.
+
|
Example: <nowiki>http://sensitive/something.php?dir=%3Bcat%20/etc/passwd</nowiki>
+
|
 
+
|
If the applucation responds with the output of the /etc/passwd file then you know the attack has been successful.
+
|
 
+
|
Many web application scanners can be used to test for this attack as they inject variations of command injections and test the response.
 
 
 
Equally Static Code Analysis tools check the data flow of untrusted user input into a web application and check if the data is then entered into a dangerous method which executes the user input as a command.
 
|Appending a semicolon to the end of a URL query parameter followed by an operating system command, will execute the command. %3B is url encoded and decodes to semicolon. This is because the ; is interpreted as a command separator.
 
Example: http://sensitive/something.php?dir=%3Bcat%20/etc/passwd
 
 
 
If the applucation responds with the output of the /etc/passwd file then you know the attack has been successful.
 
 
 
Many web application scanners can be used to test for this attack as they inject variations of command injections and test the response.
 
 
 
Equally Static Code Analysis tools check the data flow of untrusted user input into a web application and check if the data is then entered into a dangerous method which executes the user input as a command.
 
|During code review, check if any command execute methods are called and in unvalidated user input are taken as data for that command.
 
|If it is considered unavoidable the call to a system command incorporated with user-supplied, the following two layers of defense should be used within software in order to prevent attacks
 
# '''Parametrization''' - If available, use structured mechanisms that automatically enforce the separation between data and command. These mechanisms can help to provide the relevant quoting, encoding.
 
# '''Input validation''' - the values for commands and the relevant arguments should be both validated. There are different degrees of validation for the actual command and its arguments:
 
#* When it comes to the '''commands''' used, these must be validated against a whitelist of allowed commands.
 
#* In regards to the '''arguments''' used for these commands, they should be validated using the following options:
 
#** Positive or “whitelist” input validation - where are the arguments allowed explicitly defined
 
#** White list Regular Expression - where is explicitly defined a whitelist of good characters allowed and the maximum length of the string. Ensure that metacharacters like & |  ; $ > < ` \ ! and white-spaces are not part of the Regular Expression. For example, the following regular expression only allows lowercase letters and numbers, and does not contain metacharacters. The length is also being limited to 3-10 characters:
 
  ^[a-z0-9]{3,10}$
 
|'''''incorrect Usage'''''
 
ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe -arg1 -arg2");
 
In this example, the command together with the arguments are passed as a one string, making easy to manipulate that expression and inject malicious strings.
 
 
 
'''''Correct Usage'''''
 
 
 
Here is an example that starts a process with a modified working directory. The command and each of the arguments are passed separately. This make it easy to validated each term and reduces the risk to insert malicious strings.
 
ProcessBuilder pb = new ProcessBuilder("TrustedCmd", "TrustedArg1", "TrustedArg2"); Map<String, String> env = pb.environment(); pb.directory(new File("TrustedDir")); Process p = pb.start();
 
 
|}
 
|}
  

Revision as of 16:10, 14 November 2017

Cheatsheets-header.jpg

Last revision (mm/dd/yy): 11/14/2017

Introduction

This article is focused on providing clear, simple, actionable guidance for preventing the entire category of Injection flaws in your applications. Injection attacks, especially SQL Injection, are unfortunately very common.

Application accessibility is a very important factor in protection and prevention of injection flaws. Only the minority of all applications within a company/enterprise are developed in house, where as most applications are from external sources. Open source applications give at least the opportunity to fix problems, but closed source applications need a different approach to injection flaws.

Injection flaws occur when an application sends untrusted data to an interpreter. Injection flaws are very prevalent, particularly in legacy code, often found in SQL queries, LDAP queries, XPath queries, OS commands, program arguments, etc. Injection flaws are easy to discover when examining code, but more difficult via testing. Scanners and fuzzers can help attackers find them.

Depending on the accessibility different actions must be taken in order to fix them. It is always the best way to fix the problem in source code itself, or even redesign some parts of the applications. But if the source code is not available or it is simply uneconomical to fix legacy software only virtual patching makes sense.

Application Types

Three classes of applications can usually be seen within a company. Those 3 types are needed to identify the actions which need to take place in order to prevent/fix injection flaws.

A1: New Application

A new web application in the design phase, or in early stage development.

A2: Productive Open Source Application

An already productive application, which can be easily adapted. A Model-View-Controller (MVC) type application is just one example of having a easily accessible application architecture.

A3: Productive Closed Source Application

A productive application which cannot or only with difficulty be modified.

Forms of Injection

There are several forms of injection targeting different technologies including SQL queries, LDAP queries, XPath queries and OS commands.

Query languages

The most famous form of injection is SQL Injection where an attacker can modify existing database queries. For more information see the SQL Injection Prevention Cheat Sheet.

But also LDAP, SOAP, XPath and REST based queries can be susceptible to injection attacks allowing for data retrieval or control bypass.

SQL Injection

Issue Name Description How to test for the issue How to identify the issue during code review Remediation Example code - Java
SQL Injection An SQL injection attack consists of insertion or "injection" of either a partial or complete SQL query via the data input or transmitted from the client (browser) to the web application. A successful SQL injection attack can read sensitive data from the database, modify database data (insert/update/delete), execute administration operations on the database (such as shutdown the DBMS), recover the content of a given file existing on the DBMS file system or write files into the file system, and, in some cases, issue commands to the operating system. SQL injection attacks are a type of injection attack, in which SQL commands are injected into data-plane input in order to affect the execution of predefined SQL commands.

SQL Injection attacks can be divided into the following three classes:

  • Inband: data is extracted using the same channel that is used to inject the SQL code. This is the most straightforward kind of attack, in which the retrieved data is presented directly in the application web page.
  • Out-of-band: data is retrieved using a different channel (e.g., an email with the results of the query is generated and sent to the tester).
  • Inferential or Blind: there is no actual transfer of data, but the tester is able to reconstruct the information by sending particular requests and observing the resulting behavior of the DB Server.
Automated Exploitation

Most of the situation and techniques below here can be performed in a automated way using some tools. In this article the tester can find information how to perform an automated auditing using SQLMap:

https://www.owasp.org/index.php/Automated_Audit_using_SQLMap

Equally Static Code Analysis Data flow rules can detect of unsanitized user controlled input can change the SQL query.

Stored Procedure Injection

When using dynamic SQL within a stored procedure, the application must properly sanitize the user input to eliminate the risk of code injection. If not sanitized, the user could enter malicious SQL that will be executed within the stored procedure.

Time delay Exploitation technique

The time delay exploitation technique is very useful when the tester find a Blind SQL Injection situation, in which nothing is known on the outcome of an operation. This technique consists in sending an injected query and in case the conditional is true, the tester can monitor the time taken to for the server to respond. If there is a delay, the tester can assume the result of the conditional query is true. This exploitation technique can be different from DBMS to DBMS (check DBMS specific section).

http://www.example.com/product.php?id=10 AND IF(version() like ‘5%’, sleep(10), ‘false’))--

In this example the tester if checking whether the MySql version is 5.x or not, making the server to delay the answer by 10 seconds. The tester can increase the delay time and monitor the responses. The tester also doesn’t need to wait for the response. Sometimes he can set a very high value (e.g. 100) and cancel the request after some seconds.

Out of band Exploitation technique

This technique is very useful when the tester find a Blind SQL Injection situation, in which nothing is known on the outcome of an operation. The technique consists of the use of DBMS functions to perform an out of band connection and deliver the results of the injected query as part of the request to the tester’s server. Like the error based techniques, each DBMS has its own functions. Check for specific DBMS section.

During code review please check for any queries to the database are not done via prepared statements.

If dynamic statements are being made please check if the data is sanitized before used as par of the statement.

Auditors should always look for uses of sp_execute, execute or exec within SQL Server stored procedures. Similar audit guidelines are necessary for similar functions for other vendors.

Defense Option 1: Prepared Statements (with Parameterized Queries)

Prepared statements ensure that an attacker is not able to change the intent of a query, even if SQL commands are inserted by an attacker. In the safe example below, if an attacker were to enter the userID of tom' or '1'='1, the parameterized query would not be vulnerable and would instead look for a username which literally matched the entire string tom' or '1'='1.

Defense Option 2: Stored Procedures

The difference between prepared statements and stored procedures is that the SQL code for a stored procedure is defined and stored in the database itself, and then called from the application. Both of these techniques have the same effectiveness in preventing SQL injection so your organization should choose which approach makes the most sense for you. Stored procedures are not always safe from SQL injection. However, certain standard stored procedure programming constructs have the same effect as the use of parameterized queries when implemented safely* which is the norm for most stored procedure languages.

*Note: 'Implemented safely' means the stored procedure does not include any unsafe dynamic SQL generation.

Defense Option 3: White List Input Validation

Various parts of SQL queries aren't legal locations for the use of bind variables, such as the names of tables or columns, and the sort order indicator (ASC or DESC). In such situations, input validation or query redesign is the most appropriate defense. For the names of tables or columns, ideally those values come from the code, and not from user parameters. But if user parameter values are used to make different for table names and column names, then the parameter values should be mapped to the legal/expected table or column names to make sure unvalidated user input doesn't end up in the query. Please note, this is a symptom of poor design and a full re-write should be considered if time allows.

Defense Option 4: Escaping All User-Supplied Input

This technique should only be used as a last resort, when none of the above are feasible. Input validation is probably a better choice as this methodology is frail compared to other defenses and we cannot guarantee it will prevent all SQL Injection in all situations.

This technique is to escape user input before putting it in a query. It's usually only recommended to retrofit legacy code when implementing input validation isn't cost effective.

Safe Java Prepared Statement Example

The following code example uses a PreparedStatement, Java's implementation of a parameterized query, to execute the same database query.

 String custname = request.getParameter("customerName"); // This should REALLY be validated too // perform input validation to detect attacks String query = "SELECT account_balance FROM user_data WHERE user_name = ? ";  PreparedStatement pstmt = connection.prepareStatement( query ); pstmt.setString( 1, custname);  ResultSet results = pstmt.executeQuery( ); 

We have shown examples in Java, but practically all other languages, including Cold Fusion, and Classic ASP, support parameterized query interfaces.

Safe Java Stored Procedure Example

The following code example uses a CallableStatement, Java's implementation of the stored procedure interface, to execute the same database query. The "sp_getAccountBalance" stored procedure would have to be predefined in the database and implement the same functionality as the query defined above.

 String custname = request.getParameter("customerName"); // This should REALLY be validated try { 	CallableStatement cs = connection.prepareCall("{call sp_getAccountBalance(?)}"); 	cs.setString(1, custname); 	ResultSet results = cs.executeQuery();		 	// … result set handling  } catch (SQLException se) {			 	// … logging and error handling } 

LDAP Injection

Issue Name Description How to test for the issue How to identify the issue during code review Remediation Example code - Java
LDAP Injection

XPath Injection

Issue Name Description How to test for the issue How to identify the issue during code review Remediation Example code - Java
XPath Injection

Scripting languages

All scripting languages used in web applications have a form of an eval call which receives code at runtime and executes it. If code is crafted using unvalidated and unescaped user input code injection can occur which allows an attacker to subvert application logic and eventually to gain local access.

Every time a scripting language is used, the actual implementation of the 'higher' scripting language is done using a 'lower' language like C. If the scripting language has a flaw in the data handling code 'Null Byte Injection' attack vectors can be deployed to gain access to other areas in memory, which results in a successful attack.

Operating System (OS) Commands

Application developers sometimes implement operating system interactions using calls to system utilities to create and remove directories for example. Here unescaped input can lead to arbitrary OS commands being executed.

Issue Name Description How to test for the issue How to identify the issue during code review Remediation Example code - Java
Command Injection Appending a semicolon to the end of a URL query parameter followed by an operating system command, will execute the command. %3B is url encoded and decodes to semicolon. This is because the ; is interpreted as a command separator.

Example: http://sensitive/something.php?dir=%3Bcat%20/etc/passwd

If the applucation responds with the output of the /etc/passwd file then you know the attack has been successful.

Many web application scanners can be used to test for this attack as they inject variations of command injections and test the response.

Equally Static Code Analysis tools check the data flow of untrusted user input into a web application and check if the data is then entered into a dangerous method which executes the user input as a command.

Appending a semicolon to the end of a URL query parameter followed by an operating system command, will execute the command. %3B is url encoded and decodes to semicolon. This is because the ; is interpreted as a command separator.

Example: http://sensitive/something.php?dir=%3Bcat%20/etc/passwd

If the applucation responds with the output of the /etc/passwd file then you know the attack has been successful.

Many web application scanners can be used to test for this attack as they inject variations of command injections and test the response.

Equally Static Code Analysis tools check the data flow of untrusted user input into a web application and check if the data is then entered into a dangerous method which executes the user input as a command.

During code review, check if any command execute methods are called and in unvalidated user input are taken as data for that command. If it is considered unavoidable the call to a system command incorporated with user-supplied, the following two layers of defense should be used within software in order to prevent attacks
  1. Parametrization - If available, use structured mechanisms that automatically enforce the separation between data and command. These mechanisms can help to provide the relevant quoting, encoding.
  2. Input validation - the values for commands and the relevant arguments should be both validated. There are different degrees of validation for the actual command and its arguments:
    • When it comes to the commands used, these must be validated against a whitelist of allowed commands.
    • In regards to the arguments used for these commands, they should be validated using the following options:
      • Positive or “whitelist” input validation - where are the arguments allowed explicitly defined
      • White list Regular Expression - where is explicitly defined a whitelist of good characters allowed and the maximum length of the string. Ensure that metacharacters like & |  ; $ > < ` \ ! and white-spaces are not part of the Regular Expression. For example, the following regular expression only allows lowercase letters and numbers, and does not contain metacharacters. The length is also being limited to 3-10 characters:
 ^[a-z0-9]{3,10}$ 
incorrect Usage
ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe -arg1 -arg2"); 

In this example, the command together with the arguments are passed as a one string, making easy to manipulate that expression and inject malicious strings.

Correct Usage

Here is an example that starts a process with a modified working directory. The command and each of the arguments are passed separately. This make it easy to validated each term and reduces the risk to insert malicious strings.

ProcessBuilder pb = new ProcessBuilder("TrustedCmd", "TrustedArg1", "TrustedArg2"); Map<String, String> env = pb.environment(); pb.directory(new File("TrustedDir")); Process p = pb.start();

Network Protocols

Web applications often communicate with network daemons (like SMTP, IMAP, FTP) where user input becomes part of the communication stream. Here it is possible to inject command sequences to abuse an established session.

Injection Prevention Rules

Rule #1 (Perform proper input validation):

Perform proper input validation. Positive or “whitelist” input validation with appropriate canonicalization is also recommended, but is not a complete defense as many applications require special characters in their input.

Rule #2 (Use a safe API):

The preferred option is to use a safe API which avoids the use of the interpreter entirely or provides a parameterized interface. Be careful of APIs, such as stored procedures, that are parameterized, but can still introduce injection under the hood.

Rule #3 (Contextually escape user data):

If a parameterized API is not available, you should carefully escape special characters using the specific escape syntax for that interpreter.

Other Injection Cheatsheets

SQL Injection Prevention Cheat Sheet
OS Command Injection Defense Cheat Sheet
LDAP Injection Prevention Cheat Sheet
Injection Prevention Cheat Sheet in Java

Other Cheatsheets