Анализатор обнаружил, что данные, полученные из внешнего источника, используются в качестве путей к файлам или папкам без предварительной проверки. Это может стать причиной уязвимости приложения к атакам path traversal.
Атаки этого типа выделены в отдельную категорию рисков в OWASP Top 10 Application Security Risks 2017: A5:2017-Broken Access Control.
Рассмотрим пример:
HttpResponse response;
HttpRequest request;
private void SendUserFileContent(string userDirectory)
{
....
string userFileRelativePath = request.QueryString["relativePath"];
string fullPath = Path.Combine(userDirectory,
userFileRelativePath);
var content = File.ReadAllText(fullPath);
....
response.Write(content);
}
Данный метод производит отправку содержимого некоторого файла из заданной папки пользователя. Предполагается, что пользователь должен иметь возможность получения содержимого только файлов, хранящихся внутри этой папки.
В качестве относительного пути здесь используется значение, полученное из внешнего источника – 'Request.QueryString'. Отсутствие каких-либо проверок позволяет злоумышленнику получить доступ к содержимому любых файлов в системе.
Например, в папке каждого пользователя может храниться файл userInfo.xml, в котором содержится различная (в том числе конфиденциальная) информация (при этом код выполняется на системе Windows). Тогда для получения доступа к данным пользователя 'admin' злоумышленник может передать в 'Request. QueryString["relativePath"]' следующую строку:
..\admin\userInfo.xml
Для защиты от такой атаки недостаточно простой проверки на наличие '..\' в начале строки. К примеру, для получения тех же данных может передаваться и строка
someFolder\..\..\admin\userInfo.xml
Ещё одна возможность для атаки – передача абсолютного пути вместо относительного. Если один из аргументов 'Path.Combine' представляет собой абсолютный путь, то все ранее записанные аргументы игнорируются. К примеру, метод может быть вызван следующим образом:
Path.Combine("folder", "childFolder", "C:\Users\Admin\secret.txt")
В результате будет возвращена строка 'C:\Users\Admin\secret.txt '. Таким образом, отсутствие проверки входных данных позволяет злоумышленнику получить доступ к любому файлу в системе. Более подробно атаки типа path traversal и способы их проведения описаны на официальном сайте OWASP по ссылке.
Для обеспечения защиты от path traversal необходимо применять различные средства проверки входных данных. В примере, описанном выше, можно использовать проверку на наличие подстрок ":" и "..\":
HttpResponse response;
HttpRequest request;
private void SendUserFileContent(string userDirectory)
{
....
string userFileRelativePath = request.QueryString["relativePath"];
if ( !userFileRelativePath.Contains(":")
&& !userFileRelativePath.Contains(@"..\"))
{
string fullPath = Path.Combine(userDirectory,
userFileRelativePath);
var content = File.ReadAllText(fullPath);
....
response.Write(content);
}
else
{
....
}
}
Анализатор также считает источниками небезопасных данных параметры методов, доступных из других сборок. Эта тема подробно раскрыта в заметке "Почему важно проверять значения параметров общедоступных методов".
Рассмотрим пример кода, выполняющегося на ОС Windows:
public class UserFilesManager
{
private const string UsersDirectoryAbsolutePath = ....;
private HttpResponse response;
private string userName;
public void WriteUserFile(string relativePath)
{
string path = Path.Combine(UsersDirectoryAbsolutePath,
userName,
relativePath);
WriteFile(path);
}
private void WriteFile(string absolutePath)
{
response.Write(File.ReadAllText(absolutePath));
}
}
Анализатор сформирует предупреждение низкого уровня достоверности на вызов метода 'WriteFile' внутри 'WriteUserFile'. После вызова 'Path.Combine' небезопасные данные из 'relativePath' передаются в 'path', после чего выступают в качестве аргумента вызова 'WriteFile', где используются в качестве пути. Таким образом, пользовательский ввод может попасть в метод 'File.ReadAllText' без проверки, из-за чего данный код уязвим к path traversal.
Для защиты от атаки необходимо проводить валидацию параметров. В данном случае важно провести её до вызова 'Path.Combine', так как возвращаемое им значение в любом случае будет абсолютным путём:
public void WriteUserFile(string relativePath)
{
if (relativePath.Contains(":") || relativePath.Contains(@"..\"))
{
....
return;
}
string path = Path.Combine(UsersDirectoryAbsolutePath,
userName,
relativePath);
WriteFile(path);
}
Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.). |
Данная диагностика классифицируется как:
|
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V5609. |