TECH 으로 돌아가기
TECH HACKER NEWS 8분 읽기 24 READS

Cursor 마켓플레이스 'Claude Code' 확장에 숨은 SSH 백도어 — 공급망 공격의 해부

Cursor 마켓플레이스 'Claude Code' 확장에 숨은 SSH 백도어 — 공급망 공격의 해부
SOURCE IMAGE · HACKER NEWS

보안 업체 Phorion이 Cursor 마켓플레이스에 올라온 공식 'Claude Code for VS Code' 확장(버전 2.1.313) 번들에서 지속성 SSH 백도어를 발견했다. 이 악성 코드는 macOS, 리눅스, 윈도우를 모두 겨냥했으며, 피해 호스트에 공격자의 키를 심고 외부로 연결되는 터널을 열어 장기적인 대화형 접근을 노린다. Cursor는 해당 릴리스를 마켓플레이스에서 내렸고, NPM과 VS Code 레지스트리에서도 2.1.313 버전을 함께 제거했다. 조직은 즉시 자사 환경에서 이 버전의 사용 여부를 점검하고, 발견될 경우 침해 대응 절차에 착수해야 한다.

이번 사건이 특히 위험한 이유는 IDE 확장이라는 공격 표면의 성격에 있다. 확장은 IDE와 그것을 실행하는 사용자의 권한으로 동작하기 때문에, 모듈이 로드되는 순간 로컬 파일과 소스 코드, 개발 도구에 그대로 접근할 수 있다. 문제의 extension.js는 정상적인 Claude Code 번들 앞부분에 즉시 실행 함수(IIFE)를 주입한 형태였다. 이 주입된 코드는 child_process, fs, os, crypto 같은 표준 Node.js 모듈을 불러와 Node가 파일을 읽는 즉시 실행되며, 확장의 정상적인 activate 콜백보다도 먼저 동작한다. 사용자가 확장과 상호작용할 필요조차 없이 페이로드가 발화하는 구조다.

백도어가 작동하는 방식

페이로드는 먼저 ~/.ssh 디렉터리를 확보한 뒤, 공격자가 통제하는 Ed25519 공개키를 authorized_keys에 덧붙인다. 디렉터리는 0700, 파일은 0600 권한으로 설정한다. 이 키의 주석은 svc-telemetry인데, 스크립트는 키 자체가 아니라 이 주석 문자열의 존재 여부만 확인하고 중복을 판단한다. 따라서 탐지 작업에서는 주석에만 의존하지 말고 공개키 지문(fingerprint)을 기준으로 추적하는 편이 안전하다.

키를 심은 뒤에는 외부로 나가는 SSH 연결을 134.209.82.225의 22번 포트로 맺는다. 인증에는 번들에 별도로 박아둔 암호화되지 않은 Ed25519 개인키(주석 svc-telemetry-tun)를 사용하며, 이 키는 OS 임시 디렉터리에 호스트명과 홈 경로의 MD5 해시 앞 10자를 붙인 .stk_ 접두 파일로 기록된다. 터널은 -R *:0:localhost:22 옵션으로 원격 포트 포워딩을 걸어, 공격자 서버가 동적으로 할당한 포트로 들어온 트래픽을 피해 PC의 로컬 22번 포트로 되돌린다. 운영자는 이후 그 포트를 통해 1단계에서 심어둔 키로 피해자의 로컬 SSH 데몬에 인증하면, 자바스크립트 안에 별도 C2 명령 처리를 넣지 않고도 완전한 대화형 셸과 파일 전송 능력을 얻는다.

macOS를 구한 구현 실수

흥미로운 지점은 공격자의 명백한 실수다. macOS에서 스크립트는 권한 상승 없이 systemsetup -getremotelogin을 실행해 출력이 'Off'인지 검사하고, Off일 때만 원격 로그인을 켜려 한다. 그런데 일반 사용자 권한으로 이 명령을 돌리면 macOS는 설정값 대신 "administrator access가 필요하다"는 오류 문구를 stdout에 출력하면서 종료 코드 0을 반환한다. 결국 /Off/i 검사가 거짓이 되어 활성화 블록을 통째로 건너뛴다. 즉 악성 코드는 '권한이 없어 확인 불가'인 상태를 'SSH가 이미 켜짐'으로 오판하는 셈이다. 애초에 권한 상승 익스플로잇이 없고 sudo -n는 비밀번호 없는 sudo가 설정돼 있지 않으면 실패하므로, 원격 로그인이 꺼진 Mac에서는 되돌아온 트래픽이 닫힌 로컬 22번 포트에 부딪힌다. 윈도우 경로에도 PowerShell 명령을 /bin/sh에 하드코딩된 헬퍼로 넘기는 버그가 있었다.

다만 이 버그를 방어 수단으로 믿어서는 안 된다. 사용자가 이미 원격 로그인을 켜 뒀거나 나중에 켜면 백도어는 즉시 완성된다. 게다가 SSH 키와 지속성 구성 요소는 이 실수와 무관하게 멀쩡히 설치된다. 재부팅을 견디기 위해 macOS와 리눅스에서는 ~/.config/.smt 스크립트가 터널 개인키를 ~/.config/.smtk로 풀어낸 뒤 재접속 루프를 돌리고, macOS에서는 LaunchAgent가 com.apple.sysmond.plist로 위장해 ~/Library/LaunchAgents/에 자리잡는다. 터널은 분리된(detached) 재시도 루프로 60초마다 연결을 시도하므로 IDE를 닫아도 살아남는다.

탐지와 대응의 실무 포인트

설치 직후 스크립트는 setTimeout으로 1.5초 뒤 한 차례 비콘을 보낸다. 호스트 정찰 정보를 모아 134.209.82.225:8099와 127.0.0.1:8099의 /beacon 경로로 평문 HTTP POST한다. 주목할 점은 환경변수를 Object.keys(process.env)로 이름만 수집한다는 것이다. 비밀값 자체를 유출하지는 않지만, 어떤 클라우드 자격 증명이나 API 토큰이 그 머신에 사는지 운영자에게 목록을 넘겨 우선순위를 정하게 해준다. 공인 IP는 ifconfig.me를, 실패 시 api.ipify.org를 질의해 얻는다.

탐지 관점에서 핵심은 프로세스 명령이 아니라 파일 변경 텔레메트리다. 이 악성 코드는 echo나 tee 대신 Node의 fs.appendFileSync로 authorized_keys를 직접 수정하므로, 셸 명령만 감시하는 규칙은 놓친다. 정상 서명된 IDE라도 그 확장 호스트 프로세스가 백그라운드에서 SSH 인증 파일을 건드릴 이유는 없다는 점에 착안해, Code Helper나 Cursor Helper 같은 보조 프로세스가 ~/.ssh/authorized_keys에 쓰는 행위를 보라는 것이 Phorion의 권고다. systemsetup -setremotelogin on 명령은 앞서의 버그 탓에 아예 실행되지 않는 경우가 많으므로 경보의 필수 조건으로 삼아선 안 된다. 또한 포트 포워딩을 통해 들어온 로그인은 SSH 로그에서 localhost(127.0.0.1 또는 ::1)에서 svc-telemetry 키로 인증한 것처럼 보이므로, 단순히 터널이 섰는지뿐 아니라 실제 로그인이 있었는지까지 확인해야 한다. 끝으로, 확장을 삭제하는 것만으로는 백도어가 제거되지 않는다. authorized_keys의 공격자 키, 임시 디렉터리의 터널 키, LaunchAgent와 .smt·.smtk 지속성 요소까지 각 단계를 모두 걷어내야 대응이 완결된다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://phorion.io/blog/offical-claude-code-vsx-compromise/
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...