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:
Zip Slip осуществляется через передачу в приложение архива с вредоносными файлами внутри: они содержат в имени "dot-dot-slash" последовательности (../../evil.csx). Спровоцировав распаковку такого архива, злоумышленник может переписать любые файлы, к которым у приложения есть доступ.
В большинстве архиваторов и операционных систем создать файл с названием вида ../../evil.csx не получится из-за встроенных ограничений, тем не менее, существуют инструменты, допускающие эту операцию. Из-за этого атака Zip Slip и становится возможной.
Рассмотрим пример:
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.
Ожидается, что процесс распаковки любого архива будет защищён. Диагностическое правило считает все архивы внешними сущностями и потенциально подозрительными.
Исправленный пример:
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)));
}
}
}
Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.). |
Данная диагностика классифицируется как: