공급망 공격

발행: (2025년 12월 30일 오후 01:45 GMT+9)
7 min read
원문: Dev.to

Source: Dev.to

위에 제공된 소스 링크 외에 번역할 텍스트를 알려주시면, 요청하신 대로 한국어로 번역해 드리겠습니다.

Phase 1: 대상의 해부학

현대 웹 개발에서는 우리는 거의 모든 것을 처음부터 직접 작성하지 않습니다. 우리는 전이 의존성 위에 서 있습니다.

  • 직접 의존성: useful-auth-lib를 설치합니다.
  • 전이 의존성: useful-auth-libsmall-string-helper에 의존합니다.

숨겨진 위험: package.json에 패키지가 10개뿐일지라도 node_modules 폴더에는 800개 이상의 패키지가 들어 있을 수 있습니다. 당신의 보안은 그 800개의 사슬 중 가장 약한 고리만큼만 안전합니다.

Phase 2: The Attack – “The Long Game”

1. Target Selection

공격자는 React와 같이 눈에 많이 띄는 대형 라이브러리를 목표로 하지 않는다(관심이 너무 많음). 대신 깊은 의존성—1년 동안 업데이트되지 않았지만 수천 개의 다른 인기 패키지에서 사용되는 작은 유틸리티 라이브러리를 찾는다.

2. Social Engineering (The “Trojan Horse”)

공격자는 가짜이지만 전문적으로 보이는 GitHub 프로필을 사용해 저장소에 도움이 되는, 정상적인 코드를 기여하기 시작한다.

  • 오타 수정.
  • 문서 개선.
  • 루프 최적화.

Result: 원래 과중한 업무를 맡고 있던 유지관리자는 결국 그에게 “Maintainer” 권한이나 npm 레지스트리의 publish 권한을 부여한다.

3. The Injection

공격자는 v3.4.2 버전을 릴리스한다. GitHub에 있는 코드는 깔끔해 보이지만 npm 레지스트리에 게시된 코드는 악성 페이로드를 포함하고 있다.

Key Insight: npm은 레지스트리의 .tgz 파일에 있는 코드가 GitHub 저장소의 코드와 일치하는지 검증하지 않는다. 바로 여기서 백도어가 존재한다.

3단계: 실행 흐름

1단계: 자동 업데이트

대형 핀테크 기업의 개발자가 일상적인 명령을 실행합니다:

npm update

package.json에 있는 캐럿(^) 기호(예: "small-string-helper": "^3.4.0" ) 때문에 npm은 악성 v3.4.2를 자동으로 가져옵니다.

2단계: 라이프사이클 훅

공격자는 npm Lifecycle Scripts를 사용합니다. 악성 패키지의 package.json에 다음을 추가합니다:

{
  "scripts": {
    "postinstall": "node ./scripts/init.js"
  }
}

npm install이 완료되면 init.js가 자동으로 실행되며, 개발자 또는 빌드 서버와 동일한 권한을 가집니다.

3단계: 환경 지문 채취

스크립트는 즉시 공격하지 않고 환경을 “지문 채취”합니다:

  • CI/CD 서버? GITHUB_ACTIONS 또는 JENKINS_URL와 같은 변수를 확인합니다.
  • 고가치 대상? .aws/credentials, .env 파일, 혹은 id_rsa SSH 키를 찾습니다.
  • 프로덕션 환경? NODE_ENV === 'production'인지 확인합니다.

4단계: 백도어 및 정보 유출

조건이 맞으면 스크립트는 다음을 수행합니다:

  • 스니펫을 삽입하여 로그인 폼을 가로채는 코드를 메인 애플리케이션에 주입합니다.
  • 역쉘을 열어 공격자 서버와 연결하고 원격 명령 실행을 가능하게 합니다.
  • 비밀을 탈취하여 .env 변수를 원격 API로 전송합니다.

Phase 4: The Modern Defense Strategy

1. Dependency Pinning & Lockfiles

  • Lockfiles: 항상 package-lock.json을 커밋하세요. 이는 정확한 버전을 강제하고 패키지의 해시(무결성)를 검증하여 변조되지 않았는지 확인합니다.
  • Pinning: 보안이 중요한 프로젝트에서는 범위(^1.2.3) 대신 정확한 버전("library": "1.2.3")을 사용하세요.

2. Specialized Auditing Tools

ToolFunction
npm audit알려진 CVE에 대한 기본 검사.
Snyk / Socket.dev코드의 동작을 분석합니다(예: “왜 이 CSS 라이브러리가 네트워크 접근을 요구하나요?”).
StepSecurityCI/CD 파이프라인에서 알 수 없는 IP 주소로의 연결을 모니터링합니다.

3. Network Isolation

빌드 프로세스를 네트워크 제한 환경에서 실행하세요. 빌드 스크립트가 알 수 없는 외부 IP 주소로 데이터를 전송해야 하는 경우는 절대 없어야 합니다.

4. SBOM (Software Bill of Materials)

모든 릴리스에 대해 SBOM을 생성하세요. 사용된 모든 소프트웨어 구성 요소를 포괄적으로 목록화함으로써 새로 발견된 취약점이 여러분에게 영향을 미치는지 쉽게 파악할 수 있습니다.

The Takeaway

npm 세계에서는 단순히 코드를 가져오는 것이 아니라 의존성 트리의 모든 개발자가 사용하는 보안 관행을 가져오는 것입니다. 의존성 감사는 일회성 작업이 아니라 신뢰를 검증하는 지속적인 과정입니다.

Back to Blog

관련 글

더 보기 »