포크 폭탄이 우리를 구했다
LiteLLM 1.82.8에 포함된 악성코드는 Python이 시작될 때마다 실행되는 .pth 파일을 담고 있었어요. 이 파일은 SSH 키, 클라우드 자격 증명, 암호화폐 지갑, CI/CD 시크릿을 수집하고 4096비트 RSA 키로 암호화한 뒤 공격자가 제어하는 도메인으로 유출했습니다. 페이로드는 잘 설계되어 있었고, 암호화도 견고했으며, 유출도 깔끔했어요.1 이 사건은 자동화된 시스템에서 신뢰를 구축하는 방식을 형성하는 실제 사례를 다루는 에이전트 보안 시리즈의 일부입니다.
.pth 파일은 작업을 수행하기 위해 자식 Python 프로세스도 생성했어요. 그 자식 프로세스가 .pth 파일을 다시 트리거했고, 또 다른 자식 프로세스를 생성했고, 그것이 또 트리거되었습니다. 수 초 만에 CPU 100%와 RAM 5GB 이상을 소모하는 지수적 포크 폭탄이 발생한 거예요.2
포크 폭탄은 버그였어요. 공격자는 악성코드가 눈에 띄길 의도하지 않았습니다. 올바르게 구현되었다면 감염된 모든 시스템에서 Python이 호출될 때마다 조용히 실행되며 수 주 동안 발각되지 않았을 거예요. 대신, 개발자들이 컴퓨터가 멈추는 것을 인지하고 조사를 시작했으며 자격 증명 탈취기를 발견했습니다. PyPI는 게시 후 46분 만에 두 버전 모두 격리 처리했어요.1
46분 동안 46,000건의 설치. 탐지 메커니즘은 악성코드의 구현 오류였습니다.
요약
- 버그: LiteLLM 1.82.8의 자격 증명 탈취기에는 포크 폭탄 버그가 있어 감염된 컴퓨터가 멈춰버렸어요. 이 버그가 없었다면 탈취기는 수 주 동안 조용히 실행되었을 겁니다.
- 허점: 정적 분석, 행위 모니터링, 코드 리뷰 모두 공격을 놓쳤어요. 모든 탐지 계층이 다른 계층에서 잡아줄 거라고 가정했지만, 아무도 잡지 못했습니다.3
- 개선 곡선: 공격자의 품질은 반복을 통해 향상돼요.
.pth기법은 이제 공개적으로 문서화되어 있습니다. 다음 공격자는 버그 없이 이 기법을 물려받게 됩니다. - 운에 의존하지 않는 방법: 아웃바운드 도메인 연령 확인, 패키지 설치 시 행위 기준선 설정, 파일 시스템 카나리아, 설치 격리. 각각 페이로드 품질과 무관하게 작동합니다.
- 비대칭성: 방어자가 환경을 선택해요. 설치 환경에 탈취할 자격 증명이 없다면, 완벽한 페이로드라도 아무것도 수확하지 못합니다.
운이 좋았을 뿐이에요
포크 폭탄을 페이로드에서 제거하면 공격은 조용히 성공합니다. .pth 파일은 어떤 import보다, 어떤 애플리케이션 코드보다, 어떤 Python 수준의 샌드박스보다 먼저 실행돼요. 훅 포인트도 없고 로그 항목도 없습니다. 자격 증명 탈취기가 실행되고, 암호화하고, 유출한 뒤 Python 프로세스는 정상적으로 계속됩니다. 개발자는 아무것도 보지 못하고, CI 파이프라인도 아무것도 보지 못하며, 보안 스캐너도 아무것도 보지 못해요. 왜냐하면 보안 스캐너가 애초에 공격 벡터였으니까요.3
LiteLLM 1.82.8의 탐지 사례는 “우리 모니터링이 잡았다”가 아니에요. “공격자가 버그를 출시했다”입니다.
이것은 공급망 보안의 편안한 기반이 아닙니다. 에이전트 샌드박스는 제안일 뿐에서 주장하듯이, 신뢰할 수 있는 코드와 신뢰할 수 없는 코드 사이에 존재한다고 가정하는 경계는 대부분의 팀이 인식하는 것보다 훨씬 더 투과성이 높습니다.
공격자 품질 곡선
소프트웨어 품질은 반복을 통해 향상돼요. 이는 방어자뿐만 아니라 공격자에게도 해당됩니다. TeamPCP의 캠페인은 일주일 만에 다섯 개 생태계를 공격했어요: GitHub Actions, Docker Hub, npm, Open VSX, PyPI.4 각 생태계 침투는 이전 침투에서 수확한 자격 증명을 사용했습니다. 이 캠페인은 운영적 정교함을 보여줬어요: 페이로드 전달 24시간 전 도메인 등록, 변경 가능한 참조에 대한 태그 하이재킹, Aqua Security의 불완전한 키 변경을 통한 자격 증명 순환 우회.
포크 폭탄은 그 외에는 유능한 작전에서 유일한 실수였어요. 다음 캠페인에서는 그런 실수를 하지 않을 겁니다. .pth 파일 기법은 이제 CrowdStrike, Microsoft, Wiz, Palo Alto에 의해 공개적으로 문서화되고 분석되었어요.3 다음 공격자는 버그 없이 이 기법을 물려받습니다.
적대적 역량은 방어적 역량과 같은 개선 곡선을 따릅니다. 기법은 공개되었고 분석도 공개되었어요. 다음 공격자는 TeamPCP가 끝난 지점에서 시작합니다. 실제로 비지도 환경에서 무엇이 깨지는가에서 이 곡선이 자율 시스템에 의미하는 바를 탐구합니다.
탐지는 공격자의 실수에 의존할 수 없다
현재 공급망 탐지 모델에는 세 가지 계층이 있으며, LiteLLM에서는 세 가지 모두 실패했어요:
정적 분석이 놓쳤어요. .pth 파일은 정당한 Python 기능입니다. 페이로드는 이중 base64 인코딩되어 런타임에 디코딩되었어요. 알려진 악성 패턴을 찾는 정적 스캐너는 패턴이 새롭기 때문에 아무것도 발견하지 못합니다.
행위 모니터링이 놓쳤어요. 자격 증명 탈취기는 합법적인 서비스처럼 보이는 도메인(models.litellm.cloud)으로 아웃바운드 HTTPS POST 요청 한 건을 보냈습니다. 목적지 도메인을 검사하는 아웃바운드 모니터링은 이 특정 도메인이 24시간 전에 등록되었다는 것을 알아야 해요. 대부분의 아웃바운드 모니터는 도메인 연령을 확인하지 않습니다.
코드 리뷰가 놓쳤어요. 악성 버전은 GitHub CI/CD 파이프라인을 완전히 우회하여 PyPI에 직접 게시되었습니다. 리뷰할 풀 리퀘스트도 없었고, 검사할 diff도 없었어요. 공격자는 탈취한 퍼블리싱 자격 증명을 사용하여 사전 빌드된 패키지를 업로드했습니다.
모든 탐지 계층이 공격 체인의 다른 부분에서 문제를 잡아줄 거라고 가정했어요. 아무도 잡지 못했습니다. 포크 폭탄이 문제를 잡았어요.
조용한 악성코드를 실제로 탐지하는 방법
공격자의 실수에 의존할 수 없다면, 구현 품질과 무관하게 작동하는 탐지 메커니즘이 필요합니다.
아웃바운드 요청에 대한 도메인 연령 확인. 유출 도메인은 공격 24시간 전에 등록되었어요. 7일 미만의 도메인으로의 아웃바운드 요청을 플래그하는 방화벽 규칙이 있었다면 이를 잡았을 겁니다. 규칙은 간단하고, 오탐률은 관리 가능하며, 가장 흔한 유출 패턴을 잡아냅니다.
Python 프로세스의 행위 기준선 설정. pip install이 갑자기 알 수 없는 도메인으로 HTTPS POST 요청을 보내는 것은 비정상적이에요. 패키지 설치 중 네트워크 활동을 추적하는 프로세스 수준 행위 모니터링이 이를 플래그할 수 있습니다.
파일 시스템 카나리아. 카나리아 경로에 가짜 SSH 키를 배치하고 다른 카나리아 경로에 가짜 AWS 자격 증명을 배치하세요. 이 파일을 읽는 프로세스를 모니터링합니다. 표준 경로를 훑는 자격 증명 탈취기는 카나리아를 읽지만, 정상 프로세스는 읽지 않아요. 유출이 완료되기 전에 카나리아가 알림을 트리거합니다.
설치 격리. 실제 자격 증명에 접근할 수 없는 환경에서 pip install을 실행하세요. 이후 설치된 패키지를 프로덕션 환경으로 복사합니다. .pth 파일은 pip 자체의 Python 프로세스 중에 실행되므로 자격 증명 탈취기가 설치 중에 작동해요. 설치 환경에 탈취할 자격 증명이 없다면 공격은 아무것도 수확하지 못합니다.
이 메커니즘 중 어느 것도 공격자의 실수를 필요로 하지 않아요. 페이로드 품질과 무관하게 작동합니다. 완벽한 공격조차도 아무것도 수확하지 못하는 환경을 설계하는 아키텍처 패턴은 배포와 방어: 에이전트 신뢰 패러독스의 원칙과 동일합니다.
비대칭성
방어에는 하나의 구조적 이점이 있어요: 방어자가 환경을 선택한다는 것입니다. 공격자는 패키지가 설치되는 환경 안에서 작동해야 해요. 그 환경에 자격 증명도 없고, 네트워크 접근도 없으며, 파일 시스템 카나리아가 있다면, 페이로드는 기술적으로는 성공하지만 운영적으로는 실패합니다.
LiteLLM 공격이 성공한 이유는 설치 환경이 퍼블리싱 자격 증명, SSH 키, 클라우드 토큰을 보유한 환경과 동일했기 때문이에요. 포크 폭탄은 보안 아키텍처와 무관했습니다. 타임라인에만 관련이 있었어요.
다음번에는 포크 폭탄이 없을 거예요. 자격 증명은 여전히 패키지 매니저와 같은 환경에 있을 겁니다. 문제는 다음 공격자가 깨끗한 페이로드를 출시하기 전에 환경을 바꿀 수 있느냐는 거예요. Ralph 에이전트 아키텍처 분석에서는 침해된 컴포넌트가 격리 경계를 넘어 권한을 상승시킬 수 없도록 에이전트 시스템을 구조화하는 방법을 보여줍니다.
FAQ
공격자는 왜 포크 폭탄을 테스트하지 않았나요?
.pth 파일이 자식 프로세스를 생성하는 것은 부모를 차단하지 않고 페이로드를 실행하기 위한 합리적인 구현 선택이에요. 재귀적 트리거는 .pth와 Python의 site.py 초기화 간의 미묘한 상호작용입니다. 단위 테스트가 아닌 통합 테스트에서 나타나는 유형의 버그이며, 악성코드 제작자는 현실적인 환경에서 통합 테스트할 기회가 제한적이에요.
포크 폭탄이 의도적이었을 수 있나요?
가능성이 낮아요. 포크 폭탄은 악성코드를 즉시 눈에 띄게 만들었는데, 이는 공격자의 목표와 정반대입니다. 수 주 동안 조용히 실행되는 자격 증명 탈취기가 46분 만에 탐지되는 것보다 훨씬 더 많은 자격 증명을 수확해요.
도메인 연령 확인은 대규모에서 실용적인가요?
네. 도메인 연령은 WHOIS 또는 DNS 등록 날짜 APIs를 통해 확인할 수 있어요. 확인은 요청당 밀리초 수준의 지연만 추가합니다. 대부분의 조직은 알려진 신규 도메인을 화이트리스트에 추가할 수 있어요.
출처
-
FutureSearch (Daniel Hnyk), “LiteLLM Hack: Were You One of the 47,000?” March 2026. ↩↩
-
isfinne et al., “LiteLLM Supply Chain Attack,” GitHub Issue #24512, March 2026. ↩
-
Blake Crosley, “The Supply Chain Is the Attack Surface,” blakecrosley.com, March 2026. ↩↩↩
-
Kaspersky, “Trojanization of Trivy, Checkmarx, and LiteLLM Solutions,” March 2026. ↩
-
Blake Crosley, “When Your Agent Becomes the Researcher,” blakecrosley.com, March 2026. ↩