Блокировка загрузки исполняемых изображений (PHP) - PullRequest
2 голосов
/ 17 мая 2010

Мне стало известно, что пользователь пытается создать эксплойт с помощью загрузки аватара. Это было обнаружено, когда пользователь сообщил мне, что получает уведомление от своего антивируса Norton с надписью «Загрузка подозрительного исполняемого образа HTTP». Это предупреждение ссылается на изображение аватара пользователя. Я не думаю, что они действительно достигли чего-либо путем кражи информации или чего-то подобного, но я предполагаю, что это могло бы быть возможно, если бы дыра оставалась открытой достаточно долго. Я использую PHP для загрузки файлов изображений и проверяю, является ли загружаемый файл форматом png, jpg, bmp или gif.

Это код, который проверяет, является ли это изображение:

$allow_types = array('image/jpeg', 'image/png', 'image/gif', 'image/jpg', 'image/png', 'image/bmp', 'image/bitmap');
if (in_array($this->tmp_image['type'], 
$this->allow_types)) {
   return true;
}

Ответы [ 4 ]

7 голосов
/ 17 мая 2010

Нет способа предотвратить загрузку вредоносных файлов. Вместо этого вам нужно заботиться о том, как обращаться с этими файлами.

Предложения, такие как повторное сохранение файла изображения, обречены. Можно обойти такие манипуляции, упорядочив биты так, чтобы они находились в том порядке, в котором их хочет атакующий после запуска известного компрессора изображений.

Существует так много способов объединить изображения и вредоносные файлы. Вредоносный файл может быть исполняемым файлом или просто содержать JavaScript, который интерпретируется браузером. Кроме того, как вы должны повторно сохранять файлы, которые не являются типом изображения?

При обработке загрузки файлов необходимо учитывать следующее.

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

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

  • Храните файлы над корнем документа, чтобы они не были доступны напрямую.

  • Служите вашим файлам через скрипт PHP-прокси, напишите что-то вроде:

    $data = file_get_contents('/home/account/files/file.png');
    header('Content-Type: image/png');
    header('Content-Length: '. strlen($data));
    header('X-Content-Type-Options: nosniff');
    echo $data;
    
  • Переименуйте загруженные файлы, чтобы иметь совершенно случайное имя без расширения. Если вам нужно сохранить имя файла (и расширение / тип), сохраните данные в базе данных.

  • При необходимости обслуживать файлы только тогда, когда у пользователя есть разрешение на его получение.

  • Никогда не включайте / не выполняйте загруженные вами файлы. Это означает, что не нужно включать или требовать в PHP. Нет тегов HTML-сценариев или тегов таблиц стилей, включая их. Нет Apache Включить команды, включая их. И пр.

  • Если это вообще возможно, подайте файлы из другого источника. Это устраняет проблемы происхождения, которые чаще всего возникают с Flash. Использование другого порта, доменного имени или IP-адреса также хорошо. Обслуживание с поддоменов опасно, и с IP-адресами реализация становится немного сложнее (т.е. вы не можете обслуживать файлы через домен, только через IP, и вы не можете обслуживать сайт через IP, но через домен).

  • Остерегайтесь LFI и RFI. Переименуйте имена файлов перед тем, как использовать имя файла в таких функциях, как fopen(), read() и т. Д., И при необходимости проверьте / очистите все значения каталога.

2 голосов
/ 17 мая 2010

Самым простым решением является повторная выборка изображения. Получите простую библиотеку манипуляций с изображениями (GD) и загрузите заново, сохраните изображение, оно должно эффективно удалить любой исполняемый контент или просто потерпеть неудачу, если изображение просто переименовано в exe.

0 голосов
/ 18 мая 2010

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

см. Эту ссылку http://www.bitrepository.com/how-to-validate-an-image-upload.html

0 голосов
/ 17 мая 2010

используйте imagecreatefromjpeg (и другие imagecreatefrom *), чтобы проверить, что переданные данные являются фактическим изображением. exe не пройдет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...