V5628. OWASP. Possible Zip Slip vulnerability. Potentially tainted data is used in the path to extract the file.
Анализатор обнаружил операцию извлечения файла по непроверенному пути, включающему имя файла. В случае наличия в имени файла "dot-dot-slash" последовательностей эта операция приведет к возникновению уязвимости Zip Slip в приложении.
Zip Slip проводится через передачу в приложение архива с вредоносными файлами внутри: они содержат в имени "dot-dot-slash" последовательности ("../../evil.csx"). Спровоцировав распаковку такого архива, злоумышленник может переписать любые файлы, к которым у приложения есть доступ.
В большинстве архиваторов или операционных систем создать файл с названием вида '../../evil.csx' не получится из-за встроенных ограничений. Тем не менее, существуют инструменты, допускающие эту операцию. Из-за этого атака Zip Slip и становится возможной.
Рассмотрим пример небезопасного кода:
public void ExtractArchive(ZipArchive archive, string destinationDirectory)
{
var entries = archive.Entries;
foreach (var entry in entries)
{
var extractPath = Path.Combine(destinationDirectory, entry.FullName);
entry.ExtractToFile(extractPath, true);
}
}
Здесь внутри цикла файлы поочередно извлекаются из архива в директорию, расположенную по пути 'destinationDirectory'. Для каждого файла создаётся путь распаковки с помощью метода 'Path.Combine', после чего результат записывается в переменную 'extractPath'. Далее 'extractPath' используется в качестве аргумента метода 'entry.ExtractToFile', выполняющего разархивирование файла по заданному пути.
Предположим, что архив должен быть извлечён в директорию 'C:\ApplicationFiles\UserFiles'. Однако если свойство 'entry.FullName' вернёт строку вида '\..\config.ini', файл попадёт в корневой каталог приложения 'C:\ApplicationFiles'. В случае совпадения имени извлекаемого файла и, например, файла конфигурации приложения, будет выполнена перезапись последнего.
Обезопасить код в предыдущем примере можно, например, следующим образом:
public void ExtractArchive(ZipArchive archive, string destinationDirectory)
{
var destinationDirectoryFullPath = Path.GetFullPath(destinationDirectory);
foreach (var entry in archive.Entries)
{
var extractPath = Path.Combine(destinationDirectory, entry.FullName);
var extractFullPath = Path.GetFullPath(extractPath);
if (!extractFullPath.StartsWith(destinationDirectoryFullPath))
{
throw new IOException("Zip Slip vulnerability");
}
entry.ExtractToFile(extractFullPath);
}
}
Здесь в переменную 'extractFullPath' записывается результат обработки пути 'extractPath' методом 'Path.GetFullPath'. В ходе этой операции путь, содержащий "dot-dot-slash" последовательности, будет заменен на аналогичный, не включающий их.
После этого с помощью метода 'extractFullPath.StartsWith' проверяется, не изменилась ли директория для распаковки файла в результате предыдущей операции. В случае если произошла подмена директории, выбрасывается исключение.
Данная диагностика классифицируется как: