보이지 않는 C2의 해부: Steam WordPress 악성코드가 어떻게 전통적인 탐지를 속이는가 (그리고 행동 기반으로 이를 차단하는 방법)
요약
Steam 프로필 댓글의 보이지 않는 유니코드를 C2 채널로 활용하는 새로운 WordPress 악성코드 캠페인을 분석합니다. 기존의 도메인 평판 및 시그니처 기반 탐지를 우회하는 스테가노그래피 기법과 이를 차단하기 위한 행동 기반 탐지의 필요성을 다룹니다.
핵심 포인트
- Steam의 공개 프로필 댓글 내 유니코드를 이용한 스테가노그래피 C2 방식
- 신뢰할 수 있는 도메인을 활용하여 도메인 평판 기반 탐지 무력화
- PHP 백도어와 암호화된 JavaScript 주입을 통한 지속성 유지
- 시그니처 기반 방어의 한계와 행동 기반 탐지 아키텍처의 중요성
Imunno System 작성
2025년 7월, GoDaddy Security의 연구원들은 불과 몇 달 만에 약 1,980개의 WordPress 사이트를 감염시킨 캠페인을 추적하기 시작했습니다. 이 캠페인이 보안 언론에 보도된 결정적인 이유는 그 규모 때문이 아니었습니다. 바로 명령 및 제어 (C2, Command and Control) 채널의 독창성 때문이었습니다. 바로 Steam 프로필 댓글 내의 보이지 않는 유니코드 (Unicode) 문자 안에 숨겨진 명령어를 사용한 것입니다.
이 기사는 공격 체인을 분해하고, 이 방식이 왜 기존의 방어 체계를 벗어나는지 설명하며, 시그니처 (Signature) 기반이 아닌 행동 기반 (Behavior-based) 탐지 아키텍처가 어떻게 판도를 바꾸는지 보여줍니다. 또한, 저희의 접근 방식을 포함하여 각 방식이 가진 한계점에 대해서도 솔직하게 말씀드리겠습니다.
계층화된 공격 체인
이 캠페인의 탁월함은 '눈에 띄지 않는 것'에 있습니다. 각 단계는 일상적인 작업처럼 보이도록 설계되었습니다.
1. 초기 침투 (Initial Compromise). 단일 익스플로잇 (Exploit)은 존재하지 않습니다. 분석 결과, 도난당한 관리자 자격 증명, 탈취된 FTP/SFTP 액세스, 취약한 플러그인 또는 테마, 혹은 공급망 공격 (Supply chain compromise)과 같은 잘 알려진 평범한 벡터들이 지목되었습니다. 이질적인 것이 없기에, 오히려 대규모로 작동할 수 있는 것입니다.
2. PHP 백도어 (PHP Backdoor). 초기 발판을 마련한 후, 악성코드는 사이트의 PHP 파일을 수정할 수 있는 서버 측 (Server-side) 백도어를 설치합니다. 이는 쿠키 인증을 통해 유지되며 POST를 통해 명령을 수락합니다. 이것이 지속성 (Persistence) 유지 지점입니다. 겉핥기식의 정리만으로는 다시 침투할 수 있는 경로를 열어두게 됩니다.
3. 스테가노그래피 C2 (Steganographic C2). 여기에 혁신이 있습니다. 도메인 평판 (Domain reputation)에 의해 발각될 수 있는 공격자의 제어 서버로 직접 전화하는 대신, 감염된 WordPress는 Steam의 공개 프로필 페이지를 조회합니다. 댓글 텍스트는 무해한 ASCII 아트처럼 보입니다. 하지만 가시적인 문자들 사이에는 비트 (Bits)로 매핑된 6개의 보이지 않는 유니코드 문자(Zero-width non-joiner, Zero-width joiner, 그리고 'invisible' 연산자의 변형들)가 숨겨져 있습니다. 이를 디코딩하면 URL이 재구성됩니다.
4. 주입 (Injection). URL은 lodash.core.min.js와 같은 합법적인 라이브러리로 위장하여 외부에 호스팅된 JavaScript를 가리킵니다. 이 스크립트는 사이트의 모든 공개 페이지에 주입되어 모든 방문자에게 영향을 미칩니다. 페이로드 (Payload)는 여전히 PBKDF2 키 유도 및 HMAC을 사용하는 AES-256-CTR을 사용하여, 운영자에게 암호학적으로 보호된 콘텐츠 제어 권한을 부여합니다.
전통적인 탐지가 실패하는 이유
이 캠페인을 저항력 있게 만드는 요소를 살펴보십시오:
도메인 평판 (Domain Reputation)은 도움이 되지 않습니다. 침해된 서버는 인터넷에서 가장 신뢰할 수 있는 도메인 중 하나인 steamcommunity.com과 통신합니다. 어떤 차단 목록 (Blocklist)도 이를 표시하지 않을 것입니다. 공격자는 아무도 차단할 엄두를 내지 못하는 플랫폼으로 자신의 C2 인프라를 외주화했습니다.
파일 시그니처 (File Signatures)는 취약합니다. 실제 페이로드는 여러 계층에 걸쳐 암호화 및 난독화되어 있으며, 무작위화된 식별자와 미끼 코드 (Decoy code)를 포함하고 있습니다. 오늘의 문자열과 일치하는 규칙은 내일의 변종과는 일치하지 않습니다.
채널은 이상 트래픽 (Anomalous traffic)이 아닌 스테가노그래피 (Stego) 방식입니다. 보이지 않는 유니코드 (Unicode) 문자는 스팸 필터나 중재 시스템을 트리거하지 않습니다. 사용자들이 유니코드를 사용하여 ASCII 아트를 게시하는 일은 매우 흔하기 때문입니다. 페이로드는 정상적인 콘텐츠처럼 보이는 것 안에 숨겨져 이동합니다.
요약하자면: _"이 지표 (Indicator)가 알려진 악성인가?"_라고 묻는 모든 방어 체계는 패배합니다. 이 지표는 선량해 보이도록 설계되었기 때문입니다.
올바른 질문: 시그니처가 아닌 인과관계
패러다임의 전환은 _"이 아티팩트 (Artifact)가 악성인가?"_라고 묻는 것을 멈추고, _"맥락을 고려했을 때 이 동작이 일어나야 하는가?"_라고 묻기 시작하는 것입니다.
이 캠페인에 적용했을 때, 페이로드가 어떻게 암호화되었는지와 관계없이 세 가지 동작이 두드러집니다:
1. 예상치 못한 출처에 의한 PHP 파일 수정. 백도어는 PHP 파일을 다시 작성합니다. 각 PHP/JS 파일의 SHA-256 해시를 유지하고 수정 시점에 차이(divergence)를 감지하는 에이전트는 변경된 내용이 무엇인지에는 상관하지 않습니다. 대신 권한 없는 변경이 발생했다는 사실 자체를 감지합니다. 운영 환경(production)에서 WordPress의 코어 파일은 스스로 변경되지 않습니다.
2. web→shell 프로세스 계보 (Lineage). 만약 백도어가 시스템 명령을 실행한다면, 이를 실행하는 프로세스는 php-fpm 또는 웹 서버의 자식 프로세스입니다. 부모→자식 트리(parent→child tree)를 추적하는 인과관계 엔진(causality engine)은 nginx → bash 또는 php-fpm → sh 패턴을 그 본질 그대로 식별합니다. 즉, 운영 서버에서 이러한 패턴은 원격 코드 실행 (RCE)이며, 거의 항상 비정상적인 동작입니다.
3. 베이스라인(baseline)을 벗어난 도메인으로의 아웃바운드 연결. 여기가 가장 흥미로운 지점입니다. 전형적인 WordPress 서버는 페이지 로딩 중에 steamcommunity.com으로 외부 HTTP 요청을 보내지 않습니다. Steam이 신뢰할 수 있는 사이트인지 여부는 중요하지 않습니다. 중요한 것은 이 서버가 이전에 이런 동작을 한 적이 없다는 사실입니다. 네트워크 행동의 베이스라인 편차(baseline deviation)를 통한 탐지는 도메인 평판(reputation) 기반 탐지가 놓치는 부분을 정확히 잡아냅니다.
이것이 Imunno System의 논지입니다. **인과관계(causality)와 행동(behavior)**을 통해 Linux 웹 서버를 방어하며, cgroups를 통해 위협을 억제하는 것입니다 (의심스러운 프로세스를 즉시 종료하여 정상 서비스까지 중단될 위험을 감수하는 대신, 해당 프로세스의 CPU 사용량을 1%로 제한하는 방식).
행동 기반 탐지조차 한계가 있는 곳 — 솔직하게 말하자면
행동 기반 탐지를 만능 해결책(silver bullet)으로 판매하는 것은 정직하지 못한 일일 것입니다. 실제 한계점에 대해 살펴보겠습니다:
스테가노그래피(Steganography) 방식의 C2 자체는 네트워크 흐름상에서 포착하기 어렵습니다. 보이지 않는 유니코드(Unicode) 문자를 탐지하려면 특정 코드 포인트(U+200C, U+200D, U+2061–U+2064의 비정상적 밀도)를 찾는 파일 콘텐츠 검사가 필요합니다. 이는 가능하지만, 행동(Behavior) 탐지가 아닌 콘텐츠 탐지 영역이며, 명시적으로 구축되어야 하는 기능입니다. 인과관계(Causality) 모델에서 저절로 얻어지는 것이 아닙니다. 저희 로드맵에서 이는 계획된 단계이며, 이미 제공 중인 기능은 아닙니다.
네트워크 베이스라인(Baseline) 탐지는 콜드 스타트(Cold start) 문제로 어려움을 겪습니다. 새로 모니터링을 시작한 서버는 베이스라인이 없습니다. 학습 기간 동안은 부분적인 시야 결손(Blindness) 구간이 발생하며, 인내심 있는 공격자는 이 기간 동안 트래픽에 섞여 들어올 수 있습니다.
정상적인 경로를 통한 파일 수정은 회색 지대(Gray zone)입니다. 만약 백도어(Backdoor)가 파일을 정상적으로 편집하는 프로세스(예: 자동 업데이트 플러그인)를 통해 파일을 작성한다면, 추가적인 컨텍스트(Context) 없이는 신호(Signal)와 소음(Noise)을 분리하기 어렵습니다.
단일 계층으로는 해결할 수 없습니다. 효과적인 방법은 파일 무결성(File integrity) + 프로세스 인과관계(Process causality) + 네트워크 베이스라인(Network baseline) + 콘텐츠 검사(Content inspection)를 중첩하여, 하나의 계층이 실패하더라도 다른 계층이 이를 보완하도록 하는 것입니다.
시사점
이번 캠페인은 방어의 경계가 단순히 거대한 차단 목록(Blocklist)을 보유하는 데 있지 않다는 점을 상기시켜 줍니다. 방어의 핵심은 특정 서버에 무엇이 _정상(Normal)_인지 이해하고 그 편차를 탐지하는 데 있습니다. 현대의 공격자는 개별 지표(Indicator) 하나하나가 무해해 보이도록 치밀하게 움직이기 때문입니다.
현재 WordPress 서버를 운영 중인 분들을 위한 권고 사항입니다: 최근에 수정된 PHP/JS 파일을 검토하고, 예상치 못한 도메인(심지어 "신뢰할 수 있는" 도메인이라 할지라도)으로의 아웃바운드 연결을 확인하며, 웹 서버를 부모 프로세스로 하는 모든 셸(Shell) 프로세스를 의심하십시오. 만약 감염되었다면, 백도어는 지속적으로 남아있으므로 반드시 알려진 깨끗한 백업본으로 복구해야 합니다.
O Imunno System은 Linux 웹 서버를 위한 에지 EDR (Endpoint Detection and Response)으로, 웹셸 (Webshell), 파일 변조 및 프로세스 오용에 대한 행동 기반 탐지에 특화되어 있습니다. 문서 및 아키텍처: github.com/rodrigoffreir3/imunno-pitch
기술 참조: 해당 캠페인에 관한 GoDaddy Security의 원본 보고서; BleepingComputer 및 Security Affairs의 보도 (2026년 6월).
4. 주입 (Injection). URL은 lodash.core.min.js와 같은 이름의 합법적인 라이브러리로 위장하여 외부에서 호스팅되는 JavaScript를 가리킵니다. 이 스크립트는 사이트의 모든 공개 페이지에 주입되어 모든 방문자에게 영향을 미칩니다. 페이로드 (Payload)는 여전히 PBKDF2 키 유도 및 HMAC을 사용하는 AES-256-CTR을 사용하여, 운영자에게 암호학적으로 보호된 콘텐츠 제어 권한을 부여합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기