Small HTTP server: поиск блох
Small HTTP server 3.0395
Один знакомый спросил меня по аське — что я думаю по поводу Small HTTP server. Я его отправил к статьям годичной давности (смотреть тут, тут, тут и тут). «Ну, хорошо,» — сказал он — «а что ты думаешь по этому поводу сейчас?». Ничего по этому поводу «сейчас» я не думал, моего знакомого интересовала HTTP-составляющая этого сервера, поэтому я пообещал ему произвести пару-тройку тестов и высказать своё мнение.
Из дальнейшей беседы я понял, что производительность сервера моего знакомого не волнует, зато сильно интересует вопрос безопасности и наличия багов. Я произвёл тестирование до той кондиции, когда мой знакомый решил, что я своё обещание выполнил. А когда произвёл, понял, что результаты тестирования могут быть интересны более широкой публике — людям, использующим этот сервер в своих повседневных задачах или не знакомым с ним вовсе.
Эти результаты, оформленные должным образом, я и предлагаю вашему вниманию.
Давненько я не рассматривал замечательный продукт нашего программиста Макса Феоктистова Small HTTP server (SHS) на предмет багов и уязвимостей (в прошлом я это делал более-менее регулярно), а тем временем вышла версия 3.0395.
Small HTTP server — в прошлом HTTP-сервер, а в нынешней своей ипостаси — HTTP-, DNS-, Proxy-, FTP, POP3- и SMTP-сервер с поддержкой сервера динамических перенаправлений, виртуальных хостов, SSI, ISA и CGI-скриптов. Более всего продукт замечателен тем, что при своих возможностях он занимает всего 103 (!) килобайта.
В прошлом я периодически находил в нем уязвимости различного рода, Макс их исправлял, в частности, путём введения различных ограничений и проверок в код программы. В итоге, код так оброс различными коррективами, что в обработке запросов появились натуральные баги.
Сервер я запускал в установками по умолчанию, в корень сайта положил один-единственный файл index.shtm, с SSI-командой для вывода переменных сервера.
Первая ошибка связана с обработкой GET-запроса к индексному файлу. Вообще, если сервер обнаруживает, что запрос пришел не конкретному файлу, а какому-либо директорию, обычная практика в этом случае — сервер пытается найти в этом директории индексный файл и отдаёт его содержимое, если же такой файл не найден, обычно сервер показывает содержимое директория.
Все запросы, равно как и их содержание, в этом случае передаётся индексному файлу. Каким образом сервер отличает индексный файл от любого другого зависит от настроек сервера, собственно, как и его поведение в случае, если такой файл не найден.
Так вот, в случае SHS, GET-запрос к директории с какими-либо (даже пустыми) параметрами вызывает ошибку: на http://127.0.0.1/? сервер отвечает \(Undefined/default) Error. File not found.
Наверное, одна из самых распространённых ошибок доморощенных веб-серверов — неправильная обработка директория «две точки». Его указание в пути файла или URL’e обычно означает, что для извлечения файла требуется подняться на директорий выше. Обычная практика веб-серверов — игнорировать две точки, если путь выходит за директорий, где лежат файлы сайта.
SHS до жути боится двух точек в URL’e, так совершенно безвредные запросы
http://127.0.0.1/Folder../
http://127.0.0.1/file.shml?/..
http://127.0.0.1/file.shml?../
вызовут у него неадекватное bad reques (хотя ничего bad в таких requests нет).
Другая проблема SHS — негативное его отношение к слешам в конце запроса. Не то, чтобы они ему совсем не нравятся, но некоторые манипуляции с ними кажутся SHS чересчур подозрительными. Запросы ниже порождают уже знакомый «bad request».
http://127.0.0.1/file.shml?./
http:127.0.0.1/file.shml?
Другая беда — трансляция переменных запроса в переменные языка SSI. Видимо, преобразование URL к «нормальному» виду и отсечение всего подозрительного выполняются раньше любых других манипуляций. Так что после запроса
http://127.0.0.1/index.shtm?word/
в QUERY_STRING оказывается word\index.shtm, а после
http://127.0.0.1/index.shtm?/a
переменная QUERY_STRING содержит \a
Такое искажение данных недопустимо, если пытаться использовать вместе с SHS какие-либо скриптовые языки.
Собственно, даже при использовании SSI любое искажение входных данных может приводить к неожиданным, неприятным последствиям. SHS, помимо стандартной переменной QUERY_STRING, помещает данные запросы ещё и в переменные окружения, подобно тому, как это делает язык PHP. Например, запрос ?bar=1&foo=2 приведет к появлению двух переменных — bar со значением 1 и foo со значением 2.
Это очень удобно, так как позволяет использовать язык SSI для более широкого круга задач. К сожалению, и тут есть небольшой баг, искажающий внешние данные. Так запрос
http://127.0.0.1/index.shtm?var==value
порождает переменную var со значением value, хотя, по логике var должна содержать строку =value.
http://127.0.0.1/index.shtm?var=1=2
этот запрос, как не странно, порождает переменную var со значением… 2.
http://127.0.0.1/index.shtm?&
Косметический баг. В переменных окружения — пара переменных с пустыми именами и значениями.
Теперь, что касается уязвимостей. Сразу скажу, серьезно в этом плане я сервер не тестировал. Просто попробовал несколько первых комбинаций, из тех, что сразу пришли в голову.
Начнем с локальных уязвимостей. Оставим в стороне CGI/ISA и другие «внешние» вещи и займемся SSI.
Несложная команда, не лишенная логики
<!--#echo var="\"\"" -->
заставляет сервер подвисать после выполнения нескольких запросов к файлу, её содержащему.
Так же SHS не переваривает команду
<!--#exec cmd="\s.exe" --> после неё сервер выполняет недопустимую операцию и, с приличествующим шумом, умирает.
Сходная с предыдущей, команда
<!--#exec cmd="\"" -->
вводит сервер в прострацию — он зависает. Что-то не так в этом королевстве с экранированными кавычками.
Удалённая уязвимость, связанная, по всей видимости, с переполнением буфера (в этом легко убедиться, несколько сократив количество знаков & в запросе). Её я приберег на сладкое.
Как уже было сказано, запрос с одним амперсандом, порождает две пустые переменные, а вот запрос длиной в 40 амперсандов
http://127.0.0.1/index.shtm?&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
кончается для сервера фатально. По крайней мере, в моей Windows XP. Возможно, под другими операционками сакральное число этих знаков в запросе будет другим.
И, что самое интересное, судя по всему, вполне можно попытаться изготовить эксплоит, которых бы использовал эту уязвимость для выполнения вредоносного кода на атакуемой машине.
Повторюсь: все тесты выполнялись над версией 3.0395 под Windows XP. В качестве инструмента для всех запросов использовался браузер Internet Explorer 6.0. Сервер ставился в стандартной конфигурации, в корне сайта лежала одна-единственная страница index.shtm с командой <--#printenv --> внутри.
Вывод: Small HTTP server — безусловно отличный продукт, заслуживающий всяких похвал, но, к сожалению, недостаточно оттестированный. Для хостинга сайта, в силу постоянно обнаруживаемых ошибок в разборе HTTP-запроса, я бы его использовать не рекомендовал.
С другой стороны, в программе есть и другие сервера, которые, возможно окажутся более защищенными. Кроме того, у сервера есть неоспоримое преимущество — его размер в 103 килобайта, при таких-то возможностях. Мне видится, назначение SHS — работать на персональных компьютерах вне сети или в интранете, пока Макс не устранит эти, достойные сожаления, баги.
Кстати, до версии 1.22 обновился [ Photoshop’s Crap Remover ]. Всем, кому интересно, качайте новую версию.
Пишите!