1억 회 다운로드 메인테이너를 노린 가짜 면접: 러스트 생태계를 위협하는 국가 배후 표적 공격

1억 회 다운로드 메인테이너를 노린 가짜 면접: 러스트 생태계를 위협하는 국가 배후 표적 공격

사이버 보안오픈소스 생태계Rust

데이터 소스:Rust 공식 블로그와 개발자 인터뷰

싱가포르 벤처 캐피털을 사칭한 한 통의 이메일, “출장 중”이라는 핑계로 카메라 켜기를 거부하는 독일 억양의 면접관, 그리고 평범해 보이는 타입스크립트(TypeScript) 테스트 과제. 이는 최상위 오픈소스 프로젝트 메인테이너들을 겨냥해 설계된 실제 공격 사슬이었습니다.

2026년 9월 17일, 러스트(Rust) 공식 보안 팀은 긴급 보안 경고를 발령했습니다. 공격자들이 가짜 일자리 제안과 화상 회의를 침투 경로로 삼아, rust-lang 핵심 팀원들과 누적 다운로드 수가 높은 주요 크레이트(crate, 러스트 패키지 단위) 관리자들을 집중적으로 노리고 있습니다. 공격자들은 몇 달씩 걸려 제로데이 취약점을 찾는 대신, 사회공학적 기법으로 개발자의 기기 제어권을 직접 탈취하여 공식 패키지 저장소에 악성 버전을 정식 배포하려 했습니다.

화상 회의를 통해 패키지 배포 권한을 탈취하다

개인을 겨냥한 사회공학적 공격은 기업의 방화벽을 강제로 뚫는 것보다 훨씬 효율적입니다. 공격자는 먼저 거부하기 힘든 매력적인 미끼를 던집니다. 높은 연봉의 정규직 채용이나 고액의 자문 계약이 대표적입니다. 이 모든 과정을 진짜처럼 꾸미기 위해 그들은 그럴듯한 신생 기업 웹사이트를 구축하고, 화려한 이력이 담긴 링크드인(LinkedIn) 프로필까지 정교하게 위조했습니다.

개발자가 관심을 보이고 화상 면접에 참여하면 통화 도중 본격적인 공격이 시작됩니다. 면접관은 온갖 핑계를 대며 대상자가 로컬 환경에 무언가를 설치하도록 유도합니다. 화상 회의 프로그램에 특정 오디오 코덱이 없다면서 플러그인으로 위장한 설치 파일을 보내거나, 화면 공유를 통해 연결 오류를 보여주며 터미널에서 악성 명령어를 실행하도록 유도합니다. 러스트 공식 팀은 이미 지난 6월에도 여러 유명 러스트 개발자들이 이와 유사한 수법의 표적이 되었다고 밝혔습니다. 지난달에는 엄청난 다운로드 수를 자랑하는 기초 라이브러리인 arrayref가 유사한 방식으로 일시적으로 감염되기도 했습니다. 이런 하위 의존성에 악성코드가 심어지면, 이를 가져다 쓰는 하류 기업들은 자동 빌드 과정에서 조용히 감염되고 맙니다.

러스트 공식 팀은 이번 표적 공격의 정교함으로 미루어 볼 때 북한(DPRK) 배후의 해킹 조직과 직접 연관되어 있다고 명시했습니다. 가짜 웹사이트, 고객 센터, 맞춤형 공격 도구까지 갖춘 다국적 기업급 위장 체계가 오직 개발자 한 사람을 낚아채기 위해 총동원되었습니다. 오픈소스 생태계에서 가장 취약한 고리는 이제 견고한 서버 인프라가 아니라, 아무런 방비가 없는 메인테이너의 개인 계정과 기기로 옮겨갔습니다.

이미지 파일 끝자락에 숨겨둔 1.68MB 원격 제어 악성코드

개발자 매트 마스트라치(grack.com)는 자신이 희생양이 될 뻔했던 전 과정을 상세히 공개했습니다. 그는 과거에 실재했으나 현재는 운영을 중단한 탈중앙화 금융(DeFi) 벤처 캐피털인 “루아 벤처스(Lua Ventures)“를 사칭한 제안 메일을 받았습니다. 상대방은 “티켓 하버(Ticket Harbor)“라는 페리 티켓 예매 애플리케이션 저장소를 보내며, 정적 코드 검사와 빌드 명령을 실행해 줄 것을 요청했습니다.

공격자가 보낸 최초 피싱 이메일 그림: 공격자가 보낸 최초 피싱 이메일. 출처: grack.com 《Anatomy of a Failed (Nation-State?) Attack》

저장소는 겉보기에 평범한 타입스크립트 프로젝트처럼 보였지만, 내부 깊숙한 곳에 교묘히 위장된 네 개의 postinstall 훅이 숨겨져 있었습니다. 그중 하나의 훅은 은밀히 git update-index --skip-worktree 명령을 실행했습니다. 이 명령어는 깃(Git)이 특정 파일의 변경 사항을 강제로 무시하게 만듭니다. 따라서 피해자가 터미널에서 git status를 입력하더라도 패치 파일이 변조되었다는 사실을 전혀 눈치챌 수 없습니다.

실제 악성 페이로드는 typescript+5.9.2.patch라는 패치 파일 안에 숨어 있었습니다. 컴파일러 원본 파일 최상단에 난독화된 스크립트를 삽입해 둔 것입니다. 이 스크립트는 백신 프로그램의 정적 시그니처 탐지를 피하기 위해 흔히 쓰이는 eval 대신 new Function(...)을 활용하여 메모리상에서 실행 로직을 동적으로 인스턴스화했습니다.

후속 이메일로 전달된 '테스트 과제' 요청 그림: 후속 이메일로 전달된 ‘테스트 과제’ 요청. 출처: grack.com

일반적인 이미지 파서는 파일의 끝(EOF) 마커를 만나면 읽기를 중단합니다. 하지만 이 로더 스크립트는 operators/3.png 파일의 끝부분으로 직접 건너뛰어, 이미지 뒤에 덧붙여진 숨은 데이터 블록을 추출하고 웹어셈블리(WebAssembly) 형식의 실행 스텁을 구동했습니다. 이 스텁은 백그라운드에서 조용히 노드(Node) 프로세스를 띄워 최종적으로 1.68MB에 달하는 2단계 페이로드를 피해자의 운영체제에 주입했습니다. 악성코드가 정상적인 정적 이미지와 메모리 공간을 거치며 단계별로 실행될 때, 전통적인 정적 코드 분석 도구는 완전히 무력화됩니다.

세 단계에 걸쳐 모든 디지털 포렌식 흔적을 지우다

“핀핀랫(PinpinRAT)“으로 명명된 이 원격 제어 악성코드(RAT)는 시스템 상주 및 실행 단계에서 매우 엄격하고 빈틈없는 작전 규율을 보여주었습니다.

악성코드가 실행되면 즉시 피해자의 로컬 환경에서 RSA-2048 키 쌍을 생성하고 무작위 AES-256 세션 키를 생성합니다. 이후 발생하는 모든 명령 제어(C2) 통신 트래픽은 AES-256-CBC 알고리즘으로 암호화되며, HMAC-SHA256 무결성 검증 태그가 부착됩니다. 트래픽 모니터링 장비에는 엔트로피가 매우 높은 난수 데이터만 잡히기 때문에, 기업용 방화벽이라도 외부로 어떤 명령이 전달되고 있는지 전혀 분석할 수 없습니다.

이 악성코드는 기기를 완전히 장악할 수 있는 모든 기능을 내장하고 있었습니다. 클라우드 서버 접근 키와 패키지 배포 토큰이 보관되는 환경 변수를 통째로 덤프하여 외부로 유출할 수 있었습니다. 또한 임의의 파일 읽기 및 쓰기, 시스템 프로세스 생성은 물론, 암호화된 데이터를 DNS 질의 패킷에 실어 기업 내부망을 몰래 빠져나가는 DNS 터널링 구축 기능까지 지원했습니다.

미끼 저장소와 테스트 과제 설명 그림: 미끼 저장소와 테스트 과제 설명. 출처: grack.com

PinpinRAT은 윈도우(Windows) 환경에서는 숨겨진 예약 작업에 등록되었고, 맥OS(macOS)에서는 시스템 핵심 네트워크 프로세스(com.apple.WebKit.Networking)로 위장했습니다.

가장 위협적인 부분은 흔적 삭제 기법이었습니다. 전체 공격 체인은 3단계에 걸쳐 자동으로 흔적을 지우도록 설계되었습니다. Git의 skip-worktree를 통한 은닉은 첫 단계에 불과했습니다. 다운로더는 최초 실행 후 즉시 패치 파일 내의 악성코드를 삭제하고 원본 상태로 복구했습니다. 2단계 페이로드는 임시 디렉터리에서 실행을 마친 뒤 자체 파괴 메커니즘을 작동시켜 로컬에서 흔적을 지웠습니다. 이 악성코드는 주요 방어선을 뚫은 뒤에도 피해자의 시스템에 은밀히 상주하며, 지속적인 소프트웨어 공급망 오염을 위한 도약대로 활용하려 했습니다.

인공지능(AI)이 우연히 밝혀낸 가짜 면접의 실체

철저한 위장으로 무장한 이 연쇄 공격에서 grack.com의 저자가 위기를 모면할 수 있었던 것은 본능적인 경계심과 우연한 행운 덕분이었습니다.

그는 아키텍처 평가를 요구하는 직무에 비해 전달받은 저장소의 수준이 지나치게 기초적이라는 점에서 위화감을 느꼈습니다. 신중을 기한 그는 로컬 환경에서 빌드 명령을 실행하지 않았습니다. 대신 코드를 압축하여 클로드(Claude)에 전달하고 빠른 검사를 요청했습니다. 클로드는 즉시 이상 징후를 발견했습니다. 프로젝트 설정 파일에 라이프사이클 훅이 정의되어 있지 않은데도, 코드에서는 patch-package를 사용해 패치를 강제로 적용하고 있었습니다. 이를 추적한 결과 패치 디렉터리 깊숙이 숨겨져 있던 악성코드의 실체가 드러났습니다.

저자는 사후 분석에서 아찔했던 순간을 되돌아보았습니다. 만약 공격자들이 러스트 프로젝트에서 매일 실행되는 빌드 스크립트인 build.rs에 악성코드를 숨겨 두었다면 꼼짝없이 당했을 것이라고 회고했습니다.

접촉 과정 전체를 복기해 보면 곳곳에 수상한 징후(레드 플래그)가 가득했습니다. 이메일에는 대규모 언어 모델(LLM)이 생성한 특유의 정형화된 어투가 묻어 있었습니다. 링크드인 이력서는 화려했지만 실질적인 업무 성과가 없는 껍데기 직함뿐이었습니다. 상대방이 사용한 소셜 미디어 계정은 과거 활동 이력이 있었지만, 이름이 2025년 11월에야 변경되었으며 관련 기업들 역시 구체적인 영업 활동 흔적이 전혀 없었습니다.

면접 일정 조율도 상식 밖이었습니다. 정상적인 벤처 캐피털이라면 일정 캘린더 초대장도 없이 시간과 회의 링크만 덜컥 던져주지 않습니다. 면접관은 통화 내내 카메라 켜기를 거부했습니다. 또한 물리적 위치도 어색하게 분산되어 있었습니다. 싱가포르 기반 펀드, 유럽 시간대로 일하는 담당자, 캐나다에 거주하는 대상 개발자, 그리고 미국 고객을 대상으로 한다면서 .cc 도메인을 쓰는 웹사이트까지. 신원 확인 요소와 물리적 좌표를 넓게 흩어놓을수록 피해자가 허점을 간파하기는 훨씬 어려워집니다.

개인의 여가 시간으로는 국가급 표적 공격을 막아낼 수 없다

이번 보안 사건의 조사 과정에서 악성코드가 숨겨진 이미지 파일은 대표적인 백신 검사 플랫폼인 바이러스토털(VirusTotal)에서 메이저 보안 엔진 중 단 하나도 경고를 띄우지 못했습니다.

러스트 공식 팀이 이번 보안 권고에서 제시한 대응 방안은 여전히 개인의 주의에 머물러 있습니다. 낯선 연락에 의구심을 품고, 화상 회의는 본인이 직접 개설하며, 다중 인증(MFA)과 과거 로그인 기록을 수시로 확인하라는 식입니다.

하지만 개인의 경계심에만 기댄 방어 체계는 지극히 비대칭적입니다. 공격을 시도하는 쪽은 위조된 이력서 한 장과 한 시간의 화상 통화만 들이면 되지만, 성공했을 때 얻는 대가는 수억 대의 기기에 접근할 수 있는 막강한 권한입니다. 수억 회의 다운로드를 무보수로 지탱하는 개발자가 마우스 클릭을 단 한 번만 잘못해도 기기 전체를 장악당합니다. 그들이 쥐고 있는 배포 권한은 소스 코드 저장소 그 자체보다 훨씬 값비쌉니다. 몇몇 개발자가 여가 시간을 쪼개어 세운 디지털 세계의 토대가 이제 국가급 해킹 조직의 일상적이고 산업화된 표적 침투에 직접 노출되고 있습니다.

참고 링크:

  • Targeted attacks on rust-lang members and crate authors
  • Dissecting a failed nation-state attack
  • Supply-chain attack on arrayref