﻿# V5338\. OWASP\. Possible Zip Slip vulnerability\. Potentially tainted data might be used to extract the file\.

Анализатор обнаружил, что имя файла, полученное из архива, используется в качестве пути к файлам или папкам без предварительной проверки\. Если в имени файла присутствуют "dot\-dot\-slash" последовательности, операции с файлом приведут к возникновению уязвимости Zip Slip в приложении\.

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

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

Zip Slip осуществляется через передачу в приложение архива с вредоносными файлами внутри: они содержат в имени "dot\-dot\-slash" последовательности \(`../../evil.csx`\)\. Спровоцировав распаковку такого архива, злоумышленник может переписать любые файлы, к которым у приложения есть доступ\.

В большинстве архиваторов и операционных систем создать файл с названием вида `../../evil.csx` не получится из\-за встроенных ограничений, тем не менее, существуют инструменты, допускающие эту операцию\. Из\-за этого атака Zip Slip и становится возможной\.

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

```cpp
public void extractArchive(String destinationDir, ZipFile zip) {
    Enumeration<? extends ZipEntry> entries = zip.entries();
    while (entries.hasMoreElements()) {
        ZipEntry entry = entries.nextElement();

        File file = new File(destinationDir, entry.getName());

        InputStream input = zip.getInputStream(entry);
        IOUtils.copy(input, new WriterOutputStream(new FileWriter(file)));
    }
}
```

Данный метод принимает архив и распаковывает его в `destinationDir`\. Но путь до места распаковки файла создаётся из имени записи в архиве, из\-за чего данный код подвержен уязвимости Zip Slip\. Если в приложение попадёт вредоносный архив, то он может быть распакован в любом месте системы, к которому приложение имеет доступ\.

Для защиты от Zip Slip можно проверять, находится ли целевой путь внутри исходной директории\. В примере выше рекомендуется использовать метод `getCanonicalPath()` для приведения пути к канонической форме \(путь без относительных переходов `..`, `.` и избыточных разделителей\) с последующей проверкой через `startsWith(destinationDir)`\. Это предотвратит доступ к файлам за пределами разрешённой директории, даже если путь содержит замаскированные относительные переходы, например, `../../evil.csx`\.

Ожидается, что процесс распаковки любого архива будет защищён\. Диагностическое правило считает все архивы внешними сущностями и потенциально подозрительными\.

Исправленный пример:

```cpp
public void extractArchive(String destinationDir, ZipFile zip) {
    Enumeration<? extends ZipEntry> entries = zip.entries();
    while (entries.hasMoreElements()) {
        ZipEntry entry = entries.nextElement();

        File file = new File(destinationDir, entry.getName());

        if (file.getCanonicalPath().startsWith(destinationDir)) {
            InputStream input = zip.getInputStream(entry);
            IOUtils.copy(input, new WriterOutputStream(new FileWriter(file)));
        }
    }
}
```