Я заметил, что PHP Imagick изменяет блоки IDAT при обработке PNG.
Как именно это сделано? Есть ли возможность создавать фрагменты IDAT, которые остаются неизменными? Можно ли предсказать исход Imagick?
Справочная информация к этим вопросам:
Мне было интересно, может ли следующий код (часть загрузки файла PHP) предотвратить скрытие кода PHP (например, веб-оболочек) в PNG:
$image = new Imagick('uploaded_file.png');
$image->stripImage();
$image->writeImage('secure_file.png');
Комментарии удаляются, поэтому единственный способ обойти этот фильтр — скрыть полезную нагрузку PHP в блоке (ах) IDAT. Как описано Вот, это теоретически возможно, но Imagick каким-то образом интерпретирует эти данные изображения, даже если я установлю Compression
а также CompressionQuality
к значениям, которые я использовал для создания PNG. Мне также удалось создать PNG, чей заголовок ZLIB остался неизменным в Imagick, но необработанные сжатые данные изображений этого не сделали. Единственные PNG, где у меня были идентичные входные и выходные данные, были те, которые проходили через Imagick раньше. Я также пытался найти причину этого в исходный код, но не смог найти его.
Мне известно о том, что необходимы другие проверки, чтобы убедиться, что загруженный файл действительно является PNG и т. Д., И PHP-код в PNG не является проблемой, если сервер настроен правильно, но сейчас я просто заинтересован в этой проблеме.
Куски IDAT могут различаться и по-прежнему создавать идентичное изображение. К сожалению, спецификация PNG заставляет блоки IDAT формировать единый непрерывный поток данных. Это означает, что данные могут быть сгруппированы / разбиты на части по-разному, но при повторной сборке в один поток будут идентичны. Отличаются ли фактические данные или только «чанкинг» изменился? Если позже, почему это имеет значение, если изображение идентично? PNG — это тип сжатия без потерь, удаление метаданных и даже распаковка + повторное сжатие изображения не должно изменять значения пикселей.
Если вы сравниваете сжатые данные и ожидаете, что они будут идентичными, они могут отличаться и по-прежнему давать идентичное изображение. Это связано с тем, что сжатие FLATE использует итеративный процесс для поиска наилучших совпадений в предыдущих данных. Чем выше «качественное» число, которое вы ему дадите, тем больше оно будет искать совпадения и уменьшать размер выходных данных. С zlib запрос дефляции уровня 9 займет намного больше времени, чем по умолчанию, и приведет к немного меньшему размеру выходных данных.
Поэтому, пожалуйста, ответьте на следующие вопросы:
1) Вы пытаетесь сравнить сжатые данные до / после операции стриптиза, чтобы увидеть, изменилось ли изображение? Если это так, то просмотр сжатых данных не является способом сделать это.
2) Если вы хотите удалить метаданные без изменения какого-либо другого аспекта файла изображения, вам придется написать инструмент самостоятельно. На самом деле тривиально просмотреть фрагменты PNG и собрать новый файл, пропуская фрагменты, которые вы хотите удалить.
Ответьте на мои вопросы, и я дополню свой ответ более подробной информацией …
Мне было интересно, может ли следующий код (часть загрузки файла PHP) предотвратить скрытие кода PHP (например, веб-оболочек) в PNG
Вы никогда не должны думать об этом. Если вы беспокоитесь о том, что люди прячут веб-оболочки в файле, загружаемом на ваш сервер, вы делаете что-то не так.
Например, обработка этих файлов через синтаксический анализатор PHP …. таким образом, веб-оболочка может быть использована для атаки на сервер.
Из файла readme Imagick:
5) НИКОГДА не обслуживать любые файлы, которые были загружены пользователями напрямую через PHP, вместо этого либо обслуживать их через веб-сервер, без вызова PHP, либо использовать readfile для обслуживания их в PHP.
ReadFile не выполняет файл, он просто отправляет его конечному пользователю, не вызывая его, и, таким образом, полностью предотвращает тип атаки, которая вас беспокоит.