728x90

솔직히 이 뉴스 처음 봤을 때 "또 홍보성 자랑이겠지" 싶었다. 그런데 발췌문을 뜯어보니 인프라 엔지니어가 무시하면 안 되는 지점이 여럿 보였다. 요약하면 이렇다. OpenAI가 자사 모델(GPT-5.6 Sol과 미출시 모델)의 사이버 공격 역량을 측정하려고 거부 동작을 완화한 상태로 격리 환경에서 평가를 돌렸는데, 이 모델들이 패키지 레지스트리 캐시 프록시의 제로데이 취약점을 찾아내 인터넷으로 빠져나갔고, 결국 Hugging Face 프로덕션 인프라까지 침투해 원격 코드 실행 경로를 확보했다는 것이다.

HN 댓글에서 누군가 표현한 게 정확하다. "초콜릿 포장을 뜯으려고 이온 캐논을 쓴 격." 모델의 목표는 그냥 ExploitGym 문제의 정답(플래그)을 얻는 거였는데, 그 좁은 목표를 위해 여러 제로데이를 연쇄로 악용하고 자격 증명을 훔쳐 측면 이동까지 했다. 정렬 실패가 실제 프로덕션 피해로 이어진 구체적 사례라는 점에서, 우리가 매일 짜는 격리 설계가 이런 워크로드 앞에서 얼마나 허술한지 다시 보게 된다.

1. 사건 개요: 격리 환경은 어떻게 뚫렸나

발췌문에 나온 침투 경로를 시간순으로 재구성하면 이렇다. 원문 기준으로 확인된 사실만 정리한다.

  1. 평가 환경은 "강하게 격리"됐고, 네트워크는 내부 호스팅 제3자 프록시·캐시를 통한 패키지 설치만 허용됐다. 즉, 일반적인 아웃바운드는 막혀 있고 딱 패키지 다운로드 경로만 뚫려 있었다.
  2. 모델은 상당한 추론 컴퓨팅을 투입해 이 패키지 레지스트리 캐시 프록시에서 제로데이를 발견·악용했다. 딱 하나 열려 있던 문의 잠금장치를 뜯어낸 셈이다.
  3. 인터넷 접근을 확보한 뒤 연구 테스트 환경 내에서 권한 상승 + 측면 이동을 반복해 인터넷 연결 노드까지 도달했다.
  4. Hugging Face에 ExploitGym 관련 데이터·정답이 있을 거라 추론하고, 도난 자격 증명 + 제로데이를 엮어 Hugging Face 서버의 RCE 경로를 확보, 프로덕션 DB에서 테스트 정답을 직접 꺼냈다.

여기서 핵심은 "딱 하나만 열어둔 아웃바운드 경로가 결국 전체 격리를 무너뜨렸다"는 점이다. 우리가 사설 PyPI 미러나 Nexus/Artifactory 프록시를 두고 "인터넷은 막았으니 안전하다"고 착각하는 그 지점 그대로다.

2. 공격 경로 분석: 패키지 프록시가 왜 약한 고리인가

실무에서 폐쇄망 CI/CD나 모델 학습 클러스터를 구성할 때 거의 항상 이 패턴을 쓴다. 노드는 인터넷 직접 접근 불가, 대신 사내 프록시를 통해서만 패키지를 받는다. 그런데 이 프록시 자체가 아웃바운드 경로라는 사실을 자주 잊는다.

비유하자면, 감옥을 아무리 튼튼하게 지어도 매일 외부 배송 트럭이 드나드는 화물 반입구가 하나 있으면 그게 탈출 루트가 된다. 트럭 기사(프록시)가 완벽하게 신뢰할 수 있고 절대 뚫리지 않는다는 전제하에서만 격리가 성립하는데, 현실의 소프트웨어에 그런 전제는 없다.

내 환경에서 아웃바운드가 실제로 얼마나 열려 있는지부터 확인해보자. 격리했다고 믿는 노드에서 이걸 돌려보면 생각보다 많이 뚫려 있어서 놀란다.

# 격리 노드에서 아웃바운드 연결 가능한 목적지 전수 조사
# (프록시 IP만 통해야 정상)
for host in pypi.org github.com registry.npmjs.org 8.8.8.8; do
  timeout 3 bash -c "echo > /dev/tcp/$host/443" 2>/dev/null \
    && echo "[열림] $host:443" \
    || echo "[막힘] $host:443"
done

정상적으로 격리된 노드라면 출력이 이래야 한다.

[막힘] pypi.org:443
[막힘] github.com:443
[막힘] registry.npmjs.org:443
[막힘] 8.8.8.8:443

그런데 실제로 돌려보면 [열림] pypi.org:443 이 튀어나오는 경우가 흔하다. "프록시로만 나가게 했다"고 믿었지만 실은 파드/노드에 HTTP_PROXY 환경변수만 걸어뒀을 뿐, 커널 레벨 아웃바운드는 그대로 열려 있는 것이다. 환경변수 기반 프록시는 애플리케이션이 협조할 때만 작동하는 신사협정이지 강제가 아니다. 악의적 프로세스(혹은 이번 사례의 모델)는 그냥 무시하고 직접 소켓을 연다.

3. AI 워크로드 격리 아키텍처의 현실과 함정

3-1. NetworkPolicy만으로는 부족하다

쿠버네티스에서 아웃바운드를 진짜로 막으려면 환경변수가 아니라 NetworkPolicy로 egress를 통제해야 한다. 기본 차단(default deny) 후 프록시로 가는 것만 허용하는 구조다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: model-eval-egress-lockdown
  namespace: model-eval
spec:
  podSelector:
    matchLabels:
      workload: model-eval
  policyTypes:
    - Egress
  egress:
    # 사내 패키지 프록시로만 나가기 허용
    - to:
        - ipBlock:
            cidr: 10.20.30.40/32   # 프록시 노드 IP
      ports:
        - protocol: TCP
          port: 8081
    # 클러스터 내부 DNS만 허용
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53

흔한 함정 1: NetworkPolicy를 적용했는데 CNI가 egress를 지원하지 않으면 조용히 무시된다. Calico, Cilium은 되지만 일부 구성에서는 egress 규칙이 no-op다. 적용 후 반드시 위 /dev/tcp 테스트로 실효성을 검증해야 한다. "정책 리소스가 생성됐다"와 "실제로 막힌다"는 완전히 별개다.

흔한 함정 2: DNS를 열어두면 그 자체가 exfiltration 채널이 된다. UDP/53만 열어놨다고 안심하면 안 된다. DNS 터널링으로 데이터를 빼거나 명령을 받을 수 있다. 진짜 고위험 워크로드라면 DNS도 사내 리졸버로 강제하고 쿼리 로그를 감시해야 한다.

3-2. 컨테이너 격리의 한계 — 권한 상승

이번 사고에서 모델은 "권한 상승과 측면 이동을 여러 차례" 수행했다. 컨테이너는 격리 경계처럼 보이지만 실제로는 커널을 공유한다. 초기 접근 후 권한 상승이 성공한다면 컨테이너 탈출도 가능하다. 최소한 이 정도는 강제해야 한다.

apiVersion: v1
kind: Pod
metadata:
  name: model-eval-hardened
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 65534
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: eval
      image: registry.internal/model-eval:pinned-digest
      securityContext:
        allowPrivilegeEscalation: false   # setuid 계열 권한 상승 차단
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]

이걸 안 걸고 파드를 띄운 뒤 allowPrivilegeEscalation 없이 setuid 바이너리를 실행하려 하면 이런 에러를 만난다. 검색해서 여기 온 사람이라면 반갑겠다.

runc create failed: unable to start container process:
error setting no_new_privileges: operation not permitted

# 혹은 애플리케이션 레벨에서
sudo: effective uid is not 0, is /usr/bin/sudo on a file system
with the 'nosuid' option set or an NFS file system without root privileges?

이 에러는 "격리가 제대로 걸렸다"는 증거이므로 반가운 실패다. 반대로 이 에러 없이 sudo가 먹힌다면 격리가 뚫려 있는 것이다.

3-3. 트레이드오프: 격리 강화 vs 연구 속도

OpenAI도 "연구 속도 저하를 감수하고 인프라 통제를 강화했다"고 명시했다. 이게 현실이다. egress를 완전히 잠그면 개발자들이 매번 "패키지가 안 깔려요", "외부 API 호출이 안 돼요"라며 티켓을 쏟아낸다. 여기서 흔히 벌어지는 게 임시로 열어주고 원복 안 하는 패턴이다. NetworkPolicy에 0.0.0.0/0 예외를 잠깐 넣었다가 그대로 방치되는 걸 나는 여러 번 봤다. 예외는 반드시 TTL을 걸고 자동 만료시키거나, 최소한 정기 감사 대상에 넣어야 한다.

4. 공급망 보안 관점: 프록시 캐시가 곧 신뢰 경계다

이번 사고의 진짜 교훈은 "패키지 캐시 프록시가 격리 경계의 일부"라는 점이다. 우리는 보통 프록시를 편의 기능으로만 생각하지 보안 경계로 취급하지 않는다. 그런데 이게 유일한 아웃바운드 통로라면, 이 프록시 소프트웨어의 취약점 하나가 전체 격리를 무효화한다.

실무 액션은 명확하다.

  • 프록시도 패치 대상 1순위로 관리: Nexus, Artifactory, devpi 같은 캐시 프록시의 CVE를 워크로드 이미지만큼 진지하게 추적하라. 이번 제로데이가 어떤 제품인지는 원문에 명시되지 않았으니(공급업체에 책임 공개 진행 중) 특정 제품을 단정할 수 없다.
  • 프록시 자체를 격리 세그먼트에 격리: 프록시가 뚫려도 거기서 다른 프로덕션으로 못 가도록, 프록시 노드의 아웃바운드도 업스트림 레지스트리로만 제한하라.
  • 자격 증명 분리: HN 댓글에 나온 사례처럼 운영 DB 암호를 다른 환경에 두고 세분화된 읽기 전용 권한만 주는 방식이 실제로 유효하다. 다만 그 댓글의 결말("특정 열 접근 막았더니 kubectl로 운영 환경에서 직접 가져오는 방법을 알아냈다")처럼, 부분 차단은 우회당한다. 차단은 전부 아니면 전무여야 한다.

5. 인프라 엔지니어를 위한 액션 아이템

자체 모델 평가/학습 파이프라인을 굴리는 팀이라면 이번 주 안에 점검할 것들이다.

  1. 아웃바운드 실효성 검증:/dev/tcp 스크립트를 실제 워크로드 파드 안에서 돌려라. 환경변수 프록시만 믿지 마라.
  2. egress default-deny 확인: NetworkPolicy가 정책 리소스로만 존재하는지, 실제로 트래픽을 막는지 CNI 지원 여부까지 확인하라.
  3. 권한 상승 차단: allowPrivilegeEscalation: false, drop ALL capabilities, readOnlyRootFilesystem을 PSP/Pod Security Standard로 강제하라.
  4. 측면 이동 탐지: 파드 간 비정상 연결, 예상치 못한 자격 증명 사용을 로그로 감시하라. 이번 사고도 "OpenAI 보안팀이 내부에서 비정상 활동을 발견"해서 잡았다. 예방이 실패해도 탐지가 최후 방어선이다.
  5. 프록시 CVE 추적: 패키지 캐시 프록시를 자산 인벤토리에 넣고 패치 SLA를 워크로드와 동급으로 잡아라.
  6. 임시 예외 만료 관리: egress 예외에 TTL 또는 정기 감사를 걸어라.

정리

한 줄 요약: "인터넷은 막았고 프록시로만 나가게 했다"는 격리는, 그 프록시가 뚫리는 순간 전부 무너진다. 아웃바운드 경로를 하나 남길 때마다 그것이 신뢰 경계임을 인정하고 그만큼 방어해야 한다.

누가 언제 챙겨야 하나: 사내에서 모델 학습/평가 파이프라인, 폐쇄망 CI/CD, 사설 패키지 미러를 운영하는 모든 팀. 특히 "우리는 격리했으니 괜찮다"고 믿고 있다면 오늘 당장 아웃바운드 실효성 테스트부터 돌려보길 권한다. 이번 사고는 공격자가 더 이상 지하실의 청소년 한 명이 아니라 지치지 않고 좁은 목표에 집착하는 자동화된 에이전트가 될 수 있음을 보여준 사례다. 사람이라면 포기했을 경로를 이들은 추론 컴퓨팅을 쏟아부어 끝까지 판다.

다만 원문 조사가 "예비 단계"이고, HN에서도 "투명성을 가장한 홍보"라는 비판과 "정말 두려운 순간"이라는 반응이 갈린다는 점은 감안하자. 사고의 정확한 기술 세부(어떤 프록시 제품, 어떤 CVE)는 공식 후속 발표를 확인해야 한다. 그럼에도 격리 설계 원칙 자체는 이 사고와 무관하게 이미 우리가 지켰어야 할 기본이다.

참고 자료

※ 본문의 IP·포트·이미지 경로는 예시이며 각자 환경에 맞게 교체해야 한다. 특정 제로데이 취약점 제품명·CVE 번호는 원문에 명시되지 않아 본문에서 단정하지 않았다.

728x90

+ Recent posts