﻿# V5332\. OWASP\. Possible path traversal vulnerability\. Potentially tainted data might be used to access files or folders outside a target directory\.

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

Атаки этого типа выделены в отдельную категорию рисков в OWASP Top 10 Application Security Risks:

* [A01:2021 – Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/)

Path traversal — это уязвимость, позволяющая злоумышленнику читать, записывать или удалять файлы за пределами разрешённой директории\. Это происходит из\-за обработки пользовательского ввода, содержащего специальные символы \(например, `..`\)\. В результате злоумышленник может получить доступ к конфиденциальным данным \(паролям, ключам, конфигурациям\) или нарушить работу приложения\. Ознакомиться с этой уязвимостью подробнее можете по [этой](https://pvs-studio.ru/ru/blog/terms/6470/) ссылке\.

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

```cpp
HttpServletRequest request;
HttpServletResponse response;

void write(Path userdir) throws IOException {

    ....

    String userFileRelativePath = request.getParameter("relativePath");

    Path fullPath = userdir.resolve(userFileRelativePath);
    String content = Files.readString(fullPath);

    ....

    response.getWriter().write(content);
}
```

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

В качестве относительного пути здесь используется значение, полученное из внешнего источника — `request.getParameter`\. Отсутствие каких\-либо проверок позволяет злоумышленнику получить доступ к содержимому любых файлов в системе\. 

Например, в папке каждого пользователя может храниться файл `userInfo.xml`, в котором содержится различная, в том числе конфиденциальная, информация \(при этом код выполняется на системе Windows\)\. Тогда для получения доступа к данным пользователя `admin` злоумышленник может передать в `request.getParameter("relativePath")` следующую строку:

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

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

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

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

```cpp
userdir.resolve("C:\\Users\\Admin\\secret.txt");
```

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

Для защиты от path traversal можно проверять, находится ли целевой путь внутри исходной директории\. В примере выше рекомендуется использовать метод `normalize()` для приведения пути к канонической форме \(путь без относительных переходов `..`, `.` и избыточных разделителей\) с последующей проверкой через `startsWith(userdir)`\. Это предотвратит доступ к файлам за пределами разрешённой директории, даже если путь содержит замаскированные относительные переходы, например, `someFolder\..\..\admin\userInfo.xml`\.

```cpp
HttpServletRequest request;
HttpServletResponse response;

void write(Path userdir) throws IOException {

    ....

    String userFileRelativePath = request.getParameter("relativePath");

    Path fullPath = userdir.resolve(userFileRelativePath);
    
    if (fullPath.normalize().startsWith(userdir)) {
        String content = Files.readString(fullPath);

        ....

        response.getWriter().write(content);
    } else {
        ....
    }
}
```