Devlery
Blog/AI

LiteLLM 해킹 사건: AI 인프라를 노린 TeamPCP 연쇄 공급망 공격의 전말

월 9500만 다운로드 AI 프록시 LiteLLM이 공급망 공격으로 감염됐습니다. TeamPCP 그룹이 한 달간 Trivy, npm, KICS, LiteLLM을 연쇄 공격한 캠페인의 기술적 분석과 AI 생태계 보안 시사점을 정리합니다.

3월 24일, AI 개발자들이 매일 사용하는 Python 패키지 하나가 조용히 무기로 변했습니다. LiteLLM — OpenAI, Anthropic, Google 등 100개 이상의 LLM 프로바이더를 단일 API로 통합하는 프록시 라이브러리가 공급망 공격에 감염된 것입니다. 월간 다운로드 수 9,500만 회. PyPI에서 가장 널리 쓰이는 AI 인프라 패키지 중 하나입니다.

더 충격적인 것은 이 공격이 단독 범행이 아니라는 점입니다. TeamPCP라는 위협 그룹이 2월 말부터 한 달간 벌인 연쇄 공급망 공격 캠페인의 최신 챕터였습니다. Aqua Security의 Trivy, npm 생태계 45개 이상의 패키지, Checkmarx의 KICS, 그리고 LiteLLM — 하나의 침해가 다음 침해의 열쇠가 되는 도미노가 지금 AI 개발 생태계 한가운데서 벌어지고 있습니다.

한 달간의 도미노 — TeamPCP 공격 타임라인

이 사건을 이해하려면 3월 24일의 LiteLLM 감염만 봐서는 안 됩니다. TeamPCP의 캠페인은 2월 28일에 시작되어, 각 공격에서 탈취한 자격증명이 다음 공격의 진입점이 되는 연쇄 구조로 확산됐습니다.

2/28

Trivy 최초 침해

GitHub PAT 탈취

자격증명 →

3/19

Trivy 2차 공격

백도어 바이너리 배포

자격증명 →

3/20

npm 45+ 패키지

자기 전파 웜

자격증명 →

3/22

Docker Hub 감염

악성 이미지 게시

자격증명 →

3/23

KICS GitHub Action

35개 태그 탈취

자격증명 →

3/24

LiteLLM PyPI 감염

9,500만 DL/월

각 침해에서 탈취한 자격증명이 다음 공격의 진입점이 됩니다

2월 28일 — Trivy 최초 침해. Aqua Security의 오픈소스 보안 스캐너 Trivy의 GitHub 리포지토리에서 pull_request_target 워크플로우 취약점을 악용했습니다. 쓰기 권한이 있는 PAT(Personal Access Token)를 탈취하여 전체 리포지토리를 장악했습니다.

3월 19일 — Trivy 2차 공격. 불완전한 초기 대응의 틈을 파고들어 다시 침입했습니다. v0.69.4 태그를 하이재킹하여 릴리스 파이프라인을 트리거하고, GitHub Releases, Docker Hub, GHCR, ECR 전역에 백도어가 심긴 바이너리를 배포했습니다.

3월 20일 — npm 생태계 자동 전파. 탈취한 토큰으로 npm에서 자기 전파 웜(self-propagating worm) 을 실행했습니다. 60초 만에 접근 가능한 모든 패키지에 악성 패치 버전을 자동 게시하여, 45개 이상의 npm 패키지가 감염됐습니다.

3월 22일 — Docker Hub 추가 감염. 탈취한 Aqua 자격증명으로 Docker Hub에 악성 trivy:0.69.50.69.6 이미지를 게시했습니다.

3월 23일 — Checkmarx KICS 탈취. OpenVSX의 IDE 확장 2개와 KICS GitHub Action의 35개 태그 전체를 하이재킹했습니다. 새로운 C2(Command & Control) 인프라 checkmarx.zone을 도입하고, Kubernetes 영속성(persistence) 기능을 추가했습니다.

3월 24일 — LiteLLM 감염. KICS 침해로부터 약 22시간 후, UTC 10:39~10:52 사이에 LiteLLM 메인테이너의 계정을 탈취하여 PyPI에 악성 버전 1.82.7과 1.82.8을 게시했습니다. 메인테이너의 포크된 리포지토리에는 "teampcp owns BerriAI"라는 커밋 메시지가 남겨져 있었습니다.

보안 연구 기관 Endor Labs는 이 캠페인에 대해 다음과 같이 분석했습니다.

"각 침해에서 획득한 자격증명이 다음 타깃을 여는 열쇠가 됩니다. 하나의 패키지 레지스트리에 대한 접근이 다른 레지스트리를 타깃으로 삼는 것을 촉진합니다."

LiteLLM 감염의 기술적 해부

LiteLLM의 감염은 두 가지 버전에서 서로 다른 방식으로 이루어졌습니다. 두 버전 모두 목표는 동일합니다 — 개발자의 시스템에서 가능한 모든 자격증명을 수확하여 공격자에게 전송하는 것입니다.

버전 1.82.7 — import 시 실행

litellm/proxy/proxy_server.py의 128번째 줄에 12줄짜리 악성 코드가 삽입됐습니다. base64로 인코딩된 페이로드가 모듈 import 시점에 실행됩니다. from litellm import ... 한 줄이면 감염이 시작됩니다.

버전 1.82.8 — Python 실행만으로 감염

더 교활한 방식입니다. 휠(wheel) 루트에 litellm_init.pth라는 34,628바이트 파일이 포함됐습니다. .pth 파일은 Python의 site.py가 인터프리터 시작 시 자동으로 처리하는 파일입니다. LiteLLM을 import하지 않아도, Python을 실행하는 것만으로 악성코드가 동작합니다.

3단계 공격 체인

감염 후 실행되는 악성 페이로드는 정교한 3단계 구조로 설계되어 있습니다.

🎯Stage 1오케스트레이터

크리덴셜 하베스터 실행

AES-256-CBC 암호화

RSA-4096 OAEP 세션키 래핑

tpcp.tar.gz → models.litellm.cloud

🕷️Stage 2크리덴셜 하베스터 (332줄)

SSH 키 (RSA, Ed25519, ECDSA)

AWS · GCP · Azure 자격증명

Kubernetes 시크릿 전체 덤프

.env 파일 (15개+ 경로 탐색)

DB 비밀번호 · 암호화폐 지갑

TLS 인증서 · CI/CD 시크릿

👻Stage 3영구 백도어

~/.config/sysmon/sysmon.py 설치

systemd 유닛 자동 등록

50분마다 C2 서버 폴링

추가 바이너리 다운로드 · 실행

1단계 — 오케스트레이터. 크리덴셜 하베스터를 실행하고, 수집된 데이터를 AES-256-CBC로 암호화한 뒤, 세션 키를 RSA-4096 OAEP로 래핑합니다. 최종 결과물은 tpcp.tar.gz라는 이름으로 models.litellm.cloud — LiteLLM의 공식 도메인처럼 보이는 공격자 소유 도메인으로 전송됩니다.

2단계 — 크리덴셜 하베스터 (332줄). 시스템에서 수확하는 자격증명의 범위가 충격적입니다.

  • SSH 키: id_rsa, id_ed25519, id_ecdsa, id_dsa
  • 클라우드 자격증명: AWS IMDS 역할 자격증명, GCP application_default_credentials.json, Azure ~/.azure/
  • Kubernetes: 시크릿 전체 덤프, 네임스페이스 전체 탐색
  • 환경 변수 파일: /home, /root, /opt, /srv, /var/www, /app, /data 등 15개 이상 경로에서 .env, .env.local, .env.production 수집
  • 데이터베이스: .pgpass, my.cnf, redis.conf, .mongorc.js
  • 암호화폐 지갑: Bitcoin, Ethereum, Solana, Cardano 등 10개 체인
  • TLS/SSL: .pem, .key, .p12, .pfx 파일
  • CI/CD: terraform.tfvars, terraform.tfstate, .gitlab-ci.yml, Jenkinsfile
  • 셸 히스토리: bash, zsh, MySQL, PostgreSQL, Redis

3단계 — 영구 백도어. ~/.config/sysmon/sysmon.py에 백도어를 설치하고 systemd 유닛으로 등록합니다. 5분의 초기 딜레이 후, 50분마다 checkmarx.zone/raw를 폴링하여 추가 바이너리를 다운로드하고 실행합니다. 응답에 "youtube.com"이 포함되면 킬 스위치가 작동합니다.

Kubernetes 횡이동 — 클러스터 전체 장악

가장 위험한 부분은 Kubernetes 횡이동입니다. 악성코드는 모든 클러스터 노드에 특권(privileged) 파드를 배포합니다. kube-system 네임스페이스에 node-setup-{노드명}이라는 이름으로 생성되며, hostPID, hostNetwork 권한과 함께 호스트의 전체 루트 파일시스템을 마운트합니다. 모든 테인트(taint)를 톨러레이션하여 컨트롤 플레인 노드까지 침투합니다.

LiteLLM을 프로덕션에서 AI 게이트웨이로 운영하는 조직이라면, 이 공격 하나로 전체 Kubernetes 클러스터가 노출될 수 있습니다.

폭발 반경 — 누가 영향을 받는가

LiteLLM은 단독으로 사용되는 패키지가 아닙니다. AI 개발 생태계의 핵심 인프라 레이어에 위치해 있습니다.

직접 의존하는 주요 프로젝트들:

  • DSPy — Stanford NLP의 프롬프트 프로그래밍 프레임워크
  • CrewAI — 멀티 에이전트 오케스트레이션 프레임워크
  • 기업 내부 AI 게이트웨이 및 프록시 서버

Hacker News의 한 개발자는 이렇게 지적했습니다.

"문제는 LiteLLM 하나가 아닙니다. DSPy, CrewAI 등 주요 프로젝트들이 LiteLLM에 의존하고 있어서, 연쇄적인 공급망 취약점이 발생합니다."

PyPI에서 감염된 버전은 이미 제거됐지만, 마지막으로 확인된 안전한 버전은 1.82.6입니다. 자동 업데이트를 사용하거나 버전을 고정하지 않은 환경이라면, 이미 감염됐을 가능성이 있습니다.

감염 확인 방법

Endor Labs가 제공한 탐지 명령어입니다.

# LiteLLM 버전 확인
pip show litellm 2>/dev/null | grep -i version

# .pth 파일 존재 여부 확인
find "$(python3 -c 'import site; print(site.getsitepackages()[0])')" -name "litellm_init.pth"

# 백도어 영속성 확인
ls -la ~/.config/sysmon/

# K8s 악성 파드 확인
kubectl get pods -n kube-system | grep node-setup

감염이 확인되면 해당 호스트에서 접근 가능했던 모든 자격증명을 로테이션해야 합니다 — LLM 프로바이더 API 키, 클라우드 자격증명, SSH 키, 데이터베이스 비밀번호, Kubernetes 시크릿, .env 값, 레지스트리 토큰 전부입니다.

AI 생태계만의 특수한 위험

이번 사건이 일반적인 공급망 공격과 다른 점은, AI 인프라 패키지가 가진 특권적 위치 때문입니다.

첫째, AI 프록시는 모든 API 키의 허브입니다. LiteLLM 같은 AI 게이트웨이/프록시는 설계상 OpenAI, Anthropic, Google, Azure 등 다수의 LLM 프로바이더 API 키를 한곳에 보관합니다. 하나의 패키지를 침해하면 조직이 사용하는 모든 AI 서비스의 접근 키를 한꺼번에 탈취할 수 있습니다.

둘째, AI 개발 환경은 프로덕션과 가깝습니다. AI 에이전트와 프록시는 프로덕션 Kubernetes 클러스터에서 직접 운영되는 경우가 많습니다. 개발 도구 패키지의 감염이 곧바로 프로덕션 인프라의 침해로 이어질 수 있습니다.

셋째, 빠른 반복 개발 문화가 보안을 약화시킵니다. AI 스타트업과 개발팀은 빠른 프로토타이핑과 실험을 위해 pip install --upgrade를 자주 실행합니다. 버전 고정이나 보안 감사 없이 최신 버전을 바로 적용하는 관행이 공급망 공격의 공격면을 넓힙니다.

커뮤니티 반응 — "더 이상 의존성을 신뢰할 수 없다"

Hacker News에서 378 포인트, 175개의 댓글이 달린 이 사건에 대해 개발자 커뮤니티의 반응은 경각심과 좌절이 뒤섞여 있었습니다.

가장 많은 공감을 받은 의견은 근본적인 신뢰 문제를 지적했습니다.

"우리는 더 이상 의존성과 개발 환경을 신뢰할 수 없습니다."

여러 보안 연구자들은 Python 생태계의 구조적 문제를 강조했습니다. 복잡한 환경 관리, 과도한 의존성 체인, 그리고 빠른 개발을 위해 보안 검토 역량이 줄어드는 현실이 공급망 공격의 온상이 되고 있다는 것입니다.

일부 전문가들은 LLM을 활용한 악성코드 개발이 공급망 공격의 속도를 가속화하고 있을 수 있다고 우려했습니다. TeamPCP의 332줄짜리 정교한 크리덴셜 하베스터와 Kubernetes 횡이동 코드가 한 달도 안 되는 기간에 반복적으로 개선된 점이 그 근거입니다.

실무적인 대응 방안으로는 다음이 가장 많이 언급됐습니다.

  • 정확한 버전 고정: pip install litellm==1.82.6 같은 방식으로 특정 검증된 버전만 사용
  • 자동 업데이트 비활성화: CI/CD에서 --upgrade 플래그 제거
  • PyPI Trusted Publishers: OIDC 기반 게시로 토큰 탈취 위험 감소
  • 개발 환경 샌드박싱: 컨테이너화된 개발 환경으로 호스트 시스템 격리
  • 락 파일 변경 모니터링: requirements.txtpoetry.lock 변경에 대한 자동 알림

다음 타깃은 어디인가

Endor Labs는 TeamPCP의 다음 행보를 다음과 같이 예측했습니다.

추가 레지스트리 침투. RubyGems, crates.io, Maven Central이 잠재적 타깃입니다. TeamPCP는 이미 PyPI, npm, Docker Hub를 넘나들며 크로스 레지스트리 공격 능력을 입증했습니다.

자기 전파 웜의 PyPI 확산. npm에서 성공한 자기 전파 웜 패턴을 PyPI에도 적용할 가능성이 높습니다. 탈취한 PyPI 토큰으로 자동으로 악성 패치 버전을 게시하는 시나리오입니다.

보안 도구 타깃 지속. TeamPCP의 패턴을 보면 의도적으로 "보안, 관측, 인프라 도구"를 표적으로 삼고 있습니다. 이런 도구들은 시스템에서 높은 권한으로 실행되기 때문에, 침해 시 획득할 수 있는 자격증명의 범위가 넓습니다. AI 보안 스캐너, 관측 도구, 인프라 관리 패키지가 다음 타깃이 될 수 있습니다.

프로덕션 자격증명으로의 전환. CI/CD 단기 시크릿에서 AWS Secrets Manager, Kubernetes 서비스 어카운트 토큰 같은 장기 프로덕션 자격증명으로 수확 대상을 확대할 것으로 예상됩니다.

시사점 — AI 공급망 보안은 선택이 아니다

이번 사건은 AI 개발 생태계의 보안이 얼마나 취약한지를 적나라하게 드러냈습니다. LiteLLM은 그 자체로 뛰어난 프로젝트이고, 메인테이너의 잘못이 아닙니다. 문제는 오픈소스 생태계의 구조적 신뢰 모델이 현재의 위협 수준을 감당하지 못하고 있다는 점입니다.

하나의 메인테이너 계정이 침해되면, 수천만 명의 개발자가 쓰는 패키지가 수 시간 내에 무기화될 수 있습니다. 그리고 AI 패키지는 그 특성상 — 다수의 API 키를 보관하고, 프로덕션 인프라에 직접 배포되며, 빠른 업데이트 주기를 가지기에 — 공급망 공격의 가장 매력적인 타깃이 되고 있습니다.

개발자에게 권고하는 즉각적인 조치:

  1. LiteLLM 버전을 확인하고, 1.82.7 또는 1.82.8이라면 즉시 1.82.6으로 다운그레이드
  2. 감염된 호스트의 모든 자격증명 로테이션 (API 키, SSH 키, 클라우드 자격증명, K8s 시크릿)
  3. ~/.config/sysmon/ 디렉토리와 kube-systemnode-setup-* 파드 확인
  4. 모든 AI 인프라 패키지의 버전을 고정하고, 자동 업데이트 비활성화
  5. PyPI Trusted Publishers(OIDC 기반) 도입 검토

TeamPCP의 캠페인은 아직 끝나지 않았습니다. 3월 한 달간 5번의 주요 공격을 성공시킨 이 그룹이 멈출 이유는 없습니다. AI 생태계의 폭발적 성장이 보안 인프라의 성숙을 앞지르고 있는 지금, 공급망 보안은 더 이상 "나중에 할 일"이 아니라 생존의 문제입니다.