V5608. OWASP. Possible SQL injection. Potentially tainted data is used to create SQL command.
The analyzer detected an SQL command that uses data received from an external source, without a prior check. This can cause an SQL injection if the data is compromised.
An SQL injection is identified as a separate risk category in the OWASP Top 10 Application Security Risks 2017: A1:2017-Injection.
Consider an example:
void ProcessUserInfo()
{
using (SqlConnection connection = new SqlConnection(_connectionString))
{
....
String userName = Request.Form["userName"];
using (var command = new SqlCommand()
{
Connection = connection,
CommandText = "SELECT * FROM Users WHERE UserName = '" + userName + "'",
CommandType = System.Data.CommandType.Text
})
{
using (var reader = command.ExecuteReader())
....
}
}
}
In this case, we receive the value of the 'userName' variable from an external source - 'Request.Form'. Then the SQL command is formed. It is dangerous to use data in this way without any check - this way attackers get to use different ways to introduce commands.
For example, an attacker can enter a special command instead of the expected value of the user name. This way all users' data will be extracted from the base and then processed.
An example of such a compromised string:
' OR '1'='1
To protect against such requests, you should check the input data or, for example, use parameterized commands.
Code sample with parameterized commands used:
void ProcessUserInfo()
{
using (SqlConnection connection = new SqlConnection(_connectionString))
{
....
String userName = Request.Form["userName"];
using (var command = new SqlCommand()
{
Connection = connection,
CommandText = "SELECT * FROM Users WHERE UserName = @userName",
CommandType = System.Data.CommandType.Text
})
{
var userNameParam = new SqlParameter("@userName", userName);
command.Parameters.Add(userNameParam);
using (var reader = command.ExecuteReader())
....
}
}
}
The analyzer also considers methods' parameters from other builds to be unsafe sources. Users of such builds can expect that data will be checked inside the called method. However, neither a user of the library nor its developer has checked the input data. This omission can cause vulnerabilities when using compromised data.
Consider an example:
public class DBHelper
{
public void ProcessUserInfo(String userName)
{
....
var command = "SELECT * FROM Users WHERE userName = '" + userName + "'";
ExecuteCommand(command);
....
}
private void ExecuteCommand(String rawCommand)
{
using (SqlConnection connection = new SqlConnection(_connectionString))
{
....
using (var sqlCommand = new SqlCommand(rawCommand, connection))
{
using (var reader = sqlCommand.ExecuteReader())
....
}
}
}
}
The 'DBHelper' class provides the 'ProcessUserInfo' method for external use, since 'ProcessUserInfo' is available from other builds. However, the 'userName' parameter of this method is not checked in any way before use. The value obtained from the outside is directly used to form the command (the 'command' variable). Next, the received command is passed to the 'ExecuteCommand' method. In this method it is used without a prior check to create an object of the 'SqlCommand' type.
In this case, the analyzer will issue a warning due to the call to the 'ExecuteCommand' method that receives the tainted string as an argument.
Now let's look at a possible use case for the 'ProcessUserInfo' method:
static void TestHelper(DBHelper helper)
{
var userName = Request.Form["userName"];
helper.ProcessUserInfo(userName);
}
A developer who has written such code may not have access to the 'DBHelper' class code. The author might rely on the input data check inside the 'ProcessUserInfo' method. But neither the current code nor the code of the 'ProcessUserInfo' method has checked the data, so this code will be vulnerable to an SQL injection.
Although such cases can lead to a vulnerability, we don't know the explicit external data source when analyzing the 'DBHelper' code. Therefore, you will get a warning with a low certainty level if the input data source is methods' parameters available for external builds.
This diagnostic is classified as:
|