CWE Rule 89
Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
Since R2023a
Description
This checker is deactivated in a default
Rule Definition
The software constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component.
Polyspace Implementation
This rule checker checks for the issue SQL Injection.
Examples
SQL Injection occurs when data read from an untrusted source such as standard input is used in the construction of an SQL query.
This defect checker detects the flow of data from an untrusted source to a function that executes an SQL query (or prepares an SQL query to be executed). Functions flagged by this checker include the following:
MySQL C API:
SQL query functions such as
mysql_query()
andmysql_real_query()
.SQLite API:
SQL query functions such as
sqlite3_exec()
or SQL statement preparation functions such assqlite3_prepare()
andsqlite3_prepare_v2()
.
Untrusted sources include strings read from the standard input stdin
using the fread()
or fgets()
function (or from files opened with fopen()
.
SQL queries are often constructed from user inputs. However, if these inputs are directly used in the construction of an SQL database query without any sanitization, they are vulnerable to SQL injection. A malicious user can inject code masquerading as input, resulting in:
Bypassing of logic that secures part of the database.
Execution of malicious SQL queries or even shell commands.
For instance, an SQL query such as the following, where
and username
are obtained from user inputs, is vulnerable to SQL injection:itemName
SELECT * FROM items WHERE owner = 'userName' AND itemname = 'itemName';
john
and anItem' OR 'a' = 'a
, the query translates to:SELECT * FROM items WHERE owner = 'john' AND itemname = 'anItem' OR 'a' = 'a';
WHERE
clause being always true. This allows the user to access the entire database even if they do not have the requisite permissions.Depending on the API you are using, follow the recommended sanitization approaches to sanitize user inputs before using them in SQL queries. For instance:
MySQL C API:
Escape values in the SQL query string using
mysql_real_escape_string()
ormysql_real_escape_string_quote()
.SQLite API:
Create parametrized queries using the functions
sqlite3_prepare_*()
with parameters and then bind the parameters using the functionssqlite3_bind_*()
.
You can also write your own sanitization functions to validate or clean up the user input. See the following section.
You can extend this checker by specifying your own SQL statement execution and sanitization functions.
Suppose you want to specify the following:
Function
sql_exec
executes an SQL statement or prepares an SQL statement for execution:int sql_exec (char*, /* SQL query */ sqlite3* , /* Database */ int (*callback)(void*,int,char**,char**), void*, char**);
Suppose the
-th argument of this function is the SQL query string to be executed. For instance, the first argument in the above signature could be the SQL query string.n_exec
Function
sql_sanitize
sanitizes the untrusted (tainted) data to be used in an SQL statement.int sql_sanitize( char *, /* String to sanitize */ int); /* Length of string */
Suppose the
-th argument of this function is the data string to be sanitized. For instance, the first argument in the above signature could be the data to be sanitized.n_sanitize
To make the SQL injection checker aware of these functions:
In a file with extension
.dl
, add the following:If.include "models/interfaces/sql.dl" Sql.Basic.execution("sql_exec", $InParameterDeref(n_exec-1)). Sql.Basic.sanitizing("sql_sanitize", $OutParameterDeref(n_sanitize-1)).
andn_exec
are both 1 (that is, the first parameters of each function are the parameters of interest), then the statements become:n_sanitize
.include "models/interfaces/sql.dl" Sql.Basic.execution("sql_exec", $InParameterDeref(0)). Sql.Basic.sanitizing("sql_sanitize", $OutParameterDeref(0)).
Specify this file using the option
-code-behavior-specifications
. For instance, if the file is namedsqlAdditionalFunctions.dl
, use the analysis option:-code-behavior-specifications sqlAdditionalFunctions.dl
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
// Function to insert names into database
void insertIntoDatabase(void)
{
sqlite3* db;
char query[256] = "";
char name[256];
char* error_message;
int nameLength;
sqlite3_open("userCredentials.db", &db);
fread(name, 1, 128, stdin);
strcat(query, "INSERT INTO privatenames (name) VALUES ('");
strcat(query, name);
strcat(query, "');");
if (sqlite3_exec(db, query, NULL, NULL, &error_message)) // Noncompliant
{
sqlite3_free(error_message);
}
}
In this example, the function sqlite3_exec()
creates an SQL query by concatenating parts of an SQL command with a user input. The query is supposed to be:
INSERT INTO privatenames (name) VALUES ('name')
john'); DELETE FROM privatenames;--
INSERT INTO privatenames (name) VALUES ('john');
DELETE FROM privatenames;
--');
--
results in the remainder of the line being commented out. The resulting SQL query consists of two statements: the first one is the intended query and the second one results in an unintended deletion of all items from the database.To avoid possible SQL injection, prepare a parametrized query using sqlite3_prepare_v2()
and then bind the parameter to the user input using sqlite3_bind_text()
. The binding takes care of escaping reserved characters such as single quotes and prevents construction of malicious SQL queries as shown earlier.
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
// Function to insert names into database
void insertIntoDatabase(void)
{
sqlite3* db;
sqlite3_stmt *st;
char query[256] = "";
char name[256];
char* error_message;
sqlite3_open("userCredentials.db", &db);
fread(name, 1, 128, stdin);
strcat(query, "INSERT INTO privatenames (name) VALUES (?);");
if (sqlite3_prepare_v2(db, query, -1, &st, &error_message))
{
//Error handling
}
if (sqlite3_bind_text(st, 1, name, strlen(name), NULL))
{
//Error handling
}
if (sqlite3_step(st))
{
//Error handling
}
}
You can write your own sanitization function to validate or sanitize the input before using it to construct an SQL query. In this example, the function sanitizeString()
performs some basic sanitization such as removing semicolons from the input string.
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
void sanitizeString(char *, int);
// Function to insert names into database
void insertIntoDatabase(void)
{
sqlite3* db;
char query[256] = "";
char name[256];
char* error_message;
int nameLength;
sqlite3_open("userCredentials.db", &db);
fread(name, 1, 128, stdin);
nameLength = sizeof(name)/sizeof(char);
sanitizeString(name, nameLength);
strcat(query, "INSERT INTO privatenames (name) VALUES (");
strcat(query, name);
strcat(query, ");");
if (sqlite3_exec(db, query, NULL, NULL, &error_message))
{
sqlite3_free(error_message);
}
}
void sanitizeString(char *name, int len)
{
for (int i = 0; i < len; i++)
{
// Remove semicolons
if(name[i] == ';')
{
name[i] = ' ';
}
// Other sanitization of string
}
}
To make the Polyspace analysis aware of the nature of your sanitization function:
Specify the following in a file with extension
.dl
(for instance,sanitizeFunctions.dl
):.include "models/interfaces/sql.dl" Sql.Basic.sanitizing("sanitizeString", $OutParameterDeref(0)).
Specify the following option with the analysis:
-code-behavior-specifications sanitizeFunctions.dl
See also
-code-behavior-specifications
.
Check Information
Category: Data Neutralization Issues |
Version History
Introduced in R2023a
See Also
External Websites
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)