0 ratings0% found this document useful (0 votes) 170 views14 pagesSQL Injection Prevention Cheatsheet
SQL Injection Prevention Cheatsheet
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content,
claim it here.
Available Formats
Download as PDF or read online on Scribd
72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
SQL Injection Prevention Cheat Sheet
Introduction
This articleis focused on prcviding clear, simple, actionable guidance for preventing SQL Injection
flaws in your applications. SQL Injection attacks are unfortunately very common, and this is due to
‘two factors:
1. the significant prevalence of SQL Injection vulnerabilities, and
2. the attractiveness of the target (ie, the database typically contains all the interesting/critical
data for your application).
SQL Injection flaws are introduced when software developers create dynamic database queries
constructed with string concatenation which includes user supplied input. To avoid SQL injection
flaws is simple. Developers need to either: a) stop writing dynamic queries with string
concatenation; and/or b) prevent user supplied input which contains malicious SQL from affecting
the logic of the executed query
This article provides a set of simple techniques for preventing SQL Injection vulnerabilities by
avoiding these two problems. These techniques can be used with practically any kind of
programming language with any type of database. There are other types of databases, like XML.
databases, which can have similar problems (e.g., XPath and XQuery injection) and these
techniques can be used to protect them as well
Primary Defenses:
+ Option 1: Use of Prepared Statements (with Parameterized Queries)
+ Option 2: Use of Properly Constructed Stored Procedures
Option 3: Allow-list Input Validation
+ Option 4: Escaping All User Supplied Input
‘Additional Defenses:
+ Also: Enforcing Least Privilege
+ Also:
erforming Allow-list Input Validation as a Secondary Defense
Unsafe Example:
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl ane72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
‘SQL injection flaws typically look like this:
The following (Java) example is UNSAFE, and would allow an attacker to inject code into the query
that would be executed by the database. The unvalidated ‘customerName’ parameter that is.
simply appended to the query allows an attacker to inject any SQL code they want. Unfortunately,
this method for accessing databases is all too common,
String query = "SELECT account_balance FROM user_date NHERE user_nane =
+ request.getParaneter ("custonerNane" );
try {
Stotenent stotenent = connection.createStatenent( ... );
ResultSet results = statenent.executeduery( query );
Primary Defenses
Defense Option 1: Prepared Statements (with Parameterized Queries)
‘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 nct be vulnerable and would instead
look for a usemame which literally matched the entire string tom’ or "1'="1.
Language specific recommendations:
Java EE -use PreparedStatenent() with bind variables
-NET ~ use parameterized queties like Sq1Conmand() or O1edbConrand() with bind variables
PHP ~ use PDO with strongly typed parameterized queries (usingbindParam())
+ Hibemate-use crestequery() with bind variables (called named parameters in Hibemate)
# SQlite-use sqlites_prenare() to createa statement object
Inrare circumstances, prepared statements can harm performance. When confronted with this
situation, itis best to either a) strongly validate all data or b) escape all user supplied input using
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl ane72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
anescaping routine specific to your database vendor as describedbelow, rather than
prepared statement.
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.
// This should REALLY be validated too
String custnane = request.getParameter (“customerNane") ;
// Perform input validation to detect attacks
String query
PreparedStatement pstmt = connection.prepareStatement( query );
pstmt. setString( 1, custname,
ResultSet results = pstmt.executeduery( );
"SELECT account_balence FROM user_data NHERE user_nane = ? ";
Safe C# NET Prepared Statement Example:
With .NET, it's evenmore straightforward, The creation and execution of the query doesrtt change.
All youhave to do is simply pass the parametersto the query using the Perometers.Add() callas
‘shown here.
String query = "SELECT account_balance FROM user_data NHERE user_nane = ?"
try {
OleDbCommand command = new OleDbConmand(query, connection
conmand.Parameters.Add(new OleDbParameter(“customerName", CustomerName
Nane.Text));
OleDbDataReader reader = conmand.executeReader();
u
} catch (OLeDbException se) {
1/ error handling
3
We have shown examples in Java and.NET but practically al other languages, including Cold
Fusion, and Classic ASP support parameterized query interfaces. Even SQL abstraction layers, like
the Hibernate Query Language (HQL) have the same type of injection problems (which we call HOL
Injection). HQL supports parameterized queries as Well, so we can avoid this problem:
Hibemate Query Language (HQL) Prepared Statement (Named Parameters) Examples:
//First is an unsafe HOL Statement
Query unsafeHalduery = session.createQuery("from Inventory where productID=' “users
//Here is a safe version of the same query using named parameters
Query safeHalduery = session.createduery("fron Inventory where productID=:productid
safeHQLquery.setParameter("productid", userSuppliedParameter) ;
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl ane72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
For examples of parameterized queries in other languages, including Ruby, PHP, Cold Fusion, and
Pod], see the Query Parameterization Cheat Sheet or this site.
Developers tend to like the Prepared Statement approach because all the SQL code stays within
the application. This makes your application relatively database independent,
Defense Option 2: Stored Procedures
Stored procedures ate 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.
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 cant 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.
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_ouner. 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.
Safe Java Stored Procedure Example:
The following code example uses a Callablestatement,, Java implementation of the stored
procedure interface, to execute the same database query. The sp_getAccountBalance stored
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl ana72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
Procedure would have to be predefined in the database andimplement the same functionality as
the query defned above.
// This should REALLY be validated
String custnane = request .getParaneter (“customerNane") ;
try {
CallableStatenent cs = connection.prepareCall("{cal1
sp_getAccountBalance(?)}");
es.setString(1, custnane);
ResultSet results = cs.executedery();
1/ m result set handling
} catch (SQLException se) {
1] » logging and error handling
}
Safe VB .NET Stored Procedure Example:
The follewing code example uses a Sq1Connand, 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 SqlConmand = new SqlConmand(”sp_getAccountBalance”, connection)
command.ConmandType = ConmandType.StoredProcedure
conmand.Parameters.Add(new SqlParameter("@CustonerName", CustomerName.Text))
Dim reader As SqDataReader = command .ExecuteReader()
Catch se As SqlException
‘error handling
End Try
Defense Option 3: Allow-list Input Validation
Various parts of SQL queries arent legal locations for the use of bind variables, such as the names
of tables or columns, and the sort order indicator (ASC of 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 for targeting different 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 rewrite should be considered if time allows.
Here is an example of table name validation.
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl sine72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
String tableNane;
‘switch (PARAM) :
case "Valuel": tableNane = “fooTeble";
break:
case "Value2": tableNane = “barTable";
break;
default £ throw new InputValidationexception( "unexpected value provided"
+" for table name");
The tabieNane can then be directly appended to the SQL query since it is now known to be one of
the legal and expected values for a table name in this query. Keep in mind that generic table
validation functions can lead to data loss as table names are used in queries where they are not
expected.
For something simple lke a sort order, it would be best if the user supplied input is converted to a
boolean, and then that boolean is used to select the safe value to append to the query. This is a
very standard need in dynamic query creation.
For example:
public String soneMethod(boolean sortOrder) {
String SQlquery = “some SQL... order by Salary " + (sortOrder ? "ASC" : “DESC");
Any time user input can be converted to a non-String, like a date, numeric, boolean, enumerated
type, ete. before itis appended to a query, or used to select a value to append to the query, this,
ensures it is safe to do so.
Input validation is also recommended as a secondary defense in ALL cases, even when using bind
variables asis discussed later in this article. More techniques on how to implement strong input
validation ie described in the Input Validation Cheat Sheet,
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 is very database specific in its
implementation. It’s usually only recommended to retrofit legacy code when implementing input
validation isnit cost effective. Applications built from scratch, of applications requiring low risk
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl ene72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
tolerance should be built or re-written using parameterized queries, stored procedures, or some
kind of Object Relational Mapper (ORM) that builds your queries for you.
This technique works like this. Each DBMS supports one or more character escaping schemes
specific to certain kinds of queries. If you then escape all user supplied input using the proper
escaping scheme for the database you are using, the DBMS will not confuse that input with SQL
‘code written by the developer, thus avoiding any possible SQL injection vulnerabilities.
‘The OWASP Enterprise Security API (ESAPI) is a free, open source, web application security control
library that makes it easier for programmers to write lower-isk applications. The ESAPI libraries
are designed to make it easier for programmers to retrofit security into existing applications. The
ESAPI libraries also serve as a solid foundation for new development:
‘+ Full details on ESAPI are available here on OWASP.
+ The javadoc for ESAP! 2.x (Legacy) is available, This code was migrated to GitHub in
Noverber 2014.
‘* The legacy ESAP! for Java at GitHub helps understand existing use cf it when Javadoc seems
insufficient.
‘© An attempt at another ESAPI for Java GitHub has other approaches and notests or concrete
codecs.
To find the javadoc specifically for the database encoders, click on the Codec classon the left
hand side. There are lots cf Codecs implemented. The two Database specific codecs are
OracleCodec, and MySaLCodec.
Just click on theirnamesin the All Known Inpienenting Classes: atthetop ofthe interface
Codec page.
At this time, ESAPI currently has database encoders for:
= Oracle
‘+ MySQL (Bcth ANS! andnative modes are supported)
Database encoders are forthcoming for:
+ SQLServer
+ PostgreSQL
If your database encoder is missing, please let us knows.
Database Specific Escaping Details
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl mma9123/22, 8:52AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
Ifyou want to build your own escaping routines, here are the escaping details for each of the
databases that we have developed ESAPI Encoders for:
* Oracle
© SQLServer
= DB2
ORACLE ESCAPING
This information is based on the Oracle Escape character information,
Escaring Dynamic Quaties
Tose an ESAPI database codecis pretty simple. An Oracle example looks something like
ESAPT .encoder().encodeForSQL( new OracleCodec(), queryparam );
So, if you had an existing Dynamic query being generated in your code that was going to Oracle
that looked like this:
"SELECT user_id FRO user_data WHERE user_name =
+ req.getParameter("userID")
+ "" and user_password = ‘" + req.getParaneter("pwd") +°'"5
String query
try {
Statement statement = connection.createStatement( ~ );
ResultSet results = statenent .executeQuery( query );
You would rewrite the first line to look like this:
Codec ORACLE_CODEC = new OrecleCodec();
String query = "SELECT user-id FROM user_date WHERE user_nane
+ ESAPI .encoder() .encodeForSQL( ORACLE.CODEC, req.getParaneter(“userI0"))
+ °' and user_password = °
+ ESAPI .encoder() .encodeForSQL( ORACLE_CODEC, req.getParaneter("prd")) +"
‘And it would now be safe from SQL injection, regardless of the input supplied.
For maximum code readability, you could also construct your cwn Oracleéncoder :
Encoder o¢
String query
+ oe encode( req.getParaneter(“useri0")) +
+ oe.encode( req.getParameter(“pwd")) #7";
new Oracletneoder() ;
‘SELECT user-id FROM user_date MERE user_nane
"and user_password
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl ane72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
With this type of solution, you would need only to wrap each user-supplied parameter being passed
intoan EsAPt.encoder() .encodeForOracle( ) call or whatever you named the call and you would
bedone
‘Tum otf characterreplacemert
Use SET DEFINE OFF oF SET SCAN OFF to ensure that automatic character replacement is tumed
off. If this character replacement is tumed on, the & character willbe treated like @ SQLPlus
variable prefix that could allow an attacker toretrieve private data.
See here and here for more information
Escaping Wildcard characters in Like Clauses
The LIKE keyword allows for text scanning searches. In Oracle the underscore _ character
matches only one character, while the ampersand * is used to match zero or more occurences of
any characters. These characters must be escaped in LIKE clause criteria.
For example:
SELECT name FROM emp WHERE id LIKE ‘%/_X' ESCA
SELECT name FROM emp WHERE id LIKE "%\x%' ESCAPE
rade 109 escaping
{An altemative for Oracle 10g and later isto place ( and } around the string to escape the entire
string, However, youhaveto be careful that there isnt 2 } character already in the string. You must
search for these and if thereis one, then yournust replace itwith }} . Otherwise that character will
end the escaping early, and may introduce a wilnerabiity.
MYSQL ESCAPING
MySQL supports two escapingmades:
11, ANST_QUOTES SQL mode, and a mode with this off, which we call
2. nysal. mode.
ANST_SqL mode’ Simply encodeall ' (singletick) characters with '* (two single ticks)
ysal_ mode, do the following:
NUL (0x00) --> \@ [This is a zero, not the letter o]
BS (@x@8) --> \b
‘NB (0x09) --> \t
LF (@x@a) --> \n
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl one72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
CR (@x@d) --> \r
SUB (@x1a) --> \Z
" (@x22) => \
% (0x25) --> V8
" (0x27) ==> \"
\ (@xSc) --> \\
= (@xSF) => \.
all other non-alphanumeric characters with ASCIT values
less than 256 --> \c where ‘c' is the original non-alphanuneric character
This information is based on the MySQL Escape character information.
‘SQL SERVER ESCAPING
We have not implemented the SQL Sener escaping routine yet, but the following has good pointers
and linksto articles describing howto prevent SQL injection attacks on SQL server, see here,
DBZ ESCAPING
This information is based on DB2 WebQuery special characters as welll as some information from
Oracle's JDBC DB2 driver.
Information in regards to differences between several DB2 Universal drivers.
Hex-encoding al input
A someuhat special case of escaping is the process of hex-enaode the entire sting received from
the user (this can be seen as escaping every character). The web application should hex-encode
‘the user input before including it in the SQL statement. The SQL statement should take into
account this fact, and accordingly compare the data.
For example, if we have to look up a record matching a sessionID, and the user transm ted the
string abc123 as the session ID, the select statement would be:
SELECT ... FROM session WHERE hex_encode(sessionID) = "61626319233
hex_encode should be replaced by the particular facility for the database being used. The string
606162313233 the hex encoded version of the string received from the user (tis the sequence
of hex valves of the ASCIVUTF-8 codes of the user data).
I anattacker were to transmit a string containing @ single-quote character followed by their
attempt toinject SQL code, the constructed SQL statement will only look lke:
c++ WHERE hex_encode ( ... ) = '2720 ... °
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl sone72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
27 being the ASCII code (in hex) of the singlequote, wtich is simply hex-encoded lke any cther
character in the string. The resulting SQL can only contain numeric digits andlletters « to , and
never any special character that could enable an SQL injection.
Escaping SQL in PHP
Use prepared statements and parameterized queries. These are SQL statements that are sent to
and parsed by the database server separately from any parameters. This way it is impossible for an
attacker to inject malicious SQL.
‘You basically have two options to achieve this:
1. Using PDO (for any supported database driver):
‘Setmt = Spdo->prepare( "SELECT * FROM employees NHERE name = :nane’);
Sstmt->execute(array(‘name' => $nane));
foreach ($stmt as $row) ¢
11 60 something with Srow
1. Using MySQLi (for MySQL):
Sstmt = $dbConnection->prepare( ‘Sk
Sstmt->bind_paran(’s', Sname);
Sstmt-rexecute();
Sresult = $stmt->get_result();
while (Srow = Sresult->fetchassoc(}) (
11 do something with Srow
* FROM employees WHERE name
PDO is the universal option. If you're connecting to a database cther than MySQL, you can refer to a
driver-specific second option (e.g. pg_prepare() and pg_execute() for PostgreSQL).
Additional Defenses
Beyond adopting one of the four primary defenses, we also recommend adoptingalll of these
additional defenses in order to provide defense in depth. These addtional defenses are:
+ Least Privilege
+ Allow-4tist Input Validation
Least Privilege
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl sine‘SQL injection Prevention - OWASP Cheat Sheet Series
To minimize the potential damage of a successful SQL injection attack, you should minimize the
privileges assigned to every database account in your environment. Do not assign DBA or admin
type access rights to your application accounts. We understand that this is easy, and everything
just works’ when you do it this way, but itis very dangerous.
Start from the ground up to determine what access rights your application accounts require, rather
than trying to figure out what access rights you need to take away. Make sure that accounts that
only need read access are only granted read access to the tables they need access to.
Ifan account only needs access to portions of a table, consider creating a view that limits access:
to that portion of the data and assigning the account access to the view instead, rather than the
underlying table. Rarely, if ever, grant create or delete access to database accounts,
Ifyou adopt a policy where you use stored procedures everywhere, and dont allow application
accounts to directly execute their own queries, then restrict those accounts to only be able to
execute the stored procedures they need. Don't grant them any rights directly to the tables in the
database.
‘SQL injection is not the only threat to your database data. Attackers can simply change the
parameter values from one of the legal values they are presented with, to a value that is
Unauthorized for them, but the application itself might be authorized to access. As such,
‘minimizing the privileges granted to your application will reduce the likelihood of such
unauthorized access attempts, even when an attacker is not trying to use SQL injection as part of
their exploit.
While you are at it, you should minimize the privileges of the operating system account that the
DBMS runs under. Dont run your DBMS as root or system! Most DBMSs run out of the box with a
very powerful system account. For example, MySQL runs as system on Windows by default!
Change the DBMS's 0S account to something more appropriate, with restricted privileges,
Multiple DB Users
The designer of web applications should not only avoid using the same owner/admin account in
the web applications to connect to the database. Different DB users could be used for different
web applications.
In general, each separate web application that requires access to the database could have a
designated database user account that the web-app will use to connect to the DB. That way, the
designer of the application can have good granularity in the access control, thus reducing the
privileges as much as possible. Each DB user will then have select access to what it needs only,
and write-access as needed.
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl rane72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
‘As an example, a login page requires read access to the username and password fields of a table,
but no write access of any form (no insert, update, or delete). However, the sign-up page certainly
requires insert privilege to that table; this restriction can only be enforced if these web apps use
different DB users to connect to the database.
Views
You can use SQL views to further increase the granularity of access by limiting the read access to
specific fields of a table or joins of tables. it could potentially have additional benefits: for example,
suppose that the system is required (perhaps due to some specific legal requirements) to store the
passwords of the users, instead of salted-hashed passwords.
‘The designer could use views to compensate for this limitation; revoke all access to the table (from
all DB users except the owner/admin) and create a view that outputs the hash of the password
field and not the field itself. Any SQL injection attack that succeeds in stealing DB information will
be restricted to stealing the hash of the passwords (could even be a keyed hash), since no DB user
for any of the web applications has access to the table itself.
Allow-list Input Validation
In addition to being a primary defense when nothing else is possible (e.g., when a bind variable isrit
legal) input validation can also be a secondary defense used to detect unauthorized input before it
is passed to the SQL query. For more information please see the Input Validation Cheat Sheet,
Proceed with caution hete. Validated data is nct necessarily safe to insert into SQL queries via
string building.
Related Articles
‘SQL Injection Attack Cheat Sheets:
The following articles describe how to exploit different kinds of SQL Injection Vuherabifties on
various platforms that this article was created tohelp you avoid:
SQL Injection Cheat Sheet
+ Bypassing WAFS with SQLi- SQL Injection Bypassing WAF
Description of SQL Injection Vulnerabilities:
+ OWASP article on SQL. Injection Vuherabilties
‘+ OWASP article on Blind_SQL_Injection Vulnerabilities,
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl sane72822, 6352 AM ‘SQL injection Prevention - OWASP Cheat Sheet Series
How to Avoid SQL Injection Vulnerabilities:
‘+ OWASP Developers Guide article on how to avoid SQL injection vulnerabilities
‘+ OWASP Cheat Sheet that provides numerous language specific examples of parameterized
queries using both Prepared Statements and Stored Procedures
‘* The Bobby Tables site (inspired by the XKCD webcomic) has numerous examples in different
languages of parameterized Prepared Statements and Stored Procedures
How to Review Code for SQL Injection Vulnerabilities:
‘* OWASP Code Review Guide artide on how to Review Code for SQL Injection Vulnerabilities
How to Test for SQL Injection Vulnerabilities
‘© OWASP Testing Guide article on howto Test for SQL injection Vulnerabilities
Intps:iieheatshectsories.owasp.orgicheatsheets'SOL_Irjection_Prevention_Cheat_ Sheet.himl