# ``` from flask import Flask, render_template, request, redirect, url_for, session import redis import os app = Flask(__name__) app.secret_key = os.urandom(24).hex() db = redis.StrictRedis(host='localhost', port=6379, decode_responses=True) FLAG = open("/flag.txt", "rb").read().strip() @app.route('/') def home(): return render_template('index.html') @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] # Check if the username is 'admin' if username.lower() == 'cookiehanhoan': return 'You cannot create a user with the username "cookiehanhoan"!' if db.hgetall(username): return 'Username already exists!' db.hset(username, mapping={'password': password}) return redirect(url_for('login')) return render_template('register.html') @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] user = db.hgetall(username) # Check if the username is 'cookiehanhoan' if username == 'cookiehanhoan' and user and user['password'] == password: session['username'] = username return FLAG if user and user['password'] == password: session['username'] = username return redirect(url_for('home')) return 'Invalid credentials!' return render_template('login.html') @app.route('/logout') def logout(): session.pop('username', None) return redirect(url_for('home')) if __name__ == '__main__': app.run("0.0.0.0", 1330) ``` Sơ qua về source code thì chúng ta có hai plugin là register cũng như login, có vẻ đề get được flag thì phải login vào account 'cookiehanhoan'. Theo đó sau khi truyền vào username password, db sẽ được xử lý thông qua ```HSET``` Ex: Nếu ta truyền ```username=guest&password=guest``` thì Redis sẽ xử lý ``` HSET guest password 'guest'```. Cụ thể bạn có thể tìm hiều về HSET https://redis.io/commands/hset/ Ban đầu ý tưởng của mình là sử dụng nosql injection nhằm ghi đè account 'cookiehanhoan' thông qua việc truyền username nhưng có vẻ nó không hiệu quả vì không có cách nào để thoát ra khỏi HSET hoặc mình chưa nghĩ ra :< ![](https://hackmd.io/_uploads/SJYqH5Yb6.png) Sau khi đọc hint của author mình thử tìm các lỗ hổng Redis SSRF và được một người anh em chỉ điểm thì mình tìm được blog https://www.hackthebox.com/blog/uni-ctf-2022-spell-orsterra-writeup Hey, 'Redis execution via socket injection', chúng ta có thể thực thi SSRF thông qua endpoint /assets/ vì chúng ta có bypass qua việc sử dụng proxy_pass. Bạn có thể tìm hiểu thêm thông qua https://labs.detectify.com/2021/02/18/middleware-middleware-everywhere-and-lots-of-misconfigurations-to-fix/ ``` EVAL /assets/unix:%2frun%2fredis%2fredis.sock:%22return%20redis.call('set','redis_injection',1)%22%200%20/ HTTP/1.1 Host: 127.0.0.1:1337 User-Agent: Mozilla/5.0 Accept: */* ``` ![](https://hackmd.io/_uploads/rkKCu9Fbp.png) Vậy là chúng ta có thể thực hiện RCE thông qua SSRF. Ý tưởng bây giờ là chúng ta có thể ghi lên Redis database account cookiehanhoan và sau đó login vào để lấy flag ![](https://hackmd.io/_uploads/HkMLicYWp.png) We done !!!