๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿด‍โ˜ ๏ธ CTF ๐Ÿด‍โ˜ ๏ธ/โœˆ๏ธ ์›น โœˆ๏ธ

[Dream Hack - Web] csrf-1

๋ฐ˜์‘ํ˜•

CSRF๋ž€?

CSRF๋ž€, Cross Site Request Forgery์˜ ์•ฝ์ž๋กœ, ์‚ฌ์ดํŠธ๊ฐ„ ์š”์ฒญ ์œ„์กฐ๋ฅผ ๋œปํ•ฉ๋‹ˆ๋‹ค. CSRF๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ž์‹ ์˜ ์˜์ž์™€๋Š” ๋ฌด๊ด€ํ•˜๊ฒŒ ๊ณต๊ฒฉ์ž๊ฐ€ ์˜๋„ํ•œ ํ–‰์œ„(๋ฐ์ดํ„ฐ ์ˆ˜์ •, ์‚ญ์ œ, ๋“ฑ๋ก ๋“ฑ)์„ ํŠน์ • ์›น์‚ฌ์ดํŠธ์— ์š”์ฒญํ•˜๋Š” ๊ณต๊ฒฉ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ํ”ผํ•ด์ž์˜ ์ „์ž ๋ฉ”์ผ ์ฃผ์†Œ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์•”ํ˜ธ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์ž๊ธˆ์ด์ฒด๋ฅผ ํ•˜๋Š” ๋“ฑ์˜ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜, ํŠน์„ฑ์— ๋”ฐ๋ผ ๊ณต๊ฒฉ์ž๋Š” ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์— ๋Œ€ํ•œ ์™„์ „ํ•œ ์ œ์–ด๊ถŒ์„ ์–ป์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์„œ๋ฒ„๋Š” ๋กœ๊ทธ์ธ ์‹œ ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ ์„ธ์…˜(session)์— ์ €์žฅํ•˜๊ณ  ์ด์— ๋งค์นญ๋˜๋Š” ์„ธ์…˜ ์•„์ด๋””(session ID)์„ ๋งŒ๋“ ๋‹ค.
  2. ์„œ๋ฒ„๋Š” ์ €์žฅ๋œ ์„ธ์…˜ ์ •๋ณด๋ฅผ ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ธ์…˜ ์•„์ด๋””๋ฅผ Set-Cookie ํ—ค๋”์— ๋‹ด์•„์„œ ์ „๋‹ฌํ•œ๋‹ค.
  3. ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)๋Š” ์ „๋‹ฌ๋œ ์„ธ์…˜ ์•„์ด๋””๋ฅผ ์ฟ ํ‚ค์— ์ €์žฅํ•œ๋‹ค.
  4. ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)๋Š” ํ•ด๋‹น ๋„๋ฉ”์ธ์„ ๊ฐ€์ง„ ์„œ๋ฒ„๋กœ ์š”์ฒญ ์‹œ ์ฟ ํ‚ค์— ์ €์žฅ๋œ ์„ธ์…˜ ์•„์ด๋””๋ฅผ ์ž๋™์œผ๋กœ ์ „๋‹ฌํ•œ๋‹ค.
  5. ์„œ๋ฒ„๋Š” ์ฟ ํ‚ค์— ๋‹ด๊ธด ์„ธ์…˜ ์•„์ด๋””๋ฅผ ํ†ตํ•ด ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•œ๋‹ค.

์ถœ์ฒ˜ : https://junhyunny.github.io/information/security/spring-boot/spring-security/cross-site-reqeust-forgery/

 

๋ฌธ์ œ ํ•ด์„

 

/vuln ํŽ˜์ด์ง€

xss_filter์— ํฌํ•จ๋œ ๋‹จ์–ด๋Š” “*”๋กœ ๋Œ€์ฒด๋˜๊ณ  ์žˆ์–ด์„œ, <script>alert(1)</script> ๋˜๋Š” <svg/onload=alert(1)/> ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ๋ชปํ•œ๋‹ค.

@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

 

/admin/notice_flag

@app.route("/admin/notice_flag")
def admin_notice_flag():
    global memo_text
    if request.remote_addr != "127.0.0.1":
        return "Access Denied"
    if request.args.get("userid", "") != "admin":
        return "Access Denied 2"
    memo_text += f"[Notice] flag is {FLAG}\\n"
    return "Ok"

/admin/notice_flag ๋ฅผ 1. ๋กœ์ปฌ ํ˜ธ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ 2.userid=admin ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์š”์ฒญ์„ ํ•˜๋ฉด memo์— flag ๊ฐ’์ด ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋ฌธ์ œ ํ’€์ด

 

/flag ํŽ˜์ด์ง€์—์„œ param ๊ฐ’๋งŒ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ /admin/notice_flag ํŽ˜์ด์ง€ ์ ‘์†์œผ๋กœ ์œ ๋„ํ•ด์•ผ ํ•œ๋‹ค. ๋‹จ์ˆœ ์›น ํŽ˜์ด์ง€์— ์ ‘์†ํ•˜๋Š” ์ฝ”๋“œ๋งŒ ์‹คํ–‰์‹œํ‚ค๋ ค๋ฉด img ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. img ํƒœ๊ทธ๋Š” src ๋งํฌ์˜ ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋ ค๋Š” ์‹œ๋„๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— /admin/notice_flag?userid=admin ํŽ˜์ด์ง€๋กœ ์ ‘์†ํ•˜๊ฒŒ ๋œ๋‹ค.

<img src="/admin/notice_flag?userid=admin">

 

์ฐธ๊ณ 

 

Cross Site Request Forgery (CSRF) | OWASP Foundation

๋ฐ˜์‘ํ˜•