# 1. save_the_world ![image](https://hackmd.io/_uploads/HkFJSO28p.png) ```python from flask import Flask, send_file, request, render_template import os from urllib.parse import unquote import secrets import config from middleware import PathTraversalMiddleware app = Flask(__name__,template_folder="templates") app.wsgi_app = PathTraversalMiddleware(app.wsgi_app) @app.route('/') def hello_world(): return render_template('index.html') @app.route('/upload', methods=['POST','GET']) def handleUpload(): if request.method == 'POST': if 'file' not in request.files: return 'No file part' file = request.files['file'] if file.filename == '': return 'No selected file' extension = file.filename.split('.')[-1] if extension not in config.ALLOW_EXTENSION: return 'Invalid file extension' new_name = '%s.%s' % (secrets.token_hex(16), extension) if file: file.save('%s/%s' % (config.UPLOAD_FOLDER,new_name)) return render_template('upload.html', success_message='File uploaded successfully: %s' % new_name) else: return render_template('upload.html') @app.route('/viewfile/<filepath>') def handleFile(filepath): target_file = os.path.abspath('%s/%s' % (config.UPLOAD_FOLDER,unquote(filepath))) if os.path.isfile(target_file): return send_file(target_file) else: return '', 404 if __name__ == '__main__': app.run(host="0.0.0.0",port=5000) ``` ## Phân tích App này có 2 chức năng chính đó là `upload file` và `viewfile` Do ở challenge này đã bị `filter whitelist` rồi nên ta sẽ không thể upload file to rce được ```python #config.py UPLOAD_FOLDER = "/app/uploads" ALLOW_EXTENSION = ["jpg","png","gif"] ``` Next sang hàm tiếp theo ```python @app.route('/viewfile/<filepath>') def handleFile(filepath): target_file = os.path.abspath('%s/%s' % (config.UPLOAD_FOLDER,unquote(filepath))) if os.path.isfile(target_file): return send_file(target_file) else: return '', 404 ``` Ở đây có xuất hiện hàm `send_file` dẫn đến `Path Traversal` ![image](https://hackmd.io/_uploads/S1l1IdhLp.png) ## Exploit Ở đây có 1 class chống path travelsal được import ở `app.py` ```python class PathTraversalMiddleware: def __init__(self, app): self.app = app def __call__(self, environ, start_response): # Extract the path from the request path = environ.get('PATH_INFO', '') # Check if the path contains ".." if ".." in path: # Block the request if it contains ".." return self.block_request(start_response) # If the path is safe, proceed with the request return self.app(environ, start_response) def block_request(self, start_response): # Return a 403 Forbidden response start_response('403 Forbidden', [('Content-Type', 'text/plain')]) return [b'Forbidden: Path traversal not allowed.'] ``` Bypass được bằng url decode Nhưng bị dính hàm `unquote(filepath)` ```bash $ cat test.py from urllib.parse import unquote filepath = '%2e%2e%2f%2e%2e%2f%2e%2e%2f' print(unquote(filepath)) $ python3 test.py ../../../ ``` Hàm này sẽ url decode ra nên khi ta truyền thằng trên url như kia sẽ bị dính `..` trong path -> ez bypass bằng `double encode` ![image](https://hackmd.io/_uploads/SkjxKu38a.png) Flag được lưu ở biến env ![image](https://hackmd.io/_uploads/Hy8zF_38T.png) ![image](https://hackmd.io/_uploads/B1VNjdhL6.png) ![image](https://hackmd.io/_uploads/HJ_Usd3I6.png) # 2. WarmupPHP Bài này có 3 flag với mỗi vuln 1 flag ![image](https://hackmd.io/_uploads/rkgUhd28p.png) ## Flag1 ![image](https://hackmd.io/_uploads/HJMa3_nLa.png) Có thể thấy đây là [smarty ssti](https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#smarty-php) Tưởng dễ ăn nhưng lại chỉ sử dụng được hàm `{$smarty.version}` ![image](https://hackmd.io/_uploads/BJR4T_38T.png) Bế tắc nên mình chuyển sang dirsearch và có được source ``` $ curl http://103.162.14.116:10007/robots.txt User-agent: * Disallow: /?source ``` ```php <?php include('flagl.php'); include('flag2.php'); include_once('/app/vendor/autoload.php'); define(FLAG1', $flag1); if (!isset($_GET['name'])) { header (Location: /?name=guest'); } if (isset($_GET['source'])) { show_source(__FILE__); } $smarty = new Smarty(); $policy = new Smarty_Security ($smarty); if(str_starts_with ($_GET['name'], 'kcsc')) { $policy->php_functions = $allow_php_func; } $smarty->enableSecurity ($policy); $smarty->display('string: KCSC hello fen, '.$_GET['name']); ``` ez flag1 ![image](https://hackmd.io/_uploads/BkiPyFhI6.png) ## Flag2 ### Phân tích ```php <?php function debug($input) { if (str_contains($input, '/') || str_contains($input, '.')) { die('invalid filepath'); } if (strlen(readlink($input)) >= 128) { echo file_get_contents($input); } } $allow_php_func = [ 'debug', 'symlink' ]; ?> ``` Nhìn lại file source có: ```php if(str_starts_with ($_GET['name'], 'kcsc')) { $policy->php_functions = $allow_php_func; } ``` khi chuỗi bắt đầu bằng `kcsc` sẽ kích hoạt `$policy` cho phép sử dụng 2 hàm `debug` và `symlink` ``` $allow_php_func = [ 'debug', 'symlink' ]; ``` Đầu tiền với hàm `debug` ```php function debug($input) { if (str_contains($input, '/') || str_contains($input, '.')) { die('invalid filepath'); } if (strlen(readlink($input)) >= 128) { echo file_get_contents($input); } } ``` Đầu tiên hàm này sẽ kiểm tra xem symlink có chứa `.` hay `/` không thì sẽ `die()` Thứ 2, sẽ kiểm tra độ dài của symlink khi được link lúc đầu nếu lớn hơn 128 sẽ in ra file được link ấy ### Exploit Luồng exploit sẽ như sau: - Tạo 1 symlink có độ dài > 128 đến file `flag2.php` bằng hàm `symlink()` ![image](https://hackmd.io/_uploads/B1R28KnL6.png) - Đọc file bằng hàm `debug()` ![image](https://hackmd.io/_uploads/BkYR8YhIp.png) #