[KOR] LiteLLM v1.107.0 공급망 공격 분석 보고서

[KOR] LiteLLM v1.107.0 공급망 공격 분석 보고서

개요

2026년 10월 22일(목) 오전 5시 30분 (KST)에 LiteLLM이 공급망 공격을 당했다고 발표했다. LiteLLM v1.107.0 버전에서 릴리즈 파이프라인이 해킹 당했으며, 사용자 자격 증명 탈취 및 원격 코드 실행(RCE)이 가능한 악성코드가 Docker Hub, PyPi, GHCR에 릴리즈되었다.

각 소프트웨어 패키지 레지스트리에 배포되어있던 시간은 아래와 같다.

PyPI: 20시 39분 51초 ~ 22시 23분 00초 (KST)

Docker Hub: 20시 46분 56초 ~ 23시 20분 00초 (KST)

GHCR: 20시 46분 56초 ~ 22시 51분 00초 (KST)

사고 발생 배경 및 대응 경과

LiteLLM 내부 운영용 인스턴스 환경이 외부망에 노출되어 있었고, 공격자는 외부망을 통해 내부 환경에 접근하여 로그중 Claude Code의 특정 상황에서 응답 본문에 기록된 GitHUB CLI OAuth 토큰을 탈취하였다.

사고 대응 타임라인은 아래와 같다.

발생 일시(KST)

주요 경과

2026-10-13 09:45

공격에 사용된 litellm.dev 도메인 등록

2026-10-13 15:43

공격에 사용된 GitHub 계정 letters9813 생성

2026-10-18 13:17

공격 서버 주소 전달용 GitHub 저장소 pythonclient-test 생성

2026-10-20 18:15

테스트에 사용된 domain.txt 파일의 내용 삭제

2026-10-21 17:56 - 19:46

공격자가 정상 저장소와 이름이 유사한 위장 저장소 Berri-AI/litellm에 커밋 10건 반영

2026-10-21 19:08:29

브랜치 보호 정책에 의해 BerriAI의 비공개 릴리스 워크플로에 대한 무단 변경 시도 차단

2026-10-21 19:08:34

공격자가 탈취한 조직 소유자의 토큰을 이용해 브랜치 보호 정책을 우회하고, 워크플로 변경 커밋 9cf97e93 적용

2026-10-21 19:46:39

변조된 워크플로가 공격자 저장소 Berri-AI/litellm의 코드를 사용하여 공식 스테이징 파이프라인 실행

2026-10-21 20:00 - 20:06

악성코드가 포함된 v1.107.0 Docker 이미지 빌드

2026-10-21 20:08:53

프로덕션 릴리스 파이프라인 실행 시작

2026-10-21 20:11:18

공격자가 두 번째 개발자의 탈취된 자격 증명을 이용해 프로덕션 배포 승인 절차 통과

2026-10-21 20:21

LiteLLM 1.107.0 휠(wheel) 파일 빌드(휠 파일의 타임스탬프 기준)

2026-10-21 20:39:51 - 20:40:13

악성코드가 포함된 LiteLLM 1.107.0 휠 파일 7개가 PyPI에 업로드됨

2026-10-21 20:46:56

악성코드가 포함된 Docker 이미지 게시 및 latest, main-latest, main-stable 태그의 해당 이미지 연결

2026-10-21 20:50

GitHub에 v1.107.0 릴리스 게시

2026-10-21 20:53:49 - 20:54:01

공격자가 세 번째 개발자의 탈취된 자격 증명을 이용해 스테이징 및 프로덕션 워크플로 실행 기록 삭제

2026-10-21 21:06

GitHub 이슈 BerriAI/litellm#47826를 통해 LiteLLM 1.107.0 침해 사실 보고

2026-10-21 21:09 - 21:24

BerriAI가 무단 변경 사항을 제거하고 릴리스 워크플로를 정상 상태로 복원

2026-10-21 22:23

PyPI에서 LiteLLM 1.107.0 삭제 완료 확인

2026-10-21 22:51

GHCR의 관련 이미지 태그를 더 이상 사용할 수 없는 상태 확인. Docker Hub의 관련 태그는 악성 이미지 연결 상태 유지

2026-10-21 23:20

영향을 받은 Docker Hub 태그 전체에 대해 삭제 또는 정상 이미지로 연결 변경 완료

최종

GitHub 계정 letters9813 및 공격 서버 주소 전달용 저장소 pythonclient-test 삭제

공격 경로

  1. LiteLLM 개발자용 GitHub CLI 인증 토큰 세 개 탈취 (이 중 한 개는 Github 소유자 권한)

  2. 탈취된 Github 소유자 권한 토큰을 이용하여 Branch Protection 해제 및 변경 사항 Push

  3. 정상 레포지토리(BerriAi/litellm)를 악성 레포지토리(Berri-Ai/litellm)으로 변경

  4. 악성 아티팩트를 PyPI, Docker Hub, GHCR에 정식 릴리즈

영향 범위

20시 39분 ~ 22시 23분 (KST) 사이에 pip를 이용하여 LiteLLM을 설치했거나, 20시 46분 ~ 23시 20분 (KST) 사이에 v1.107.0,main-latest,main-stable 태그의 Docker 이미지를 사용했다면 해당 공격에 영향을 받는다.

단, LiteLLM의 기업용 버전을 사용중인 엔터프라이즈 유저라면 이번 사건의 영향을 받지 않는다.

영향 받는 패키지 및 파일들은 아래 표로 정리했다.

영향을 받은 패키지 목록

배포 패키지

버전·대상

영향

PyPI wheel

LiteLLM 1.107.0, 플랫폼별 7개

악성 파일 cook.pth, cook.py, sitecustomize.py 포함

PyPI 소스 배포본

litellm-1.107.0.tar.gz

pyproject.toml 변조. 악성 페이로드 파일은 없음

Docker 이미지 (Docker Hub·GHCR)

v1.107.0 및 악성 배포 기간 동안의 latest, main-latest, main-stable

악성코드 포함. GHCR의 litellm-database·litellm-non_root 이미지도 영향

영향 받은 파일 및 버전 목록

파일명

SHA-256

비고

litellm-1.107.0-cp310-abi3-macosx_10_12_x86_64.whl

7598727f209d717041db37f7dca271d3a7d328a279890e0e1d55375729aeb86d

악성 페이로드 포함

litellm-1.107.0-cp310-abi3-macosx_11_0_arm64.whl

0aaf7ba346d41ef2f40390436738b001180d5a1c03aa093f121078a9969d9a1a

악성 페이로드 포함

litellm-1.107.0-cp310-abi3-manylinux_2_28_aarch64.whl

668169d35b87bf51324080390b1b1c5ab12bd335cfe5f1a99e3689abd5e02ae6

악성 페이로드 포함

litellm-1.107.0-cp310-abi3-manylinux_2_28_x86_64.whl

462d0c9f67ca522d9e0e4acd245e90b36ce0d5353604a66bb7c43a1ec4a6fcf7

악성 페이로드 포함

litellm-1.107.0-cp310-abi3-musllinux_1_2_aarch64.whl

c2e32d0ce2548aa662c18bf5001911a79fe5b30cf8357132275add02fdcde054

악성 페이로드 포함

litellm-1.107.0-cp310-abi3-musllinux_1_2_x86_64.whl

1bbce8caa94f01c0aaa0b7ddae51553a8a32e1ce53d96d44fe583272aff7ad00

악성 페이로드 포함

litellm-1.107.0-cp310-abi3-win_amd64.whl

12d4ccc5c6f8d35cf4f2cf233b7f3e418e863e657d81ff5f5fc9e210005b9484

악성 페이로드 포함

litellm-1.107.0.tar.gz

2befe2a79fb4fbbd9a543b5b40b530c8cffa8771bab22b8fb22b2e4ae3b1f819

페이로드 파일 없음, pyproject.toml 변조

영향 받지 않은 패키지 목록

배포 패키지

버전·대상

확인 결과

LiteLLM (PyPI)

1.107.0rc1, 1.107.0rc2, 1.106.x, 1.105.x, 1.104.x, 1.103.x

검사한 wheel에서 이번 사건의 악성 파일·설치 흔적 미발견

LiteLLM 프리릴리스 (PyPI)

1.107.0.dev1~dev3

해당 분석에서 미검사. 영향 여부 미확인

litellm-proxy-extras · litellm-enterprise (PyPI)

0.4.108~0.4.110; 0.1.69.post2, 0.1.73.post1, 0.1.76.post1

최초 공개 분석에서 악성코드가 없는 것으로 보고됨

악성코드 분석

이번 공격은 LiteLLM의 빌드 과정에 악성 파일을 포함시킨 뒤 Python이 시작될 때 악성 파일이 실행되도록 구성한 공급망 공격이다. 악성코드는 개발 환경과 클라우드의 자격 증명을 수집하고 외부로 전송하며, 별도 백그라운드 프로세스를 통해 추가 Python 코드를 내려받아 실행할 수 있도록 작성되어 있다.

아래는 악성코드의 실행 동작 흐름을 요약 분석한 내용이다.

## PyPI sdist litellm 1.107.0
  
  [tool.maturin]
  manifest-path = "litellm-rust/crates/python-bridge/Cargo.toml"	  manifest-path = "litellm-rust/crates/python-bridge/Cargo.toml"
  module-name = "litellm.rust_bridge._native"	  module-name = "litellm.rust_bridge._native"
  python-source = "."	  python-source = "."
+ data = "cook"
  python-packages = ["litellm_cli"]	  python-packages = ["litellm_cli"]

## PyPI sdist litellm 1.107.0
  
  [tool.maturin]
  manifest-path = "litellm-rust/crates/python-bridge/Cargo.toml"	  manifest-path = "litellm-rust/crates/python-bridge/Cargo.toml"
  module-name = "litellm.rust_bridge._native"	  module-name = "litellm.rust_bridge._native"
  python-source = "."	  python-source = "."
+ data = "cook"
  python-packages = ["litellm_cli"]	  python-packages = ["litellm_cli"]

## PyPI sdist litellm 1.107.0
  
  [tool.maturin]
  manifest-path = "litellm-rust/crates/python-bridge/Cargo.toml"	  manifest-path = "litellm-rust/crates/python-bridge/Cargo.toml"
  module-name = "litellm.rust_bridge._native"	  module-name = "litellm.rust_bridge._native"
  python-source = "."	  python-source = "."
+ data = "cook"
  python-packages = ["litellm_cli"]	  python-packages = ["litellm_cli"]

pyproject.toml의 maturin 설정에 다음 항목을 추가하여 cook디렉터리의 파일이 wheel에 포함되도록 했다.




위 세 개의 파일이 /app/.venv/lib/python3.13/site-packages/패키지에 포함되어 CPython 인터프리터 프로세스와 함께 실행된다.

주요 악성 행위는 cook.pth, cook.py, sitecustomize.py 각 세 개의 파일에서 실행되며, 링크에서 코드를 확인 할 수 있다. 아래는 주요 악성 코드를 요약 분석한 내용이다.

cook.pth

## <strong>cook.pth</strong>
import cook
## <strong>cook.pth</strong>
import cook
## <strong>cook.pth</strong>
import cook

Python은 일반적인 초기화 과정에서 .pth 파일의 import 행을 실행한다. 따라서 LiteLLM을 직접 호출하지 않아도 해당 환경에서 Python을 시작하면 cook.py가 실행될 수 있다. pip나 Jupyter 를 통해서도 실행 트리거가 가능하며, 실행 이후 sitecustomize.py 파일에서 원격 코드 로더가 시작된다.

cook.py

<strong>## cook.py</strong>
import zlib as _3659944d
import base64 as _35100b45

exec(
    _3659944d.decompress(
        _35100b45.b64decode(
            'eNrdfWt327qu4Pf+Ck/XdCTv...[중간 생략]...fEnSdf8X7kPs7s='
        )
    ),
    {'__name__': 'p14c7d1bb'}
)
<strong>## cook.py</strong>
import zlib as _3659944d
import base64 as _35100b45

exec(
    _3659944d.decompress(
        _35100b45.b64decode(
            'eNrdfWt327qu4Pf+Ck/XdCTv...[중간 생략]...fEnSdf8X7kPs7s='
        )
    ),
    {'__name__': 'p14c7d1bb'}
)
<strong>## cook.py</strong>
import zlib as _3659944d
import base64 as _35100b45

exec(
    _3659944d.decompress(
        _35100b45.b64decode(
            'eNrdfWt327qu4Pf+Ck/XdCTv...[중간 생략]...fEnSdf8X7kPs7s='
        )
    ),
    {'__name__': 'p14c7d1bb'}
)

cook.py는 zlib으로 압축되고 Base64로 인코딩된 코드를 실행한다. 인코딩된 코드를 복원하면 공격자가 만든 정보 수집기인 privcollect 가 나타난다.

수집기는 아래의 주요 정보들을 수집하는 인포 스틸러(Info Stealer)로서 동작한다. 수집 동작은 아래와 같다.

  • 브라우저 데이터, SSH·GPG 개인키, 클라우드 자격 증명, CI/CD 설정, 환경변수와 AI 개발 도구의 인증 정보 등을 수집한다.

  • 리눅스에서 읽기 권한이 있는 다른 프로세스의 환경 변수에 주요 정보가 존재하면 수집한다.

  • DATABASE_URL 이 설정되어 있으면 Prisma를 통해 LiteLLM 데이터베이스에 접근하여 공급자 자격 증명과 모델 설정을 조회화고 수집한다.

최종적으로 수집 결과는 AES-256-CBC로 암호화하고, 암호화에 사용한 키는 RSA-4096 공개키와 OAEP 패딩으로 보호한다. 이후 hdr.json, data.bin, key.bin을 tar.gz로 묶어 hxxp://www[.]litellm[.]dev/healthcheck 에 HTTP POST 전송하고, 전송 성공 시 /tmp/.pc_once_72129118c59f5636c0bb 에 기록을 남긴다.

sitecustomize.py

fork,setsid를 이용해서 최초 Python 프로세스와 분리된 원격 코드 로더를 만든다. 로더는 아래의 과정을 3600초마다 반복한다.




조치 방안

해당 공격에 노출되었을 경우 다음과 같은 조치 이행을 권고한다.

  1. site-packages에서 cook.pth, cook.py, sitecustomize.py와 관련 __pycache__의 .pyc 파일 삭제

  2. 클라우드 키, SSH/GPG 키, 브라우저 비밀번호 및 세션, Github 및 AI 토큰, Kubernetes 및 CI 비밀 정보, 프로세스 환경 변수 등의 유출 데이터를 교체하거나 무효화

  3. LiteLLM DB, 공급자 API 키 및 마스터 키, salt key, virtual keys, DATABASE_URL_의 비밀번호 교체

  4. DNS·방화벽에서 litellm.dev, www.litellm.dev차단

  5. 감염 컨테이너 교체 후 v1.106.2 이미지를 digest로 고정하여 재배포

  6. 내부 이미지 레지스트리·이미지 캐시·PyPI 미러·캐싱 프록시에 남은 1.107.0 이미지와 wheel 삭제

  7. 가상환경을 새로 구성 후 litellm==1.106.2로 버전 고정

  8. /tmp/remote_code_loader.lock을 점유한 프로세스를 확인하여 종료


https://github.com/PetoWorks/Litellm.1.107.0-attack-checker
https://github.com/PetoWorks/Litellm.1.107.0-attack-checker
https://github.com/PetoWorks/Litellm.1.107.0-attack-checker

해당 스크립트는 감염 여부 및 유출 여부를 리눅스,윈도우에서 확인하는 스크립트이다.

악성 코드 해시, 악성 코드 유출 로그 파일(/tmp/.pc_once_72129118c59f5636c0bb), 1.107.0 버전의 LiteLLM 설치 및 캐시 흔적, 악성 Docker 이미지 설치 여부 등을 확인한다.

아래 명령으로 실행할 수 있다.

python3 -I -S
python3 -I -S
python3 -I -S

참고자료

https://docs.litellm.ai/blog/security-incident-oct-21-2026

https://www.stepsecurity.io/blog/litellm-1-107-0-compromised-pypi-backdoored-wheels-credential-stealer

https://github.com/BerriAI/litellm/blame/20535d8fa11f786a6c24df7488a0e449ed5f09ad/cook/purelib/sitecustomize.py


070-4110-1337
(Representative Number)


02-861-1337
(Invoice Inquiry)


02-861-1338 (Fax)

205-15 Gasan Digital 1-ro,
Geumcheon-gu, Seoul
Room 614, SH Dream Tower

We are waiting for
colleagues to research together

© PetoWorks Inc. 2025

070-4110-1337
(Representative Number)


02-861-1337
(Invoice Inquiry)


02-861-1338 (Fax)

205-15 Gasan Digital 1-ro,
Geumcheon-gu, Seoul
Room 614, SH Dream Tower

We are waiting for
colleagues to research together

© PetoWorks Inc. 2025

070-4110-1337
(Representative Number)


02-861-1337
(Invoice Inquiry)


02-861-1338 (Fax)

205-15 Gasan Digital 1-ro,
Geumcheon-gu, Seoul
Room 614, SH Dream Tower

We are waiting for colleagues to research together

© PetoWorks Inc. 2025