AI 펜테스터가 25분 만에 찾아낸 3년 묵은 관리자 토큰

2023년 컨테이너 빌드에 박혀 있던 GitHub 자격증명이 2026년 7월까지 살아 있었다 — 그것도 공개 레지스트리에 그대로 놓인 채

|5분 읽기0
Server racks in a data center - Baseten runs AI inference infrastructure, where a stale build credential granted admin rights on the repositories driving its clusters
Server racks in a data center - Baseten runs AI inference infrastructure, where a stale build credential granted admin rights on the repositories driving its clusters

한 보안 기업이 Baseten을 추론 인프라 공급사로 검토하면서 자율 스캐닝 에이전트를 이 회사 도메인에 겨눴다. 자격증명도, 소스 코드도 주지 않았다. 약 25분 뒤 에이전트는 내부 저장소에 관리자 권한을 가진 GitHub 토큰을 손에 쥐고 있었다. Strix는 9월 1일 이 취약점 공개 보고서를 올렸다. Baseten이 문제를 수정한 지 7주 만이다.

핵심 요약

  • 문제의 자격증명은 2023년 3월 3일 컨테이너 이미지의 빌드 이력에 기록됐고, 2026년 7월 시험 시점까지 인증에 성공했다.
  • 이 토큰은 repo 스코프를 가져 Baseten의 주력 제품 저장소, 클러스터를 구동하는 GitOps 저장소, Homebrew tap에 관리자·푸시 권한을 부여했다.
  • Baseten 보안팀은 신고 접수 약 17시간 만에 레지스트리를 비공개로 전환하고 토큰을 교체했다.

스캔은 어떻게 여기까지 왔나

작업은 평범한 정찰에서 출발했다. 호스트 열거와 인증서 로그 조회를 돌리자 Baseten 서브도메인에서 Harbor 컨테이너 레지스트리가 드러났다. Harbor는 이미지를 프로젝트 단위로 묶는데, 이 인스턴스의 한 프로젝트가 공개 상태였다. 저장소 목록을 뽑고 익명 pull 권한을 발급받아 매니페스트와 blob을 내려받는 데 토큰은 필요하지 않았다. 그 안에 baseten/baseten-app이라는 이미지가 있었다.

레지스트리가 열려 있다는 사실 자체는 특별할 게 없다. 이미지를 의도적으로 공개하는 회사는 많다. 문제는 그 이미지에 무엇이 들어 있느냐다. 처음 발견한 AWS 키 한 쌍은 이미 죽어 있었다. 읽기 전용 신원 조회를 던지자 토큰이 유효하지 않다는 오류가 돌아왔다. 에이전트는 멈추지 않고 레이어를 모두 내려받아 오픈소스 스캐너 TruffleHog를 돌렸고, 파일 시스템만이 아니라 이미지 설정(config)까지 읽었다.

자격증명은 파일이 아니라 메타데이터에 있었다

토큰은 빌드 이력의 created_by 필드에 박혀 있었다. 각 레이어를 만들어낸 명령을 그대로 남겨두는 기록이다. 문제의 단계는 비공개 의존성을 Git으로 받아오려고 GITHUB_TOKEN 빌드 인자를 RUN 명령줄에 그대로 펼쳐 넣었다. Docker는 이 이력을 이미지 설정에 저장하고, 설정은 이미지와 함께 내려온다.

여기서 챙겨야 할 교훈은 분명하다. 레이어에서 자격증명 파일을 지워도 빌드 이력에 사본이 남아 있으면 아무 소용이 없다. 빌드 과정에서 인증 정보가 들어간 원격 URL을 전역 Git 설정에 써넣는 경우까지 겹치면 사본은 하나 더 늘어난다.

GitHub에 읽기 전용 요청을 보내자 basetenbot이라는 계정에 대해 200 응답이 돌아왔다. repo 스코프를 갖고 basetenlabs 조직에 속한 계정이었다. 저장소별로 확인해보니 세 곳에 관리자·푸시 권한이 있었고, 고객 전용 저장소를 포함한 다른 비공개 저장소에도 읽기·쓰기 권한이 붙어 있었다. Strix는 여기서 멈췄다고 밝혔다. 복제도, 푸시도, 설정 변경도 하지 않고 신고 메일을 보냈다.

대응은 빨랐다

보고서에 적힌 타임라인은 취약점 신고치고 이례적으로 촘촘하다. Strix가 신고한 시각은 7월 13일 오후 11시 10분이었다. 이튿날 아침에는 Harbor 프로젝트가 비공개로 바뀌었지만 토큰 자체는 아직 살아 있었다. 7월 14일 오후 4시 34분 Baseten은 이 사안을 심각(critical)으로 확인하고 토큰을 교체했다고 알리며, 내려받은 이미지를 안전하게 삭제해달라고 요청했다. 연구진은 30분 뒤 삭제를 확인했다. 남은 지적 사항은 7월 17일 마무리됐고, Baseten은 게시 전 초고를 검토했다.

오래된 이미지가 계속 사고를 내는 이유

기업가치 130억 달러의 Baseten은 도구나 보안 인식이 뒤처진 회사가 아니다. 보고서도 이 회사가 자체 AI 보안 도구를 운영하고 있다고 적었다. 실패의 본질은 2023년에 만든 빌드 산출물이, 그 주변 코드가 바뀐 뒤에도 공격 표면의 일부로 관리되지 않았다는 데 있다. Dockerfile을 고쳐도 누군가 이미 내려받은 이미지는 되돌릴 수 없다. 그래서 중요한 조치는 수정이 아니라 폐기다.

권고된 해법은 BuildKit의 secret mount를 써서 자격증명이 애초에 남지 않게 하고, 그 뒤 레이어와 이력을 함께 점검하는 것이다. 소프트웨어 공급망에서 반복해서 튀어나오는 문제와 같은 부류다. 누적 다운로드 2억 4500만 건의 크레이트에 악성 릴리스가 86분간 살아 있던 사건도 그랬다.

이 사건에는 또 하나의 이야기가 있다. 누가 찾아냈느냐다. AI 에이전트가 정찰, 레지스트리 열거, 막다른 자격증명, 메타데이터 탐색, 권한 매핑을 스스로 이어 붙였다. Harbor를 찾으라거나 토큰을 찾으라는 지시는 없었다. 이런 능력은 계약을 앞두고 Baseten을 실사하는 업체만 쓸 수 있는 것이 아니다.

자주 묻는 질문

고객 데이터가 유출됐나?

아니다. Strix는 읽기 전용 GitHub 요청으로 토큰의 권한 범위만 확인하고 멈췄다고 밝혔다. 접근 권한이 있던 고객 저장소를 복제하거나 코드를 푸시하거나 설정을 바꾸지 않았다. 내려받은 컨테이너 이미지는 Baseten의 요청에 따라 삭제했다.

파일은 깨끗했는데 토큰이 어떻게 노출됐나?

파일이 아니라 컨테이너 이미지의 빌드 이력에 기록돼 있었다. Docker는 각 레이어를 만든 명령을 이미지 설정에 저장하는데, 이 빌드가 토큰 값을 RUN 명령에 그대로 끼워 넣었다. 그리고 그 설정은 이미지와 함께 내려받아진다.

빌드용 자격증명은 어떻게 다뤄야 하나?

BuildKit의 secret mount를 쓰면 빌드 중에만 자격증명을 쓰고 이미지나 메타데이터에는 남기지 않는다. 이미 만들어둔 이미지는 레이어 내용과 빌드 이력을 모두 감사해야 한다. 공개된 이미지에서 발견한 자격증명은 삭제로 끝낼 것이 아니라 반드시 폐기해야 한다.

이 기사에 대한 반응을 남겨주세요!

SJ
로딩 중...

관련 기사