https://dreamhack.io/wargame/challenges/269
[1] ๋ฌธ์ ๋ถ์
# ๋ฌธ์ ์น ํ์ด์ง ๋ถ์
(1) /Home
์ด๊ธฐ ํ๋ฉด(Home ํ๋ฉด)์ด๋ค.
(2) /vuln(csrf) page
script๋ *๋ก ๋์ฒด๋์๊ณ
/script๋ ๊ณต๋ฐฑ ์ฒ๋ฆฌ๋ ๊ฒ ๊ฐ๋ค.
์์ค ์ฝ๋๋ ์ด๊ฒ ์ ๋ถ๋ค.
(3) /flag ํ์ด์ง
/vuln ๊ฒฝ๋ก์ param ๋งค๊ฐ๋ณ์๋ฅผ ์ ๋ฌํ ๋ ๋ฃ์ ๊ฐ์ ์ ์ถํ๋ฉด ๋๋ ํ์์ด๋ค.
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="/static/css/non-responsive.css">
<title>Index CSRF-2</title>
<style type="text/css">
.important { color: #336699; }
</style>
</head>
<body>
<!-- Fixed navbar -->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">CSRF-2</a>
</div>
<div id="navbar">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<form method="POST">
http://127.0.0.1:8000/vuln?param=<input type="text" name="param"/><br/>
<input type="submit"/><br/>
</form>
</div> <!-- /container -->
<!-- Bootstrap core JavaScript -->
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</body>
</html>
/flag ํ์ด์ง์ ์์ค ์ฝ๋์ด๋ค.
๋ฐฉ๊ธ ๋ถ์ํ ๊ทธ๋๋ก์ด๊ณ , ์ด์ธ์ ๋ฑํ ํํธ๊ฐ ๋๋ ๋ด์ฉ์ ์์๋ค.
(4) /login ํ์ด์ง
๋ก๊ทธ์ธ์ ํ ์ ์๋ ํ๋ฉด์ด ๋ํ๋๋ค.
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="/static/css/non-responsive.css">
<title>Login CSRF-2</title>
</head>
<body>
<!-- Fixed navbar -->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">CSRF-2</a>
</div>
<div id="navbar">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<h1>Login</h1><br/>
<form method="POST">
<div class="form-group">
<label for="InputName">username</label>
<input type="text" class="form-control" id="InputName" placeholder="username" name="username" required>
</div>
<div class="form-group">
<label for="InputPassword">password</label>
<input type="password" class="form-control" id="InputPassword" placeholder="password" name="password" required>
</div>
<button type="submit" class="btn btn-default">Login</button>
</form>
</div> <!-- /container -->
<!-- Bootstrap core JavaScript -->
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</body>
</html>
/login ํ์ด์ง์ ์์ค ์ฝ๋์ด๋ค.
username๊ณผ password๋ฅผ ๋ฐ์๋ค์ด๊ณ ์๋ค.
ํน๋ณํ ์ ์ ์์ด๋ณด์ธ๋ค.
# ๋ค์ด๋ก๋ํ ๋ฌธ์ ํ์ผ ๋ถ์
โ๏ธ app.py
#!/usr/bin/python3
from flask import Flask, request, render_template, make_response, redirect, url_for
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import urllib
import os
app = Flask(__name__)
app.secret_key = os.urandom(32)
try:
FLAG = open("./flag.txt", "r").read()
except:
FLAG = "[**FLAG**]"
users = {
'guest': 'guest',
'admin': FLAG
}
session_storage = {}
def read_url(url, cookie={"name": "name", "value": "value"}):
cookie.update({"domain": "127.0.0.1"})
try:
service = Service(executable_path="/chromedriver")
options = webdriver.ChromeOptions()
for _ in [
"headless",
"window-size=1920x1080",
"disable-gpu",
"no-sandbox",
"disable-dev-shm-usage",
]:
options.add_argument(_)
driver = webdriver.Chrome(service=service, options=options)
driver.implicitly_wait(3)
driver.set_page_load_timeout(3)
driver.get("http://127.0.0.1:8000/")
driver.add_cookie(cookie)
driver.get(url)
except Exception as e:
driver.quit()
print(str(e))
# return str(e)
return False
driver.quit()
return True
def check_csrf(param, cookie={"name": "name", "value": "value"}):
url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
return read_url(url, cookie)
@app.route("/")
def index():
session_id = request.cookies.get('sessionid', None)
try:
username = session_storage[session_id]
except KeyError:
return render_template('index.html', text='please login')
return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not an admin"}')
@app.route("/vuln")
def vuln():
param = request.args.get("param", "").lower()
xss_filter = ["frame", "script", "on"]
for _ in xss_filter:
param = param.replace(_, "*")
return param
@app.route("/flag", methods=["GET", "POST"])
def flag():
if request.method == "GET":
return render_template("flag.html")
elif request.method == "POST":
param = request.form.get("param", "")
session_id = os.urandom(16).hex()
session_storage[session_id] = 'admin'
if not check_csrf(param, {"name":"sessionid", "value": session_id}):
return '<script>alert("wrong??");history.go(-1);</script>'
return '<script>alert("good");history.go(-1);</script>'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
try:
pw = users[username]
except:
return '<script>alert("not found user");history.go(-1);</script>'
if pw == password:
resp = make_response(redirect(url_for('index')) )
session_id = os.urandom(8).hex()
session_storage[session_id] = username
resp.set_cookie('sessionid', session_id)
return resp
return '<script>alert("wrong password");history.go(-1);</script>'
@app.route("/change_password")
def change_password():
pw = request.args.get("pw", "")
session_id = request.cookies.get('sessionid', None)
try:
username = session_storage[session_id]
except KeyError:
return render_template('index.html', text='please login')
users[username] = pw
return 'Done'
app.run(host="0.0.0.0", port=8000)
users = { ... }
users = {
'guest': 'guest',
'admin': FLAG
}
์ด ๋ถ๋ถ์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ด์ ๋์
๋๋ฆฌ๋ฅผ ์ ์ํ๊ณ ์๋ค. (ํ์ด์ฌ์์ ๋์
๋๋ฆฌ๋ฅผ ์ ์ํ๋ ๋ฌธ๋ฒ์ ์ค๋๋ง์ ๋ ์ฌ๋ ธ๋ค.)
์... id์ 'guest'๋ฅผ ๋ฃ๊ณ password์ 'guest' ๋ฃ์์ ๋ ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด
๋์ ๋๋ฆฌ์ key : value๊ฐ username : password ๋ฅผ ์ ์ํ๋ ๊ฒ์ด๋ค.
ํ ๋ฒ ์๋๋ฅผ ํด๋ณด์๋ค.
์ค!
/login ํ์ด์ง์์ username์ 'gues', password์ 'guest'๋ฅผ ๋ฃ์๋๋
guest๋ก ๋ก๊ทธ์ธ๋์์์ ํ์ธํ ์ ์๋ ๋ฌธ๊ตฌ๊ฐ ์ถ๋ ฅ๋์๋ค.
.
.
.
๊ทธ ๋ง์ ์ฆ,
admin ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธํ๋ ค๋ฉด, username์ 'admin'์ ๋ฃ์ผ๋ฉด ๋๋ ๊ฒ์ด๊ณ ,
password๋ FLAG๋ผ๊ณ ์ ํ์๋ ๊ฒ์ ๋ณด๋ password ๊ฐ์ ๊ตฌํ๋ ๊ฒ์ด ๊ด๊ฑด์ธ ๊ฒ ๊ฐ๋ค.
๊ทธ๋ฌ๋๊น ์ด์ ๋ถํฐ password ๊ฐ์ ๊ตฌํ๊ธฐ ์ํด app.py์ ๋๋จธ์ง ๋ถ๋ถ์ ๋ถ์ํด๋ณด๊ฒ ๋ค.
@app.route("/")
@app.route("/")
def index():
session_id = request.cookies.get('sessionid', None)
try:
username = session_storage[session_id]
except KeyError:
return render_template('index.html', text='please login')
return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not an admin"}')
์ด ๋ถ๋ถ์ ์ด๊ธฐ ํ๋ฉด์ ์ ์ํ๋๋ฐ,
์ง๊ธ ์ํฉ(guest๋ก ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๊ณ , username์ด admin์ธ ๊ฒ์ ์๋ ์ํฉ)์์ ์ฃผ๋ชฉํ ๋งํ ๋ถ๋ถ์
return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not an admin"}') ๋ถ๋ถ์ด๋ค.
๋ก๊ทธ์ธ์ ํ์ ๋, admin์ด ์๋๋ฉด, "Hello {username}, you are not an admin" ์ ์ถ๋ ฅํ๊ณ ,
admin์ผ๋ก ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ์ ๋, "Hello {username}, flag is " + FLAG" ๋ฅผ ์ถ๋ ฅํ๋ค.
์ด๋ ๊ฒ ์ ์๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ด๊ฐ ๋ฐฉ๊ธ ์ ์ 'guest'๋ก ๋ก๊ทธ์ธํ์ ๋,
"Hello guest, you are not an admin" ๋ฌธ๊ตฌ๊ฐ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
@app.route("/vuln")
@app.route("/vuln")
def vuln():
param = request.args.get("param", "").lower()
xss_filter = ["frame", "script", "on"]
for _ in xss_filter:
param = param.replace(_, "*")
return param
๋ฐ์์จ param ๊ฐ์ ๋ชจ๋ ์๋ฌธ์๋ก ๋ฐ๊พผ ๋ค์,
"frame", "script", "on" ์ผ ๊ฒฝ์ฐ ํํฐ๋งํ๊ธฐ ๋๋ฌธ์ ํด๋น ๋ฌธ์์ด์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ ์๋ ค์ค๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ img ํ๊ทธ๋ฅผ ํ์ฉํ ๊ฒ์ด๋ค.
@app.route("/change_password")
@app.route("/change_password")
def change_password():
pw = request.args.get("pw", "")
session_id = request.cookies.get('sessionid', None)
try:
username = session_storage[session_id]
except KeyError:
return render_template('index.html', text='please login')
users[username] = pw
return 'Done'
๋ฌธ์ ํ์ด์ง์์๋ ๋ณผ ์ ์์๋ "/change_password" ๊ฒฝ๋ก๋ฅผ ์ ์ํ๋ ๋ถ๋ถ์ด๋ค.
์ด ๋ถ๋ถ์ ๋ณด๋ฉด /change_password ํ์ด์ง์์ GET ๋ฐฉ์์ผ๋ก pw ๋งค๊ฐ๋ณ์์ ๊ฐ์ ๊ฐ์ ธ์ pw์ ๊ทธ ๊ฐ์ ํ ๋นํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
(์ฃผ์์ฐฝ์ /change_password?pw=1234 ๋ผ๊ณ ์ ๋ ฅํ๊ณ ์ ์กํ๋ฉด pw์ 1234๋ฅผ ํ ๋นํ๋ ๊ฒ์ด๋ค.)
๊ทธ ๋ค์ users์ pw ๊ฐ์ ์ ๋ฐ์ดํธํ์ฌ ์ ์ฅํ๋ค.
@app.route('/login', methods=['GET', 'POST'])
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
elif request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
try:
pw = users[username]
except:
return '<script>alert("not found user");history.go(-1);</script>'
if pw == password:
resp = make_response(redirect(url_for('index')) )
session_id = os.urandom(8).hex()
session_storage[session_id] = username
resp.set_cookie('sessionid', session_id)
return resp
return '<script>alert("wrong password");history.go(-1);</script>'
๊ทธ๋ฆฌ๊ณ /login ํ์ด์ง๋ฅผ ๋์์ํค๋ ์ฝ๋๋ฅผ ๋ณด๋ฉด
/login ํ์ด์ง์์ ์ ๋ ฅ๋ฐ์์จ password ๊ฐ์ด pw ๊ฐ์ด๋ ๊ฐ์ ๋,
์ฌ์ฉ์๋ฅผ 'index'๋ก ๋ฆฌ๋ค์ด๋ ์ ํ๋ ์๋ต ๊ฐ์ฒด๋ฅผ ๋ฐ์์ํจ๋ค.
.
.
.
์๊น index ํจ์๋ฅผ ์ ์ํ ๋, admin์ผ๋ก ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด, "Hello {username}, flag is " + FLAG" ๋ฅผ ์ถ๋ ฅํ๋ค๊ณ ํ๋ค.
๊ทธ๋ ๋ค๋ฉด!
1. /vuln(csrf) page์ img ํ๊ทธ๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ทจ์ฝ์ ์ด ์์.
2. pw ๊ฐ์ /change_password ํ์ด์ง์์ GET ๋ฐฉ์์ผ๋ก ๊ฐ์ ๋ฐ์๋ค์ฌ admin์ password๊ฐ ๋จ.
.
.
.
์์ ์ฌ์ค์ ์์๋์ผ๋,
/flag ํ์ด์ง์ <img src="/change_password?pw=1" /> ๋ฅผ ์ ๋ ฅํด์ password ๊ฐ์ 1๋ก ๋ฐ๊ฟ์ฃผ๊ณ ๋ก๊ทธ์ธ์ ์๋ํด๋ณด์.
์ด๊ธฐ ํ๋ฉด ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ์ ๋๋ฉด์ ์์๋๋ก flag ๊ฐ์ด ๋ํ๋ฌ๋ค.
์ฑ๊ณต!!
[3] ๋๋ ์
ํ์ด์ฌ ๋ฌธ๋ฒ๋ ์ ์์์ผ ์น์ด ์๋ํ๋ ๋ฐฉ์์ ์ ์ดํดํ ์ ์๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค!
(์ฒ์์ user๋ฅผ ๋์ ๋๋ฆฌ๋ก ์ ์ํ๋ ๋ถ๋ถ์ ํด์ํ์ง ๋ชปํด์ ๋ฌธ์ ํ์ด์ ์ด๋ ค์์ ๊ฒช์์๋ค.)
'SWLUG > ์น ํดํน' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Dreamhack/๋๋ฆผํต] Command Injection Advanced (1) | 2023.11.19 |
---|---|
[Dreamhack/๋๋ฆผํต] baby-linux (0) | 2023.11.16 |
[Dreamhack/๋๋ฆผํต] csrf-1 (0) | 2023.11.10 |
[Dreamhack/๋๋ฆผํต] XSS Filtering Bypass (0) | 2023.11.10 |
[webhacking.kr] Challenge old-23 (0) | 2023.11.09 |