
Классическое переполнение буфера стека в Savant Web Server 3.1, демонстрирующее удалённое повреждение памяти начала 2000-х годов через специально созданный HTTP-запрос.
Классический переполнение буфера на стеке в Savant Web Server 3.1, демонстрирующее удаленное повреждение памяти начала 2000-х годов через специально сформированный HTTP-запрос (уязвимость 2002 года, которая требует от новичка большего, чем большинство переполнений буфера CVE 2025 года).
Этот репозиторий является частью материалов, которые я использую при обучении эксплуатации повреждений памяти (в дополнение к основной работе я также преподаю на различных курсах по кибербезопасности, где помогаю обучать следующее поколение реверс-инженеров). Когда я рассматриваю переполнение буфера на стеке в классе, я работаю с реальными случаями, а не с игрушечными примерами, и эта CVE — одна из тех, к которым я возвращаюсь специально, когда хочу проверить студентов, уже имеющих некоторый опыт с базовым перезаписью EIP.
Причина в том, что год в идентификаторе CVE ничего не говорит о том, насколько сложна эксплуатация. Большинство студентов полагают, что старые CVE должны быть проще: прямолинейное переполнение, JMP ESP, и готово. Эта уязвимость доказывает обратное. Некоторые CVE, которые я преподаю, начиная с 2025 года, принципиально более просты, потому что класс уязвимости проще или ограничений меньше. CVE-2002-1120 требует понимания вещей, которые не требуются некоторым современным эксплоитам: почему определенные опкоды нельзя использовать в определенных частях запроса, как создать условный переход, который всегда срабатывает, когда безусловный заблокирован, как доставить шелл-код, когда он не помещается туда, куда обычно помещают, и как эггхантер решает проблему с пространством, которая в противном случае сделала бы эксплойт невозможным.
Это та CVE, которую я назначаю, когда хочу проверить, действительно ли кто-то понимает, что делает.
Эта уязвимость затрагивает Savant 3.1 — бесплатный HTTP-сервер для Windows от 2002 года. Что делает его достойным изучения в 2025 году, это не возраст, а комбинация ограничений, которые он вводит, и методов, необходимых для их обхода:
Каждое из этих ограничений — отдельный урок.
Savant — это бесплатный HTTP-сервер с открытым исходным кодом для Windows, изначально предназначенный для превращения любого настольного компьютера в веб-сервер. Он прослушивает TCP-порт 80 и обрабатывает стандартные HTTP GET-запросы. Переполнение происходит в обработчике, который копирует путь URI в буфер фиксированного размера на стеке без проверки длины.
Ключевые технические детали:
Savant обрабатывает входящие HTTP GET запросы и копирует путь URI в буфер фиксированного размера на стеке без проверки длины. Упрощенная версия уязвимой логики выглядит так:
char uri_buffer[270];
strcpy(uri_buffer, uri_path);
Отправка GET-запроса с URI длиной примерно 271 байт перезаписывает сохраненный адрес возврата на стеке. Переполнение ограничено: отправка значительно большего количества приводит к сбою таким образом, что EIP больше не контролируется, поэтому доступное окно узкое.
Эксплуатация сложнее, чем стандартная перезапись EIP, из-за двух дополнительных свойств сервера: поле HTTP-метода также копируется в память и выполняется, а тело HTTP-запроса хранится в отдельной области кучи, а не на стеке (оба этих свойства становятся важными частями цепочки эксплойта).
Сбой можно воспроизвести, отправив GET-запрос с достаточно длинным URI. Аутентификация не требуется. Пример на Python:
import socket
HOST = '127.0.0.1'
PORT = 80
payload = b"A" * 271
request = (
b"GET /" + payload + b" HTTP/1.1\r\n"
b"Host: 127.0.0.1\r\n"
b"Connection: close\r\n"
b"\r\n"
)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send(request)
s.close()
При выполнении под отладчиком сбой показывает EIP, перезаписанный данными, контролируемыми пользователем:
EIP = 41414141
что подтверждает повреждение сохраненного адреса возврата из-за переполнения.
Цель этого репозитория — не только продемонстрировать сбой, но и пошагово провести через полный процесс эксплуатации, включая все ограничения, которые делают этот случай сложнее стандартной перезаписи EIP, и все решения, принятые для их обхода.
Чтобы основной README оставался чистым, подробные заметки по эксплуатации, скрипты и шаги отладчика помещены в папку Vulnerability 📂 этого репозитория.
Там вы найдете полный рабочий процесс, используемый для эксплуатации этой CVE, включая: