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:

Path traversal — это уязвимость, позволяющая злоумышленнику читать, записывать или удалять файлы за пределами разрешённой директории. Это происходит из-за обработки пользовательского ввода, содержащего специальные символы (например, ..). В результате злоумышленник может получить доступ к конфиденциальным данным (паролям, ключам, конфигурациям) или нарушить работу приложения. Ознакомиться с этой уязвимостью подробнее можете по этой ссылке.

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

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") следующую строку:

..\admin\userInfo.xml

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

someFolder\..\..\admin\userInfo.xml

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

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

В результате будет получен путь C:\Users\Admin\secret.txt. Таким образом, отсутствие проверки входных данных позволяет злоумышленнику получить доступ к любому файлу в системе. Более подробно атаки типа path traversal и способы их проведения описаны на официальном сайте OWASP по ссылке.

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

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

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.).

Данная диагностика классифицируется как: