๊ธ€ ์ž‘์„ฑ์ž: heogi

RCE via Server-Side Template Injection | by Gaurav Mishra | Medium

 

SSTI ์ทจ์•ฝ์ ์„ ์ด์šฉํ•˜์—ฌ Remote Code Execution์„ํ•˜๊ณ  Akamai WAF์„ ์šฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜๋Š” ๊ธ€์ด๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ๋ฅผ Response์— ๋ฌธ์ž์—ด๋กœ ์‘๋‹ตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋ฐœ๊ฒฌํ•˜์˜€๋‹ค.
ํ•ด๋‹น ๊ธฐ๋Šฅ์— XSS ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ช‡๊ฐœ ์ž…๋ ฅํ•˜์˜€์ง€๋งŒ Javascript๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์•˜๋‹ค.

ํ•˜์ง€๋งŒ context_type Parameter์— ${191 * 7} SSTI ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ž…๋ ฅํ•˜์ž ์•„๋ž˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ์„ฑ๊ณต์ ์œผ๋กœ ๊ณ„์‚ฐ์ด๋˜์–ด ์ถœ๋ ฅ๋˜์—ˆ๋‹ค.


์ดํ›„ ์–ด๋–ค Template Engine์ด ์‚ฌ์šฉ๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด Error Message๋ฅผ ์ถœ๋ ฅ์‹œ์ผœ๋ณผ๋ ค๊ณ  ํ–ˆ์ง€๋งŒ ์‹คํŒจํ–ˆ๋‹ค.

ํ•ด๋‹น ์ทจ์•ฝ์ ์„ ์ด์šฉํ•œ ๊ณต๊ฒฉ์˜ ํšจ๊ณผ๋ฅผ ๋†’์ด๊ธฐ ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์€ Remote Command Execution ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ž‘์„ฑํ•˜์˜€๋‹ค.

${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("ls")}

ํ•ด๋‹น ํŽ˜์ด๋กœ๋“œ๋ฅผ ํ†ตํ•ด ๊ณต๊ฒฉ์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์‘๋‹ต์— ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ˆ˜๊ฐ€์—†์—ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์œ„์˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ Unix Process ์ •๋ณด๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.
์ด๋Š” ์ž…๋ ฅํ•œ ๋ช…๋ น์ด ์„ฑ๊ณต์ ์œผ๋กœ ์‹คํ–‰๋˜์—ˆ์Œ์„ ๋œปํ•œ๋‹ค.

์ดํ›„ Reverse Shell์„ ์ด์šฉํ•˜์—ฌ ์ ‘์†์‹œ๋„ํ•˜๊ธฐ ์œ„ํ•ด wget์„ ํ†ตํ•ด ์„œ๋ฒ„์— Reverse Shell Script๋ฅผ ๋ฐ€์–ด๋„ฃ๋Š”๋‹ค.
python์„ ์ด์šฉํ•ด Reverse Shell Script๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๊ณ 

wget์„ ํ†ตํ•ด ํ˜ธ์ŠคํŒ…ํ•œ ์ฃผ์†Œ๋ฅผ ๋„ฃ์—ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ netcat์„ ์‹คํ–‰ํ•˜๊ณ  ํŽ˜์ด๋กœ๋“œ๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์—์„œ Reverse Shell์„ ์‹คํ–‰์‹œํ‚จ๋‹ค.

๊ธฐ๋ณธ์ ์ธ ์‚ฌ์น™์—ฐ์‚ฐ์€ ์‹คํ–‰๋˜์—ˆ์ง€๋งŒ ๋งˆ์ง€๋ง‰ Payload๋Š” 403 ์—๋Ÿฌ๋ฅผ ๋ฟœ์œผ๋ฉฐ ์‹คํŒจํ–ˆ๋‹ค.
Payload๋ฅผ ํ•˜๋‚˜์”ฉ ๋ถ„์„ํ•˜๋ฉฐ WAF๊ฐ€ ์–ด๋–ค ํ‚ค์›Œ๋“œ๋ฅผ ์ปจํŠธ๋กคํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๋‹ˆ ์•„๋ž˜์˜ ํ‚ค์›Œ๋“œ๊ฐ€ ํ•„ํ„ฐ๋ง๋˜๊ณ ์žˆ์—ˆ๋‹ค.

  • "java.lang.Runtime"
  • ( )

java doc์„ ๋ณด๊ณ  ์šฐํšŒ์ ์œผ๋กœ "java.lang.Runtime" ๋ฌธ์ž์—ด์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ฐพ์•„๋ณด์•˜๋‹ค.

์ด ๊ฒฝ์šฐ concat์„ ํ†ตํ•ด ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

"java.lang.Runtime === "java.lang".concat(".Runtime")

๋‹ค์Œ์œผ๋กœ ( )์„ ์šฐํšŒํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ถ„์„์„ ํ–ˆ๋‹ค.
์ฝ˜์†”์ฐฝ์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ˆ

 

console.log("hello")์™€ (console.log).("hello")๊ฐ€ (console.log("hello"))์™€ ๊ฐ™์€ ์˜๋ฏธ๋ผ๋Š”๊ฑธ ํ™•์ธํ–ˆ๋‹ค.
์œ„์˜ ๋‘ ๊ฐ€์ง€๋ฅผ ์šฐํšŒํ•˜์—ฌ ์•„๋ž˜์˜ ์ตœ์ข… Payload๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

${("".getClass()).forName("java.lang".concat("Runtime")).getMethods()[6].invoke(("".getClass()).forName("java.lang".concat("Runtime"))).exec("wget")}

์‹ค์„œ๋ฒ„์ด๊ธฐ ๋•Œ๋ฌธ์— ์›น์‰˜์ด๋‚˜/์•…์„ฑ์ฝ”๋“œ๋Š” ์—…๋กœ๋“œํ•˜์ง€ ์•Š์•˜๋‹ค.

์‹ค์ œ๋กœ Payload๊ฐ€ ์ž˜๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ์œ„ํ•ด Burp Collaborator ์„œ๋ฒ„์— Outbound request๋ฅผ ์š”์ฒญํ•˜์˜€๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜์ฒ˜๋Ÿผ ์„œ๋ฒ„์˜ ์‹ค์ œ IP ์ฃผ์†Œ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.