Пишу, по большей части, про историю, свою жизнь и немного про программирование.

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-запрос к директории с какими-либо (даже пустыми) параметрами вызывает ошибку: на htt​p://127.0.0.1/? сервер отвечает \(Undefined/default) Error. File not found.

Наверное, одна из самых распространённых ошибок доморощенных веб-серверов — неправильная обработка директория «две точки». Его указание в пути файла или URL’e обычно означает, что для извлечения файла требуется подняться на директорий выше. Обычная практика веб-серверов — игнорировать две точки, если путь выходит за директорий, где лежат файлы сайта.

SHS до жути боится двух точек в URL’e, так совершенно безвредные запросы

htt​p://127.0.0.1/Folder../
htt​p://127.0.0.1/file.shml?/..
htt​p://127.0.0.1/file.shml?../

вызовут у него неадекватное bad reques (хотя ничего bad в таких requests нет).

Другая проблема SHS — негативное его отношение к слешам в конце запроса. Не то, чтобы они ему совсем не нравятся, но некоторые манипуляции с ними кажутся SHS чересчур подозрительными. Запросы ниже порождают уже знакомый «bad request».

htt​p://127.0.0.1/file.shml?./
htt​p:127.0.0.1/file.shml?

Другая беда — трансляция переменных запроса в переменные языка SSI. Видимо, преобразование URL к «нормальному» виду и отсечение всего подозрительного выполняются раньше любых других манипуляций. Так что после запроса

htt​p://127.0.0.1/index.shtm?word/
в QUERY_STRING оказывается word\index.shtm, а после

htt​p://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 для более широкого круга задач. К сожалению, и тут есть небольшой баг, искажающий внешние данные. Так запрос

htt​p://127.0.0.1/index.shtm?var==value
порождает переменную var со значением value, хотя, по логике var должна содержать строку =value.

htt​p://127.0.0.1/index.shtm?var=1=2
этот запрос, как не странно, порождает переменную var со значением… 2.

htt​p://127.0.0.1/index.shtm?&
Косметический баг. В переменных окружения — пара переменных с пустыми именами и значениями.

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

Начнем с локальных уязвимостей. Оставим в стороне CGI/ISA и другие «внешние» вещи и займемся SSI.

Несложная команда, не лишенная логики

<!-​​-#echo var="\"\"" -​​->
заставляет сервер подвисать после выполнения нескольких запросов к файлу, её содержащему.

Так же SHS не переваривает команду

<!-​-#exec cmd="\s.exe" -​-> после неё сервер выполняет недопустимую операцию и, с приличествующим шумом, умирает.

Сходная с предыдущей, команда

<!-​-#exec cmd="\"" -​->
вводит сервер в прострацию — он зависает. Что-то не так в этом королевстве с экранированными кавычками.

Удалённая уязвимость, связанная, по всей видимости, с переполнением буфера (в этом легко убедиться, несколько сократив количество знаков & в запросе). Её я приберег на сладкое.
Как уже было сказано, запрос с одним амперсандом, порождает две пустые переменные, а вот запрос длиной в 40 амперсандов

htt​p://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 ]. Всем, кому интересно, качайте новую версию.

Пишите!