Безопасность распаковки пользовательских файлов

здесь не столько проблема кодирования, сколько общий вопрос, касающийся безопасности. В настоящее время я работаю над проектом, который позволяет пользователю отправлять контент. Ключевой частью этого контента является загрузка пользователем Zip-файла. Zip-файл должен содержать только mp3-файлы.

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

меня беспокоит то, что это открывает нас для некоторых потенциально опасных zip файлы. Я читал о "zipbombs" в прошлом и, очевидно, не хочу, чтобы вредоносный zip-файл наносил ущерб.

Итак, есть ли безопасный способ сделать это? Могу ли я сканировать zip-файл, не распаковывая его, и если он содержит что-либо, кроме MP3, удалите его или отметьте предупреждение администратору?

Если это имеет значение я разрабатываю сайт на WordPress. В настоящее время я использую встроенные функции загрузки wordpress, чтобы пользователь мог загрузить zip-файл на наш сервер (я не уверен, есть ли какая-либо форма безопасности в wordpress уже для сканирования zip-файла?)

3 ответов


код, только извлечь MP3 из zip, игнорировать все остальное

$zip = new ZipArchive();
$filename = 'newzip.zip';

if ($zip->open($filename)!==TRUE) {
   exit("cannot open <$filename>\n");
}

for ($i=0; $i<$zip->numFiles;$i++) {
   $info = $zip->statIndex($i);
   $file = pathinfo($info['name']);
   if(strtolower($file['extension']) == "mp3") {
        file_put_contents(basename($info['name']), $zip->getFromIndex($i));
   }

}
$zip->close();

Я бы использовал что-то вроде id3_get_version (http://www.php.net/manual/en/function.id3-get-version.php), чтобы убедиться, что содержимое файла mp3 тоже


Почему они должны застегнуть МР3? Если в информации ID3v2 в MP3s нет много текстовых фреймов, размер файла фактически увеличится с помощью ZIP из-за хранения словаря.

насколько я знаю, нет никакого способа сканировать ZIP, фактически не разбирая его. Данные непрозрачны, пока вы не запустите каждый бит через словарь Хаффмана. И как бы вы определили, какой файл является MP3? По расширению файла? По рамкам? Кодеры MP3 имеют свободный стандарт (декодеры имеют более строгую спецификацию), что затрудняет сканирование файловой структуры без ложных негативов.

вот некоторые риски безопасности ZIP:

  1. комментировать данные, вызывающие переполнение буфера. Решение: удалить данные комментариев.
  2. молнии, которые малы в сжатом размере, но надуваются, чтобы заполнить файловую систему (классическая zip-бомба). Решение: проверите надутый размер перед надувать; проверите словарь для обеспечения его имеет много записей, и это обжатое данные не все 1.
  3. вложенные молнии (связанные с #2). Решение: остановить, когда запись в ZIP-архиве сама является ZIP-данными. Вы можете определить это, проверив маркер Центрального каталога, номер 0x02014b50 (шестнадцатеричный, всегда маленький-endian в ZIP -http://en.wikipedia.org/wiki/Zip_%28file_format%29#Structure).
  4. вложенные структуры каталогов, предназначенные для превышения предела файловой системы и зависания процесса дефляции. Решение: не распаковывать справочники.

Итак, либо сделайте много проверок очистки и целостности, либо, по крайней мере, используйте PHP для сканирования архива; проверьте каждый файл на его MP3-ness (однако вы это делаете - расширение и наличие MP3-заголовков? Однако вы не можете полагаться на то, что они находятся в байте 0. http://en.wikipedia.org/wiki/MP3#File_structure) и дефлированные размер файла (http://www.php.net/manual/en/function.zip-entry-filesize.php). Выручить при завышенной файла слишком большой, или если есть какие-либо не-MP3s присутствует.


используйте следующий код имена файлов внутри a .zip-архив:

$zip = zip_open('test.zip');

while($entry = zip_read($zip)) {
    $file_name = zip_entry_name($entry);
    $ext = pathinfo($file_name, PATHINFO_EXTENSION);
    if(strtoupper($ext) !== 'MP3') {
        notify_admin($file_name);
    }
}

обратите внимание, что следующий код будет только посмотреть на расширение. Это означает, что пользователь может загружать все, что имеет расширение MP3. Чтобы действительно проверить, является ли файл mp3, вам придется его распаковать. Я бы посоветовал вам сделать это во временном каталоге.

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

Если анализ не удается, вы можете пометить файл.