우리는 정말 큰 위협을 피했음
(xeiaso.net)- 최근 NPM 패키지 생태계에서 발생한 공급망 공격이 실제로는 더 큰 피해를 야기할 수 있었음
- 공격자는 인기 있는 라이브러리를 악용해 암호화폐 지갑 주소를 변경하는 방향으로만 악성코드를 사용함
- 이 공격은 정교한 피싱 이메일을 통해 개발자의 2단계 인증 정보를 탈취하는 방식으로 이루어졌음
- 만약 더 치명적인 형태(예: API 키 탈취 등)로 사용됐다면 막대한 피해 가능성이 존재함
- 모든 의존성이 잠재적으로 위험하다는 인식과 전체 의존성 트리 이해의 중요성을 강조함
공격 개요 및 우려
- 최근 가장 큰 패키지 생태계 중 하나인 NPM에서 인기 패키지가 공격에 노출되었음
- 예시 기능: 터미널 색상 처리, 색상 이름-RGB 매핑, 함수 디버깅 데코레이터, 배열 유사 값 판별 유틸리티 등
- 이런 일반적인 의존성들은 광범위하게 사용되며, 코드가 유입되면 곧바로 프로덕션 환경에 배포될 가능성이 큼
- 만약 악성 프록시, API 키 탈취, 기타 심각한 공격이 포함됐더라면 결과는 훨씬 심각해졌을 위험이 있었음
- 실제로는 해당 악성코드가 온라인 지갑(예: MetaMask)에서 암호화폐 결제 주소만 변조하는 방식이었음
피싱 공격의 정교함
- 공격의 출발점은 매우 잘 만들어진 피싱 이메일이었음
- NPM 사용자명을 활용해 개인화된 인상을 주는 방식
- "보안을 위해 비밀번호와 2차 인증 자격 증명을 변경"하라는 메시지로 신뢰 유도
- NPM의 특이한 운영 방식과 맞물려 평범한 사용자라면 쉽게 속을 수 있는 내용 구성
- 특정 기한을 명시해 긴급성을 부여, 바쁜 상황에서 방심한 상태로 피싱 링크 클릭 유도
- 실제 NPM 공식 도메인과 유사한
.help
도메인을 활용
-
두드러지는 부분은 공식 도메인 대신 "npmjs.help"을 쓰는 정도였음
- 요즘은 다양한 신규 gTLD(Generic Top Level Domain)가 블로그나 문서 등에 광범위하게 활용되고 있어, 이 역시 자연스럽게 보일 수 있음
공격의 잠재적 피해
- 피싱 이메일은 사용자의 2단계 인증 정보를 탈취한 후, 공격 코드를 삽입해 신규 패키지 배포가 가능했음
-
is-arrayish, color-string, color-name 등 매우 널리 사용되는 대표 라이브러리가 대상이었음
- 만약 악성코드가 단순 암호화폐 가로채기뿐 아니라, API 키 탈취 등으로 확대되었다면 치명적 결과 초래 가능
- 예를 들어 OpenAI, AWS API 키 대량 노출 등, 장기적이고 대규모 피해가 나올 수 있었음
- 실제로 대부분의 감염된 라이브러리는 커맨드라인 툴에서 주로 쓰이고 있어, 암호화폐 탈취 목적은 그만큼 제한적이었음
Web3 생태계 겨냥 및 공격자의 전략
- 이번 공격은 Web3 사용자(브라우저로 결제 등)를 주 타깃으로 한 것으로 보임
- Web3와 관련 없는 범용 라이브러리를 공격 대상으로 삼아, Web3 생태계의 빠른 인지와 차단 가능성을 피해감
- 예: Metamask와 연동하는 라이브러리를 주의 깊게 점검하더라도, text color 관련 유틸리티에서 공격이 일어나리라고는 예측 어려움
개발 생태계의 교훈
- 이번 사례로 모든 의존성 패키지가 실제로 악성일 수 있다는 점이 강조됨
- 의존성 트리를 항상 전적으로 통제하거나 모니터링하는 데는 현실적 한계가 존재
- 빠른 프로덕션 배포 흐름과 시간적 압박 속에서 보안적 검토가 뒷전으로 밀릴 수밖에 없음을 시사
- 앞으로는 프로젝트의 전체 의존성 구성 파악과 신중한 관리의 중요성 증대
마무리 및 안내
- 본 내용은 특정인을 비난하거나 책임을 묻지 않으며, 누구나 피싱 공격에 노출될 수 있음을 인지하는 것이 중요함
- 이 포스트의 게시 이후로 상황 변화가 있을 수 있으니, 내용 오류나 의문이 있을 시 직접 확인 요청 필요
Tags:
Hacker News 의견
-
nx npm 공급망 공격은 많은 회사들이 피하지 못한 총알임, VS Code nx 플러그인을 설치하기만 해도 자동으로 npm에서 최신 nx 버전을 확인하면서, Github 세션(예: GH CLI로 회사 계정 로그인)이나 .env 파일에 중요한 인증 정보가 있다면 모두 유출당했음, 이는 의존성 고정이나 보안 업데이트를 잘 관리해도 피할 수 없는 일이었음, 이 생태계에서 근본적으로 더 깊은 변화가 필요함, 자세한 내용은 공식 보안 공지 참고 바람
- 나는 NPM 관련 모든 것을 피하고 있음, typescript compiler만 예외로 쓰고 있으나 Go로 리라이트되면 그것도 제거할 계획임, Go의 경우 최소 버전 명시 기능이 있고, 다운로드한 것을 컴파일 과정에서도 절대 실행하지 않는 점이 뛰어남, NPM의 경우 소스가 github와 다른 경우가 많고 신뢰할 수 없다고 생각함
- 에디터 확장 프로그램은 위험도가 높은 개발 환경에서 자동 업데이트 및 설치가 되어 매우 매력적인 공격 타깃임, 왜 아직 브라우저 확장 프로그램처럼 악의 세력의 대규모 매입이 없는지 의아함, VsCode 팀이 악성 소프트웨어 탐지에 노력을 많이 기울인다고 들었으나, Sublime 등 모든 에디터가 이런 검증 과정을 가지고 있는지 궁금함
- 나는 모든 패키지와 데이터베이스를 로컬로 유지하고, 개발 머신에서는 에어플레인 모드로 작업함, 오직 git push할 때만 인터넷 연결을 켬
-
정말 위기 일촉즉발의 상황에서 겨우 피했음, 이런 패키지에 접근한 공격자가 단순하게 암호화폐 탈취 툴 하나만 올렸다는 사실이 믿기지 않음, 절호의 기회라면 추가로 일주일 정도 투자해서 좀 더 정교한 익스플로잇을 심는 게 이득일 것 같은데, API 키, SSH 공개키 추가, 서버 IP 유출, 개발자 기기의 브라우저 프로필이나 세션 토큰, 심지어 내 데스크탑의 아마존 카드 정보 등 탈취할 수 있는 게 너무 많음, 이런 것들은 자신이 직접 사용하지 않아도 다크웹 포럼에서 손쉽게 판매 가능함, 혹시 실력 있는 사이버범죄자들은 이미 안정적이고 고소득 테크 회사에서 일하고 있어서 이런 단순한 공격만 남겨진 걸까 궁금함
- 이 공격 방식은 금방 발각될 것이 확실했기 때문에 은밀한 방식이 아니라 계정 전체 장악, 즉 빠르게 '치고 빠지기' 전략을 택한 것으로 보임, 몇 시간 안에 자동화로 가장 많은 돈을 빠르게 뽑아낼 수 있는 방법이 필요했고, 암호화폐가 명백한 정답임, 절반의 세계가 코드를 뜯어본다고 해도 백도어가 들키지 않을 수준이 아니라면, 더 오래 준비할 이유가 없었음
- 도난당한 암호화폐는 거래 취소, 환불, 복구가 불가능하기 때문에 현실적으로 무조건 손에 넣을 수 있는 자원임, 반면 개발자의 API나 SSH키는 거의 가치가 없고, 운이 좋다 해도 결국 그것도 현금화하려면 결국 암호화폐로 환전하게 됨
- 빠르게 진입해서 수십만 달러 훔치고, 나가고, 몇 달 뒤 똑같이 반복, 이런 식으로 경찰만 잘 피하면 평생 걱정 없이 살 수 있음, AWS 키 같은 걸 훔쳐도 그리 큰 이득이 안 됨, 암호화폐 외에 비밀번호나 패스워드 매니저 데이터베이스를 노리는 범죄자도 있는데, 결론적으로 결국 암호화폐 관련 사이트를 노릴 때가 많음, 지금도 꼼꼼히 기업을 침투할 타이밍을 노리는 범죄자도 있을 것이고, 이들은 드러나지 않고 성공할 때까지 숨어 있을 것임
- 이건 일생에 한 번 있는 기회 같은 게 아님, 앞으로 범죄자들이 워낙 "개발자" 몇 명만 노려도 수백만 달러에 손쉽게 접근할 수 있다는 걸 깨닫고, 더 대담한 수법이 계속 나올 것임, 오픈소스 코드 유지보수자라면 온라인에서 자신의 물리적 신원을 얼마나 잘 숨기고 있는지 반드시 고민해봐야 할 수준임
-
나는 미뤄두는 습관이 생존기술임, 남들이 베타 테스트할 때까지 기다리기 때문에, 예전에 회사에서 12년 동안 Microsoft Office 2000만 썼고, 업그레이드로 인한 문제나 재교육 없이 10년 동안 평화로운 시간을 보냈음, 그리고 이메일에 있는 링크는 절대 클릭하지 않는 습관을 가지고 있음
- 내 Honda 차량과 Kubernetes도 그런 식임, 2006년식 자동차를 오래 유지해서 여러 세대의 크고 작은 자동차-폰 연동 문제를 건너뛰었었고, 최근에야 2023년식 차에서 아이폰 연결이 매우 매끄러워짐, Kubernetes도 마찬가지로 상사의 권유를 오랜 시간 미뤄온 덕분에 EKS, GKE 등이 충분히 성숙한 지금에서야 마이그레이션으로 겪는 고생이 크게 줄었음, 만약 6~7년 전에 바로 따랐다면 수많은 삽질을 했을 것 같음
- npm 생태계에서는 54초마다 업데이트하지 않으면 이미 크게 뒤처지는 상황임
- 신규 악성 패키지에는 효과적이긴 하지만 이미 감염된 소프트웨어가 웜까지 맞아버리는 경우엔 안되기도 함
- 내일 답장하겠음
- "신규 버전은 기본적으로 2주간 사용 미루기"는 공급망 공격에 매우 효과적인 방어책임
-
작은 스타트업은 힘들겠지만 npm 같은 대형 플레이어라면 "npm.io", "npm.sh", "npm.help" 등 모든 TLD 버전의 npm 도메인을 선점해야 한다고 생각함, 공격자가 "npm.help" 도메인을 차지한 게 이 공격을 더욱 효과적으로 만들었음
- AWS처럼 고객들에게 피싱 경계하라고 해놓고, 공식 청구서 메일 주소를
no-reply-aws@amazon.com
에서no-reply@tax-and-invoicing.us-east-1.amazonaws.com
으로 바꿔버리는 경우가 많음, 처음 본 주소라 거의 피싱 메일처럼 보여도 공식이라고 하니 헷갈리는 상황임, 심지어 사전 안내 메일도 피싱스럽게 보여 진짜로 청구서를 받아보기 전까지는 의심스러워 첨부 PDF 파일을 열지 않음, 기업들이 고객들에게 피싱을 조심하라면서 불필요하게 혼동을 주는 행동을 하고 있음 - 1,500개가 넘는 TLD가 있고, 일부는 제한적이거나 국가 코드형이라 하더라도, 이런 TLD를 전부 등록하는 것의 실제 연간 비용이 얼마나 될지 궁금해짐, SaaS로 대행해주는 곳도 있을 듯함
- TLD 목록을 보면 도메인이 너무 많고, 대규모 업체라도 유사 TLD 전부 선점해서 피싱 방지하려는 시도는 필요하더라도, 완벽히 차단 가능하지 않음이라고 생각함
- 모든 공식 도메인 여부를 먼저 확인하는 게 첫 번째임, 최근 등록된 할인 도메인(registrar)이라든가 사용 기한이 얼마 안 남은 도메인은 무조건 의심함, 특히 마감일 등을 같이 강조하면서 '시간이 없다'는 식으로 사람을 몰아붙이는 링크일 경우 더 깊이 조사함, 공식 소통은 유명 대표 도메인(혹은 그 하위도메인)만 사용하는 게 옳다고 봄
- npm 및 유사 도메인 네이밍은 변종이 끝이 없어서, 전부 선점 방법으로는 실질적으로 막는 게 불가능함, 도메인 이름만 봐도 피싱으로 의심되겠지만 npmjs.help 같은 도메인도 실수로 클릭되는 게 현실임
- AWS처럼 고객들에게 피싱 경계하라고 해놓고, 공식 청구서 메일 주소를
-
만약 누군가가 매우 치밀함(Jia Tan 방식)과 우리의 보안 허술함(에디터 플러그인, 쉘 유저랜드 등)의 문제를 합친다면? 개발자 관련 도구들은 슈퍼유저 권한으로 실행되지만 가장 검증이 적은 것임, 나도 elisp, neovim, vscode, 그리고 간단한 유저랜드 도구까지 일일이 다 검증하진 못함, best case가 nixpkgs에서 받아오는 정도임, 언젠가 더 좋은 VSCode 플러그인 하나 출현시키고 1~2년 기다리면 끝임, GG임
- 언젠가는 누군가가 xkcd 1200번 이슈를 꼭 해결해주길 바람
-
MetaMask 등 지갑이 타깃이 되었지만, MetaMask는 LavaMoat라는 격리 모듈 덕분에 이런 공격에 대해 상당히 잘 보호받고 있다고 들음, 실제 보호 수준에 대한 상세 분석 글이 있으면 정말 보고 싶음, 개인적으로는 MetaMask와 무관하지만 이런 보안 대응책(실제 공격에 비해 적용 속도가 느림)의 효과가 궁금함, 참고로 관련 기사를 추가함
-
"이런 피싱 공격엔 결국 언젠가 당할 수밖에 없다는 게 진실이다"라는 말에, 나 스스로는 아마 아닐 거라 생각함, 내가 직접 요청한 적 없는 이메일의 링크에는 절대 인증 정보를 입력하지 않는 습관이 있음(예: 비번 초기화 등), 2025년이라면 누구나 반드시 익혀야 할 보안 스킬이라고 생각함
- "'이런' 피싱 공격"이라고 표현하니 뭔가 정교한 공격처럼 들리지만, 사실 개발자가 또 다시 진짜 평범하게 피싱 메일에 당한 사례일 뿐임, 아주 기본적인 실수이자, 때로는 관리 부서 직원도 안 속을 수준임, 물론 누구나 실수할 순 있지만 명백한 부주의와 아마추어 실수가 이런 걸 반복시킨다고 생각함
-
"모든 악성코드는 암호화폐 지갑 주소만 바꿔치기 했음"이라는 기사 설명과 달리, MetaMask가 영향을 받지 않은 이유는,
- 공격 시점에 패키지가 바로 업데이트되지 않았고
- MetaMask가 설치 및 실행 단계 모두에서 LavaMoat을 사용해 보호를 받았기 때문임, 반면 이 악성 페이로드는 MetaMask와 상호작용하는 타 지갑 사용 웹페이지를 노리려 했음, 참고로 나는 LavaMoat 개발에 참여했음, 자세한 정보는 LavaMoat 깃허브 참고 바람
-
메이저 오픈 패키지 저장소들은 훨씬 강력한 보안 솔루션이 필요함, 아니면 신뢰성 높은 심사된 핵심 패키지 집합만이라도 생겨야 함, Python, Rust 생태계 등도 마찬가지로 신뢰만으로 돌아가고 있음
- npm의 근본적인 문제는 네임스페이스 강제 부재임, Java의 Maven에서 초보자들이 "왜 npm만큼 쉽지 않냐"고 불평하지만, Maven의 이름공간 체계 등 품질관리 집착은 세월이 갈수록 더 높게 평가하게 됨, POM xml이 불편하긴 해도, 보수적인 변화 관리가 신뢰를 주는 부분임, 관련 아티클: 왜 퍼블릭 오픈소스 저장소에 네임스페이스가 중요한가
- 이 사례처럼 패키지 유지자의 계정 자체가 탈취될 경우엔 네임스페이스 등 구조적 방안도 무의미함, 유일한 해결책은 신규 릴리스가 즉시 적용되지 않도록 지연시키는 것뿐임
- 리눅스 배포판 역시 신뢰 기반이지만, 패키지를 올릴 권한을 얻으려면 신뢰를 '입증'해야 하고, 신뢰 확인 시스템 전체가 존재함, NPM은 마치 누구나 올릴 수 있는 자유로운 시스템임
-
"이건 막을 방법이 없다"는 주장이 가장 자주 침해가 일어나는 생태계에서만 나옴
- 정확히 그 점이 문제임, 너무나 게으른 결론임