> For the complete documentation index, see [llms.txt](https://notes.kraken-security.ru/kraken/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://notes.kraken-security.ru/kraken/secure-coding/server-side/directory-traversal.md).

# Directory Traversal

## 1. Введение:

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

## 2. Типичный уязвимый код:

Случаев, когда возможен обход каталога, очень много, и в большинстве случаев код уязвимого приложения выглядит следующим образом:

```
private static final String BASE_PATH = "/storage/items/images";

private void getProfileImage(HttpServletRequest request, 
HttpServletResponse response) throws IOException {
    
    String folderName = request.getParameter("folder");
    String fileName = request.getParameter("file");
    String path = BASE_PATH + folderName + fileName;

    File file = new File(path);
    
    buildResponse(response, file);
}

private void constructResponse(HttpServletResponse response, 
File file) throws IOException {
    
    response.setContentType("image/png");
    
    OutputStream os = response.getOutputStream();
    
    // Notice there is no extra validation on the path of the file, it is read 
    // straight away.
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
   
    byte[] buffer =  new byte[1024];
    int read;

    while ((read = bis.read(buffer)) != -1) {
        os.write(buffer, 0, read);
    }

    bis.close();
    os.flush();
    os.close();
}
```

Мы считываем тот факт, что путь строится (на основе BASE\_PATH и полученного запроса на имя файла и папки).

Догадываясь об этом, злоумышленник может ввести в имя файла вредоносный путь, например ../../../etc/passwd, который преобразуется в /storage/items/images/../../../etc/passwd (предполагается, что мы имеем дело с UNIX-системой), который затем интерпретируется системой как /etc/passwd, что приводит к утечке файла passwd.

## 3. Смягчение последствий:

### 3.1. Проверка абсолютного пути:

Самый эффективный способ предотвратить уязвимости Directory Traversal - не передавать пользовательский ввод в API файловой системы. Многие функции приложений, которые это делают, можно переписать, чтобы обеспечить более безопасное поведение.

Однако если это невозможно, приложение должно выполнять строгую проверку ввода параметров, предназначенных для операций с файловой системой. К ним относятся проверка пути и проверка абсолютного пути к данным, предоставленным пользователем.

Проще говоря, мы можем проверить абсолютный путь к запрашиваемому файлу и, если он не совпадает с нашим жестко закодированным базовым путем, вообще его проигнорировать.

```
private static final String BASE_PATH = "/storage/items/images";

private void getProfileImage(HttpServletRequest request, 
 HttpServletResponse response) throws IOException {
    
    String folderName = request.getParameter("folder");
    String fileName = request.getParameter("file");
    String path = BASE_PATH + folderName + fileName;

    File file = new File(path);
    
    String canonicalPath = file.getCanonicalPath();

    // Check whether the given path corresponds to the base path
    //(where the image files are stored)
    if(canonicalPath.startsWith(BASE_PATH)) {
        buildResponse(response, file);
    } else {
        throw new GenericException("Access denied.");
    }
}

private void constructResponse(HttpServletResponse response,
 File file) throws IOException {
    
    response.setContentType("image/png");
    
    OutputStream os = response.getOutputStream();
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
   
    byte[] buffer =  new byte[1024];
    int read;

    while ((read = bis.read(buffer)) != -1) {
        os.write(buffer, 0, read);
    }

    bis.close();
    os.flush();
    os.close();
}
```

### 3.2. Использование службы хостинга файлов:

Подобный подход к безопасному хранению файлов на CDN/облачном сервисе мы уже обсуждали здесь:

{% content-ref url="/pages/VljPpkW6eHkcxwy27mjE" %}
[File Upload](/kraken/secure-coding/server-side/file-upload.md)
{% endcontent-ref %}

Кроме того, извлечение этих файлов по умолчанию будет осуществляться безопасным и эффективным способом. Они очень просты в применении и использовании, так что вам определенно стоит использовать их в дальнейшем.

### 3.3. Косвенные ссылки на файлы:

Если хранение файлов на локальном сервере действительно необходимо, то наиболее безопасным способом защиты от атак обхода каталога является косвенный: вы присваиваете каждому файлу произвольный идентификатор, соответствующий пути к файлу, а затем заставляете все URL ссылаться на файл по этому идентификатору. Это можно сделать, например, с помощью базы данных (где хранится ссылка между путем к файлу и его относительным идентификатором)

## 4. Выводы:

Проверка абсолютного пути представляет собой основу защиты от обхода каталога. Однако основным способом защиты является использование CDN или любых других систем хранения файлов в онлайне/облаке. Если хранение файлов на локальном сервере является одним из ваших требований, помните, что косвенные ссылки на файлы - это очень мощная техника, и вы должны ее использовать.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://notes.kraken-security.ru/kraken/secure-coding/server-side/directory-traversal.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
