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"
m (d) (Tag: Visual edit) |
m (Edit) (Tag: Visual 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> | ||
− | + | 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. | ||
− | + | '''<u>Defense Option 3: White List Input Validation</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. |
− | + | '''<u>Defense Option 4: Escaping All User-Supplied Input</u>''' | |
− | + | 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. | |
| | | | ||
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( ); | ||
− | + | We have shown examples in Java, but practically all other languages, including Cold Fusion, and Classic ASP, support parameterized query interfaces. | |
− | |||
− | |||
− | We have shown examples in Java | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
; 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 } | ||
− | |||
− | |||
− | |||
|} | |} | ||
Line 137: | Line 125: | ||
!Example code - Java | !Example code - Java | ||
|- | |- | ||
− | | | + | |LDAP Injection |
− | | | + | | |
− | + | | | |
− | + | | | |
− | + | | | |
− | + | | | |
− | |||
− | |||
− | |||
− | | | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | | | ||
− | | | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | | | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
Line 182: | Line 142: | ||
!Example code - Java | !Example code - Java | ||
|- | |- | ||
− | | | + | |XPath Injection |
− | | | + | | |
− | + | | | |
− | + | | | |
− | + | | | |
− | + | | | |
− | |||
− | |||
− | |||
− | | | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | | | ||
− | | | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | | | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
Revision as of 16:10, 14 November 2017
Last revision (mm/dd/yy): 11/14/2017
IntroductionThis 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 TypesThree 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 ApplicationA new web application in the design phase, or in early stage development. A2: Productive Open Source ApplicationAn 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 ApplicationA productive application which cannot or only with difficulty be modified. Forms of InjectionThere are several forms of injection targeting different technologies including SQL queries, LDAP queries, XPath queries and OS commands. Query languagesThe 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
LDAP Injection
XPath Injection
Scripting languagesAll 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) CommandsApplication 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.
Network ProtocolsWeb 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 RulesRule #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 Other Cheatsheets |