Уязвимости серверов к медленному чтению

:

Приветствую.
Хочу рассказать, чем я баловался в свободное от работы в Qualys время. Так как в англоязычном интернете на удивление много шума про Slow Read DoS attack, и уверен что получу здесь много полезной критики и дельных предложений.

В августе 2011 года написал програмку slowhttptest, которая тестирует веб-серверы на наличие уязвимостей, связанных с обработкой медленных HTTP запросов, таких как slowloris и slow HTTP Post. Цель — создать конфигурируемый инструмент, облегчающий работу разработчиков и позволить им концентрироваться на создании эффективных защит, а не ковырянии в питоне, на котором написаны большинство proof-of-concept эксплоитов.

А потом решил попробовать, как реагируют серверы на медленное чтение клиентами HTTP респонсов. На удивление плохо реагируют. Дефолтные apache, nginx, lightpd, IIS отказывают в обслуживании на ура.

А суть такова:

если найти ресурс на веб сервере, который размером больше send buffer-a, который ядро выделило для соединения, в который серверная программа пошлет ресурс, то если каким то образом вынудить ядро не принимать все данные — сервер будет пытаться послать оставшийся кусок данных, занимая ограниченную в размере очередь соединений, процессорное время, память, и свободное время сисадмина. Если забить такими соединяниями всю очередь — сервер, соответственно начнет отказывать в обслуживании быстрым клиентам.

Заставить ядро себя так вести довольно просто и описано было еще в 2008 году ребятами из Outpost24 в методе Sockstress: например, посылать в TCP пакете размер окна равным 0, т.е. у клиента нет места для приема данных. Дизайн TCP правильно подразумевает, что приложение, а не ядро обязано контролировать медленные и мертвые соеднинения. Однако за 4 года никто не пошевелил пальцем.

Sockstress вручную создает пакеты, высчитывает, когда послать очередное подтверждение, чтоб не ресетнуть persist timer на сервере, сложно короче.
Мой метод даже школьник в состоянии реализовать на практике:
Создаете сокет, задаете сравнительно малый размер receive buffer-а на клиенте, посылаете совершенно целостный и нормальный HTTP запрос на картинку размером 100Кб, например. Сервер берет картинку из памяти, дает ядру, чтоб тот передал ее в сеть. Сервер берет кусок картинки и шлет, клиент принимает первые тыщу байт, и говорит стоп, места нету. Сервер poll-ает сокет, пытаясь понять когда он будет готов к записи, а он не готов! Раз в минуту читаете пару байтов из клиентского receive buffer, чтоб TCP стек послал что то отличное от нуля, тем самым создав видимость живого соедниения для файрволов и IDS-ов.

Вот и все. Прошу сильно не пинать, первый технический пост на русском, но хабр нравится, неудержался. Детальное описание можно найти здесь.
P.S. Для предыдущей версии slowhttptest написал вики по-русски, если хоть одной душе интересно, переведу и для новой версии.

Update:
ModSecurity подсуетилась, детально показывают как защищаться:
ModSecurity Advanced Topic of the Week: Mitigation of 'Slow Read" Denial of Service Attack
Update 2:
Semy указал на ошибки сборки на BSD. Исправил в svn.