> 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/file-upload.md).

# File Upload

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

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

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

* [x] Список разрешенных расширений. Разрешите только безопасные и критически важные расширения для бизнес-функций.
* [x] **Убедитесь, что загруженные файлы не могут быть выполнены как код!**
* [x] Убедитесь, что проверка ввода применяется перед проверкой расширений.
* [x] Измените имя файла на то, которое генерируется приложением. (например, пользовательская хэш-функция 'a.txt' -> jd21j3jjd213jj3321.txt)
* [x] Установите ограничение на длину имени файла. По возможности ограничьте допустимые символы. (Попробуйте очистить имя файла)
* [x] Установите ограничение на размер файла.
* [x] Разрешите загрузку файлов только авторизованным пользователям.
* [x] Храните файлы на другом сервере. Если это невозможно, храните их за пределами webroot.
* [x] В случае публичного доступа к файлам используйте обработчик, который сопоставляется с именами файлов внутри приложения (некоторый идентификатор -> файл.расширение)
* [x] Прогоняте файлы через антивирус или "песочницу", если таковая имеется, чтобы убедиться, что он не содержит вредоносных данных.
* [x] Убедитесь, что все используемые библиотеки надежно настроены и поддерживаются в актуальном состоянии.
* [x] Защитите загрузку файла от CSRF-атак. (Если у вас реализовано что-то вроде `get-this-file-from-this-url`).

## 2. Методы смягчения последствий и защиты:

### 2.1. Использование системы безопасного хранения:

`Зомби, которого нет в вашем доме, не может причинить вам вреда!`

Шутки в сторону, один из самых важных подходов к обеспечению безопасности функции загрузки файлов заключается в том, чтобы ваш веб-сервер воспринимал загружаемые файлы как инертные, а не как исполняемые объекты. В этом смысле вы можете выбрать альтернативу хранения загружаемых файлов в CDN (Content Delivery Network), например Cloudflare; возможно, вы уже догадались из моей цитаты про зомби, что таким образом разработчик, по сути, снимает бремя безопасности с третьей стороны, с которой он работает, так что файлы всегда хранятся безопасно таким образом.

Конечно, использование CDN может оказаться не самым лучшим вариантом, и тогда вы можете выбрать одну из других альтернатив, например облачное хранилище (Amazon S3, Google Storage Bucket и т. д.) или даже выделенную CMS (хотя это сопряжено с дополнительной головной болью по настройке и вниманию).

### 2.2. Различные методы защиты и альтернативы:

Вы можете не использовать CDN или любую из перечисленных выше альтернатив. В таком случае, если вам действительно необходимо загрузить файлы на "локальный" диск, вот что нужно сделать:

* Переименовывать файлы по мере их загрузки: создание собственной или использование стандартной функции хэширования для имен файлов - хороший принцип, чтобы было сложнее догадаться, где именно были сохранены файлы.
* Запись на диск без прав на исполнение: это необходимый шаг к обеспечению безопасности процесса загрузки. Существует бесчисленное множество скриптов или исполняемых файлов, которые могут быть использованы злоумышленниками, поэтому вы просто обязаны снять такие разрешения с загружаемых файлов.

{% tabs %}
{% tab title="Python" %}

```python
import os

file_f = os.open("/path/to/your/file", os.O_WRONLY | os.O_CREAT, 0o600)

with os.fdopen(open(file_f, "wb")) as file_handling:
    file_handling.write(...)
```

{% endtab %}

{% tab title="Node.js" %}

```ruby
var chmodr = require('chmodr');

chmodr('/path/to/entire/folder', 0o600, (err) => {
  if (err) {
    console.log('Failed to execute chmod', err);
  } else {
    console.log('Success');
  }
});

```

{% endtab %}
{% endtabs %}

* Проверка расширений файлов: убедитесь, что проверка происходит после декодирования имени файла и что установлен соответствующий фильтр, чтобы избежать некоторых известных обходов, таких как следующие:
  * Двойные расширения, например .jpg.php, где легко обходится regex .jpg.
  * Нулевые байты, например, .php%00.jpg, где .jpg обрезается, а .php становится новым расширением.
  * Плохой регекс, который не был должным образом протестирован и проверен. Воздержитесь от создания собственной логики, если у вас нет достаточных знаний по этой теме.
* Проверка содержимого файла: Поскольку содержимое файла может содержать вредоносные или нежелательные данные, разработчик всегда может провести его дополнительную проверку, основываясь на предполагаемом типе файла:
  * Что касается изображений, то стоит прочитать эти два поста: Inject Executable, malicious code into PNG и How can I be protected from picture vulnerabilities. Переписывание изображений - одна из распространенных техник, которая теоретически уничтожает любой вид вредоносного содержимого, которое может быть внедрено в изображение, и обычно это делается с помощью рандомизации.
  * Загружать ZIP-файлы категорически не рекомендуется, поскольку они могут содержать буквально любые типы файлов, а значит, допускают безграничные возможности.

## 3. Выводы:

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


---

# 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/file-upload.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.
