
Nous continuons à développer PVS-Studio en tant que solution SAST. L'un des domaines dans lesquels des travaux sont en cours est l'amélioration de la couverture de l'OWASP. Et qu'est-ce que l'OWASP sans analyse d'altération ? Nous l'avons donc pensé et avons décidé de l'attacher à l'analyseur C#. À propos de ce qui a fonctionné et de ce qui n'a pas fonctionné, ci-dessous.
. SQL SQL C#. taint .
taint ?
, taint , (taint source). "" . (taint sinks), : SQLI, XSS .. taint , , taint source taint sink.
:
- (taint sources);
- (taint sinks);
- ;
- .
, . ;)
:
var userName = Request.QueryString["userName"];
var rawCommand = "SELECT * FROM users WHERE name = '" + userName + "'";
var sqlCommand = new SqlCommand(rawCommand);
// Execution of the tainted command
"" SQL – , - . , . , , SQL-. JohnSmith? Sergey'; DROP TABLE users; --. .
Taint PVS-Studio:
++
PVS-Studio, taint , C C++ . taint V1010. , : , . , – system. , ( ). C++ Russia 2018 , .
. , CVE, - . , , - CVE-. . :)
C#
taint C# . , , C++ . " V1010 C# " , - . , , C# 2021 – OWASP ( – OWASP Top 10 2017, ASVS ). , .
, taint , SQL . , OWASP Top 10 2017 (A1:2017-Injection) OWASP ASVS – . .
Taint PVS-Studio C#: ?
data-flow . , . , , , .
, : data-flow, , false positives . , , .
taint .
(taint sources)
. , . , , .
:
- HttpRequest.QueryString;
- TextBox.Text;
- Console.ReadLine;
- ..
, taintedVariable .
void Example()
{
var taintedVariable = Console.ReadLine();
TaintSink(taintedVariable);
}
, . , public public :
public class Helper
{
public void ExecuteCommand(String commandToExecute)
{
TaintSink(commandToExecute);
}
}
ExecuteCommand commandToExecute . . , , API . – - . :)
, , , . - GitHub, , . , , .
, . , – .
, , , , , . — , .
PVS-Studio , , , . . , , , taint sink .

- , .
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())
....
}
}
}
}
ProcessUserInfo (public public ). userName SQL ( command). command ExecuteCommand. — rawCommand — SQL (sqlCommand), . , taint .
, — - . SQLILib.dll. ( SQLIApp.exe), ProcessUserInfo :
static void TestHelper(DBHelper helper)
{
var userName = Request.Form["userName"];
helper.ProcessUserInfo(userName);
}
, (Request.Form["userName"]), ProcessUserInfo. ProcessUserInfo — , .
, , — .
, , , . , API. , , .
, SQLIApp.exe SQL , ProcessUserInfo. , .
, — , taint . SQL .
. , //-V::5608:3 .pvsconfig . V5608 (SQLI) . .pvsconfig " " ( " (.pvsconfig)").
, , , //V_LEVEL_1::5608. " " " ".
(taint sinks)
. , taint . , , . , taint source taint sink — .
, SQL , SQLCommand FromSqlRaw.
:
var taintedStr = GetTaintedData();
var sqlCommand = new SqlCommand(taintedStr); // taint sink
....
, SqlCommand — , , , - : SqlCommand.ExecuteSomehow. , . , . SqlCommand — sink, .
SqlCommand.CommandText. :
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())
....
}
}
}
SqlCommand, , CommandText.
, . :
- , - ;
- , ;
- , .
, , , - .
. , : SQL , - .. SQLI, , .
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())
....
}
taint SqlParameter. , . , userNameParam . userName , .
, taint source taint sink. , , . :) , taint sink. . — .
, , :
void Example()
{
var taintedVariable = Console.ReadLine();
TaintSink(taintedVariable);
}
Console.ReadLine() taintedVariable .
:
var taintedVariable = Console.ReadLine();
var taintedVariable2 = taintedVariable;
. , :
var shipCity = Console.ReadLine();
var resStr
= "select * from OrdersTable where ShipCity = '" + shipCity + "'";
, , . , .
:
var resStr = $"select * from UsersTable where Id = '{id}'";
— , , .
— . , . :)
— . :
var resStr = String.Join(separator, nonTaintedStr, taintedStr);
taintedStr String.Join, — resStr.
, , — , . — StringBuilder.
var sb = new StringBuilder();
sb.AppendLine(taintedStr);
var resStr = sb.ToString();
sb , AppendLine, taintedStr . , sb , . resStr ToString, .
, , — .
?
, , — . , data-flow C# , int, byte, short .. - , (- , ), . .
, taint , . , . false positive , , - , , . .
taint-based
. , .
- , sink' .
- — , sink'.
- sink, , taint .
- ...
- PROFIT!
, , , , .
taint : SQLI
, taint SQL .
, SQL , .. . , docs.microsoft.com. .
taint , . - (taint source). , , . , SQL (sink). , , , . .

. "SQLI C#", - :
private HttpRequest Request { get; set; }
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())
....
}
}
}
, userName SQL - . , userName . , ' OR '1'='1, , .
. SQLI?
Request.Form ( Request HttpRequest). Form — NameValueCollection, . , ( ): Request.Form -> Request.Form["userName"]. userName , .
SqlCommand, . CommandText. CommandText — sink. . : "SELECT * FROM Users WHERE UserName = '" + userName + "'". , . , , , . , userName . . , , CommandText, , , .
Taint PVS-Studio 7.13. SQLI — V5608. .
, Twitter-. ;)
, : Sergey Vasiliev. OWASP, Vulnerabilities, and Taint Analysis in PVS-Studio for C#. Stir, but Don't Shake.