LinkedIn 채용 제안 속 백도어

1 week ago 11
  • 채용 코드 리뷰 요청이 공개 GitHub 저장소 검토와 npm install 유도로 이어졌고, 저장소 안에는 서버가 돌려주는 코드를 실행하는 백도어가 숨겨져 있었음
  • 의심이 든 뒤 로컬 설치 대신 Hetzner의 일회용 VPS에서 저장소를 복제하고, Pi를 읽기 전용 도구만 켠 상태로 실행해 의심 파일을 빠르게 찾아냄
  • 백도어는 app/test/index.js에 테스트 코드처럼 숨겨져 있었고, 조각난 문자열이 ` URL로 합쳐진 뒤 서버 응답을 실행함
  • app/index.js가 ./test를 불러오고 package.json의 prepare 스크립트가 npm install 뒤 자동 실행되므로, 의존성 설치만으로 백도어가 실행됨
  • 저장소 커밋 작성자와 리크루터 프로필 모두 실제 인물의 신원을 빌린 것으로 확인됐고, GitHub와 LinkedIn에 신고했지만 당시 저장소 코드는 그대로 남아 있었음

사건 흐름과 백도어 구조

  • LinkedIn 채용 제안

    • 작은 암호화폐 스타트업의 리크루터가 LinkedIn 메시지를 보냈고, 며칠간 대화한 뒤 고장 난 개념증명 코드에 리드 엔지니어가 필요하다고 설명함
    • 리크루터는 공개 GitHub 저장소를 보내며 “deprecated Node modules issue”를 확인해 달라고 요청함
    • 기존 코드베이스 리뷰 요청 자체는 드문 일이 아니었지만, 메시지 흐름에서 이상함을 느껴 더 조심스럽게 접근함
    • 로컬에서 저장소를 복제하고 의존성을 설치하지 않고, Hetzner의 일회용 VPS에서 저장소를 복제함
    • Pi를 read, grep, find, ls만 허용한 읽기 전용 모드로 실행했고, 에이전트가 거의 즉시 app/test/index.js를 의심 파일로 찾아냄
  • 백도어

    • 저장소는 React 프런트엔드와 Node 백엔드처럼 보였고, 실제 함정은 약 250줄짜리 테스트 스위트처럼 위장한 app/test/index.js에 있었음
    • 파일 안에서는 protocol, domain, separator, path, token, subdomain, bearrtoken 같은 조각이 합쳐져 https://rest-icon-handler.store/icons/77 URL이 만들어짐
    • 주석 처리된 테스트 코드 사이에 묻힌 페이로드는 해당 서버가 돌려주는 내용을 사용자 머신에서 실행함
    • 실제 테스트 실행을 기다리지 않고 app/index.js가 const test = require('./test')를 실행하면서 app/test/index.js가 로드되고 실행됨
    • package.json은 app/index.js를 시작 과정에 연결했고, npm의 prepare 스크립트는 npm install 뒤 자동 실행됨
    • “deprecated Node modules issue” 확인 요청은 npm install 실행을 유도하는 미끼였음
    • 샌드박스에서 페이로드를 실행해 두 번째 단계 응답을 볼 수도 있었지만, 서버가 넘겨주는 코드를 실행하는 저장소라는 점만으로 충분한 증거였음

도용된 신원과 실무적 교훈

  • 도용된 개발자 신원

    • 저장소 커밋은 실제 개발자의 이름과 이메일로 작성된 상태였음
    • 해당 개발자는 평범한 LinkedIn 프로필, 개인 웹사이트, 긴 이력이 있는 GitHub 계정을 가진 풀스택 엔지니어였음
    • 코드베이스를 물려받았다는 식으로 구현 질문을 보내 반응을 확인했고, 해당 개발자는 그 회사에서 일한 적이 없다고 답함
    • 해당 개발자는 이전에도 GitHub에서 사칭당했고, 그 일로 저장소가 내려간 적이 있으며, 이번 저장소들과도 관련이 없다고 답함
    • 해당 개발자도 이런 저장소들을 신고하고 있었음
  • 도용된 리크루터 신원

    • 리크루터 프로필은 실제 예술 저널리스트의 신원을 사용하고 있었음
    • 해당 인물은 잘 알려진 예술 저널리스트였고, 긴 문화 분야 이력이 있었으며, 기술 관련 이력은 없었음
    • 프로젝트 설치가 되지 않는다고 하자 해당 프로필은 즉시 npm과 Node 버전에 능숙한 사람처럼 대응함
  • 누구에게나 일어날 수 있는 공격

    • 이런 공격을 들어보고 Hacker News에서도 읽은 적이 있었지만, 실제로 직접 당하자 약간 당황할 수밖에 없었음
    • 처음 몇 메시지부터 의심했지만, 피곤하거나 급한 날이었다면 생각하기 전에 npm install을 실행했을 수도 있었음
    • LinkedIn에서 저장소 리뷰 요청을 받으면 약간의 의심과 기본적인 보안 위생이 도움이 됨
    • 읽기 전용 에이전트로 코드를 검토한 방식은 직접 읽는 것보다 더 생산적이었고, 초보자가 짠 엉성한 코드처럼 꾸며진 백도어를 몇 초 만에 찾아냄
    • 저장소는 GitHub에, 리크루터는 LinkedIn에 신고했지만 당시 아무 변화가 없었고 코드는 여전히 올라와 있었음
Read Entire Article