На днях вышло исследование от команды Portswigger с кричащим названием "HTTP/1.1 Must Die".
Ресерч посвящен объяснению ключевых проблем версии протокола 1.1 и новой технике HTTP Request Smuggling - 0.CL. Как в целом и все прочие их исследования, статья очень хорошая и я бы рекомендовал прочитать ее полностью. Но если вы не хотите тратить время на ее прочтение (справедливости ради, она достаточно длинная), приведу основные поинты выделенные в статье:
- ⏩Протокол HTTP/1.1 имеет в себе проблему на уровне дизайна. Так как протокол тектовый (а не бинарный, как, например, HTTP/2) в нем отсутствуют нормальные принципы разраничения одного запроса от другого (если точнее, то их существуют несколько и все они достаточно абстрактны)
- ⏩Различные имплементации HTTP/1.1 только усугубляют ситуацию
- ⏩С момента обнаружения эксплуатации этой проблемы (HTTP Request Smuggling) в 2004 году мы постоянно пытаемся запатчить или скрыть какие-то проблемы, но это порождает лишь новые и новые уязвимости и их количество никогда не закончится
- ⏩Показана новая теника эксплуатации 0.CL. Смысл заключается в том, что мы скрываем заголовок "Content-Length" (или причастные) от Frontend-сервера, но делаем его заметным для Backend-сервера. При этом важно найти гаджет, который позваоляет получить ответ от приложения на неполный запрос (чтобы обойти таймаут соединения). Эксплуатация происходит в три этапа: 1. Очередь запросов отравляется 0.CL; 2. Очередь отравляется заново на этот раз известными техниками CL.0; 3. Происходит похек пользователей
- ⏩Также показаны способы эксплуатации 0.CL при помощи древнего заголовка Expect - многие парсеры просто не умеют нормально работать с его функциональностью (он предполагает, что приложение будет возвращать несколько блоков заголовков)
- ⏩Единственный нормальный способ полностью зафикситься - переходить на более новые версии HTTP на upstream-прокси и внутренней инфраструктуре. При этом указано, что в целом ок если HTTP/1.1 используется только на уровне взаимодействия пользователя с прокси (критичность таких атак сильно меньше).
Для того, чтобы потыкать новую технику руками сдалали новую лабу. В целом, лаба мне понравилась, но пришлось несколько раз перечитать статью, чтобы ее решить. Официальный райтап будет показан в прямом эфире 15 августа. Но я могу поделиться своим решением уже сейчас. Помещу его в комментариях. Так что, если вы планировали изучить ее самостоятельно, пока туда не заглядывайте.
#Research #Smuggling


Content-Length. Мы хотим сделать его невидимым для Frontend-Сервера, но заметным для Backend. Очень важна цифра, но об этом чуть далее 4. Конструируем второй запрос с нагрузкой, объединяем его в группу с первым и отправляем друг за другом в separate connections: Теперь пояснение. CL=41 в первом запросе должен покрывать длину запроса до X: Y во втором запросе. Эта часть второго запроса будет "съедаться" предыдущим запросом и будет проходить то, что идет дальше (`GET /404`). Значение CL=260 во втором запросе должно покрывать всю длину последнего запроса (`GET /post?postId=3`), включая CL=5. Если ваши запросы сложатся удачно, следующий запрос пользователя вернет ему ответ с XSS-нагрузкой вместо ожидаемой страницы, какую бы он ни открыл. Можно добавить в группу любой легальный запрос и наблюдать. Важно: при эксплуатации возникает Race Condition внутри upstream proxy, поэтому эту всю конструкцию, что я прописал выше нужно отправлять несколько раз, пока оно все не соберется как надо и не пройдет эксплуатация. Также важный теоретический момент - при нормальной эксплуатации нам нужно понимать полную длину для второго запроса, включая заголовки, которые выставляет Frontend-Сервер (а он их выставляет всегда). В данном случае я накостылил и специально ограничил последний запрос (часть запроса улетает куда-то дальше в очередь и немного ломает все вокруг. Для решения это не сильно имеет значение, но в реальных случаях так делать нельзя, иначе будет хаос в запросах и ответах пока очередь не почистится). В том же приложении есть гаджет, через который вы можете достать все заголовки Frontend-сервера: Когда оставляете комментарий, ставьте значение email в конец запроса так, чтобы Smuggled-нагрузка добавлялась в него. Если все сделть правильно вы получите рефлект всех заголовков Frontend-сервера в ответе на этот запрос и сможете посчитать необходимую длину запроса. Hunt Or Be Hunted