﻿# V5609\. OWASP\. Possible path traversal vulnerability\. Potentially tainted data is used as a path\.

Анализатор обнаружил, что данные, полученные из внешнего источника, используются в качестве путей к файлам или папкам без предварительной проверки\. Это может стать причиной уязвимости приложения к атакам path traversal\.

Атаки этого типа выделены в отдельную категорию рисков в OWASP Top 10 Application Security Risks 2017: [A5:2017\-Broken Access Control](https://owasp.org/www-project-top-ten/2017/A5_2017-Broken_Access_Control.html)\.

Рассмотрим пример:

```cpp
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"\]' следующую строку:

```cpp
..\admin\userInfo.xml
```

Для защиты от такой атаки недостаточно простой проверки на наличие '\.\.\\' в начале строки\. К примеру, для получения тех же данных может передаваться и строка

```cpp
someFolder\..\..\admin\userInfo.xml
```

Ещё одна возможность для атаки – передача абсолютного пути вместо относительного\. Если один из аргументов 'Path\.Combine' представляет собой абсолютный путь, то все ранее записанные аргументы игнорируются\. К примеру, метод может быть вызван следующим образом:

```cpp
Path.Combine("folder", "childFolder", "C:\Users\Admin\secret.txt")
```

В результате будет возвращена строка 'C:\\Users\\Admin\\secret\.txt '\. Таким образом, отсутствие проверки входных данных позволяет злоумышленнику получить доступ к любому файлу в системе\. Более подробно атаки типа path traversal и способы их проведения описаны на официальном сайте OWASP по [ссылке](https://owasp.org/www-community/attacks/Path_Traversal)\.

Для обеспечения защиты от path traversal необходимо применять различные средства проверки входных данных\. В примере, описанном выше, можно использовать проверку на наличие подстрок ":" и "\.\.\\":

```cpp
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
  {
    ....
  }
}
```

Анализатор также считает источниками небезопасных данных параметры методов, доступных из других сборок\. Эта тема подробно раскрыта в заметке "[Почему важно проверять значения параметров общедоступных методов](https://pvs-studio.ru/ru/blog/posts/csharp/0835/)"\.

Рассмотрим пример кода, выполняющегося на ОС Windows:

```cpp
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', так как возвращаемое им значение в любом случае будет абсолютным путём:

```cpp
public void WriteUserFile(string relativePath) 
{ 
  if (relativePath.Contains(":") || relativePath.Contains(@"..\"))
  {
    ....
    
    return;
  }

  string path = Path.Combine(UsersDirectoryAbsolutePath,
                             userName,
                             relativePath);
  WriteFile(path);
}
```