OX Security는 동일한 악성 HTML 파일을 담은 npm 패키지 24개를 발견했다. 해당 파일은 Cloudflare의 보안 인증 화면을 흉내 낸 가짜 CAPTCHA 페이지였다.
2
17
이번 사례의 핵심은 npm 패키지를 설치한 개발자를 직접 감염시키는 전형적인 공급망 공격이 아니라는 점이다. 공격자는 npm 레지스트리와 unpkg처럼 패키지 파일을 자동으로 동기화하는 미러를 신뢰할 수 있는 호스팅 공간처럼 이용해 피싱 페이지를 배포했다.
2
17
npm은 악성 코드 실행 수단이 아니라 ‘호스팅 인프라’였다
문제의 패키지에는 설치 과정에서 실행되는 복잡한 프로그램 대신 단일 HTML 페이지가 들어 있었다. 사용자가 npm 또는 미러에 올라온 해당 파일의 URL을 열면 익숙한 서비스 도메인 아래 Cloudflare 스타일의 인증 화면이 나타났다.
2
17
따라서 패키지를 내려받았다는 사실만으로 곧바로 감염이 발생했다고 보기는 어렵다. 공격자의 실제 목표는 외부에서 유포한 링크를 클릭하게 만들어, npm 레지스트리와 미러에 호스팅된 페이지로 피해자를 끌어들이는 것이었다.
17
이 방식은 npm 생태계의 높은 인지도와 미러의 안정적인 접근성을 악용한다. 악성 페이지가 낯선 공격자 도메인이 아니라 익숙한 패키지·CDN 경로에서 제공되면, 사용자가 경계심을 늦출 가능성이 커진다.
바뀌는 리디렉션 경로와 KeyVal ‘데드 드롭’
가짜 CAPTCHA는 최종 공격이 아니라 리디렉션 체인의 첫 단계였다. OX Security에 따르면 초기 버전은 Microsoft를 사칭한 도메인으로 연결됐고, 이후에는 microcloud[.]homes, login[.]microsofte[.]live 등 목적지와 인프라가 바뀌었다.
2
18
공격자는 목적지 정보를 전달하거나 갱신하기 위해 공개 키-값 저장소인 KeyVal도 사용했다. 이 구조에서는 모든 패키지에 들어 있는 동일한 HTML 파일을 다시 배포하지 않고도 피해자가 이동할 최종 주소를 바꿀 수 있다.
21
이 때문에 단순히 npm에서 패키지를 삭제하는 것만으로는 충분하지 않을 수 있다. 이미 미러로 동기화된 파일이나 외부에 유포된 URL이 계속 작동할 수 있기 때문이다. 캠페인 관련 보도에서도 레지스트리에서 삭제된 뒤 일부 패키지 파일과 미러 호스팅 페이지가 남아 있었던 것으로 전해졌다.
17
18
마지막 단계는 ClickFix형 심리 조작
가짜 CAPTCHA는 실제 보안 검사가 아니었다. 페이지는 피해자에게 명령어를 복사해 운영체제의 실행 창이나 셸에 붙여넣고 실행하도록 유도했다. 이것이 ClickFix의 전형적인 방식이다. 소프트웨어 취약점을 직접 뚫는 대신, 사용자가 자신의 권한으로 악성 명령을 실행하게 만든다.
20
25
이 수법은 브라우저와 보안 서비스의 익숙한 디자인을 차용한다는 점에서 효과적이다. 유사 캠페인에서는 인증 버튼이 악성 PowerShell 명령을 클립보드에 몰래 넣은 뒤, 키보드 단축키나 운영체제 안내를 따라 하도록 유도하는 방식이 관찰됐다.
26
28
기억해야 할 원칙은 간단하다. 정상적인 CAPTCHA는 사용자가 셸, PowerShell, Terminal 또는 실행 창을 열고 웹페이지에서 복사한 텍스트를 실행하도록 요구하지 않는다.
패키지 다운로드 수는 얼마나 됐나
OX Security에 따르면 각 패키지는 삭제되기 전까지 대체로 주당 50~300회의 다운로드를 기록했다.
2 다만 이 수치는 npm 레지스트리 활동만 보여줄 뿐, 외부 링크나 미러 URL을 통해 피싱 페이지를 본 사람의 수까지 포함하지는 않는다.
공격자는 패키지를 설치하는 개발자만 노린 것이 아니라, 피싱 메시지나 변조된 웹사이트 등 다른 경로로 URL을 퍼뜨릴 수 있었다. 따라서 npm의 다운로드 수만으로 캠페인의 실제 도달 범위를 판단하기는 어렵다.
2
17
더 커지는 ClickFix 흐름 속에서의 의미
이번 npm 캠페인은 광범위하게 확산 중인 ClickFix 모델의 인프라 변형으로 볼 수 있다. 공격자들은 CAPTCHA, 브라우저 오류, 가짜 업데이트, 유틸리티 화면처럼 익숙한 미끼를 내세운 뒤 피해자 스스로 명령을 실행하게 만든다. Proofpoint는 이 기법이 악성코드 전달 수단으로 확대되고 있다고 설명했으며, Microsoft도 브라우저 작동을 방해한 뒤 사용자의 실행을 유도하는 관련 변종을 기록했다.
22
25
27
PavinLoader, EtherHiding, Amatera Stealer, Mac 개발자를 겨냥한 가짜 OpenAI Codex 페이지, ACR Stealer 등의 사례는 사용자 지원 실행이라는 더 넓은 흐름을 설명하는 참고 사례가 될 수 있다. 그러나 제공된 근거만으로는 이 24개 npm 패키지 캠페인이 해당 작전들과 같은 공격자에 의해 운영됐다고 확인할 수 없다.
또한 175개 npm 패키지를 악용했다는 과거 Beamglea 작전과 이번 캠페인의 구체적인 운영상 연관성도 제공된 자료만으로는 입증되지 않는다.
개발자와 보안팀이 주의할 점
이번 사례는 npm 공급망 위협의 범위를 넓혀 보여준다. 패키지 설치 중 악성 코드를 실행하지 않더라도, 신뢰받는 레지스트리와 미러에 정적 HTML 파일을 올리는 것만으로 피싱 작전의 진입점이 될 수 있다.
개발자와 보안팀은 다음과 같은 대응을 고려해야 한다.
- 예상하지 못한 npm 및 CDN URL을 열기 전에 도메인과 경로를 확인한다.
- CAPTCHA나 브라우저 오류 화면이 명령어 복사와 실행을 요구하면 사회공학 공격으로 간주한다.
- 브라우저와 엔드포인트에서 비정상적인 명령 실행을 모니터링한다.
- 웹페이지에서 복사한 명령어를 셸, PowerShell, Terminal 또는 실행 창에 붙여넣지 않는다.
가장 중요한 경고 신호는 CAPTCHA 자체가 아니다. 정상적인 보안 절차를 우회하라며 텍스트를 복사하고 실행하도록 요구하는 순간, 사용자는 공격자가 설계한 마지막 실행 단계에 들어선 것이다.