mirror of https://github.com/yandex/gixy
3.6 KiB
3.6 KiB
[http_splitting] HTTP Splitting
HTTP Splitting - уязвимость, возникающая из-за неправильной обработки входных данных. Зачастую может быть для атак на приложение стоящее за Nginx (HTTP Request Splitting) или на клиентов приложения (HTTP Response Splitting).
Уязвимость возникает в случае, когда атакующий может внедрить символ перевода строки \n
или \r
в запрос или ответ формируемый Nginx.
Как самостоятельно обнаружить?
При анализе конфигурации всега стоит обращать внимание на:
- какие переменные используются в директивах, отвечающих за формирование запросов (могут ли они содержать CRLF), например:
rewrite
,return
,add_header
,proxy_set_header
илиproxy_pass
; - используются ли переменные
$uri
и$document_uri
и если да, то в каких директивах, т.к. они гарантированно содержат урлдекодированное значение; - переменные, выделенные из групп с исключающим диапазоном:
(?P<myvar>[^.]+)
.
Пример плохой конфигурации с переменной, полученной из группы с исключающим диапазоном:
server {
listen 80 default;
location ~ /v1/((?<action>[^.]*)\.json)?$ {
add_header X-Action $action;
return 200 "OK";
}
}
Пример эксплуатации данной конфигурации:
GET /v1/see%20below%0d%0ax-crlf-header:injected.json HTTP/1.0
Host: localhost
HTTP/1.1 200 OK
Server: nginx/1.11.10
Date: Mon, 13 Mar 2017 21:21:29 GMT
Content-Type: application/octet-stream
Content-Length: 2
Connection: close
X-Action: see below
x-crlf-header:injected
OK
Из примера видно, что злоумышленник смог добавить заголовок ответа x-crlf-header: injected
. Это случилось благодаря стечению нескольких обстоятельств:
add_header
не кодирует/валидирует переданные ему значения, считая что автор знает о последствиях;- значение пути нормализуется перед обработкой локейшена;
- переменная
$action
была выделена из группы регулярного выражения с исключающим диапазоном:[^.]*
; - таким образом, значение переменной
$action
равноsee below\r\nx-crlf-header:injected
и при её использовании в формировании ответа добавился заголовок.
Что делать?
- старайтесь использовать более безопасные переменные, например,
$request_uri
вместо$uri
; - запретите перевод строки в исключающем диапазоне, например,
/some/(?<action>[^/\s]+)
вместо/some/(?<action>[^/]+
; - возможно, хорошей идеей будет добавить валидацию
$uri
(только если вы знаете, что делаете).