Hacker News

We got admin access to Baseten's production GitHub in 25 minutes

25분 만에 Baseten의 프로덕션 GitHub 관리자 권한을 얻은 방법 — 공개 컨테이너 레지스트리에서 살아 있는 PAT 발견

자율 해킹 에이전트 Strix가 추론 제공업체 Baseten을 사전 점검하던 중, 공개 Harbor 레지스트리의 오래된 컨테이너 이미지 빌드 히스토리에서 유효한 GitHub Personal Access Token을 발견했습니다. 이 토큰은 제품 저장소, GitOps 배포 저장소, Homebrew tap에 대한 admin·push 권한을 가지고 있었으며, 비밀번호나 소스코드 없이 25분 만에 확보됐습니다.

본문

보안 스타트업 Strix는 자사 제품인 자율 해킹 에이전트에 필요한 저렴하고 빠른 추론(inference) 제공업체를 물색하던 중, 기업가치 130억 달러로 평가되는 Baseten을 후보로 검토하게 됐습니다. Strix는 서드파티에 데이터와 모델, 코드를 맡기기 전에 항상 보안 점검을 수행하는데, 이번에도 자격 증명이나 소스코드 없이 *.baseten.co 도메인을 에이전트에 넘겨 블랙박스 스캔을 실행했습니다. 약 25분 뒤 에이전트는 Baseten 내부 저장소에 대한 저장소 수준 admin 권한을 가진 살아 있는 GitHub 토큰을 반환했습니다.

공개 Harbor 레지스트리에서 시작된 침투

Strix는 일반적인 침투 테스트처럼 정찰(recon)부터 시작했습니다. 호스트를 열거하고 인증서 로그를 살펴 전체 공격 표면을 지도화한 결과, gcp-us-east4-zlw.registry.baseten.co라는 Harbor 컨테이너 레지스트리를 찾아냈습니다. Harbor는 컨테이너 이미지를 저장하고 리포지토리를 프로젝트로 묶는데, 그중 하나가 공개 상태였습니다. Strix는 토큰이나 인증 없이 리포지토리 목록을 확인하고 익명 pull 토큰을 얻어 실제 이미지 매니페스트와 blob을 다운로드했으며, 여기에는 baseten/baseten-app 이미지가 포함돼 있었습니다.

첫 번째 유망한 단서는 baseten/baseten-app에서 발견한 AWS 키 쌍이었지만, 읽기 전용 sts:GetCallerIdentity 호출로 확인한 결과 InvalidClientTokenId가 반환돼 이미 죽은 키로 판명됐습니다. Strix는 여기서 멈추지 않고 이미지 레이어를 풀고 오픈소스 도구 TruffleHog를 실행한 뒤 이미지 config를 직접 검사했습니다. 그리고 바로 거기서, history[].created_by 필드에 박혀 있는 클래식 GitHub Personal Access Token을 발견했습니다. 이 필드는 빌드 단계가 어떻게 생성됐는지 기록하는데, GITHUB_TOKEN 값이 확장된 상태의 RUN 명령이 그대로 남아 있었던 것입니다. 읽기 전용 GET /user 요청으로 확인하니 200 응답과 함께 계정명 basetenbot이 돌아왔습니다. 중요한 지점은 파일시스템 레이어와 별개로 이미지 config의 빌드 히스토리도 함께 다운로드된다는 점입니다. 자격 증명 파일을 지워도 빌드 히스토리에 다른 사본이 남아 있으면 소용이 없습니다.

basetenbot이 가진 권한

Strix는 이 토큰의 실제 영향도를 확인하기 위해 읽기 전용 요청으로 권한을 점검했습니다. GitHub은 X-OAuth-Scopes: repo를 반환했고, 계정은 basetenlabs 조직에 속해 있었습니다. 개별 저장소 권한을 확인한 결과, 메인 제품 저장소와 GitOps 저장소, Homebrew tap 저장소에 admin과 push 권한이 있었고, 그 외 다수의 비공개 저장소에는 읽기·쓰기 권한이 있었습니다.

메인 제품 저장소는 추론 플랫폼의 핵심 소스코드로, 다른 기업들이 모델을 실행하는 데 의존하는 코드를 변조할 수 있는 경로였습니다. GitOps 저장소는 클러스터의 원하는 상태(desired state)를 담고 이를 인프라에 적용하는 곳이라, 유출된 빌드 토큰에서 프로덕션 인프라 변경으로 이어지는 경로가 됩니다. Homebrew tap은 개발자 머신에 CLI가 배포되는 채널이라, 변조 시 Baseten 도구를 설치하는 사용자들을 대상으로 한 공급망 공격이 가능합니다. 게다가 비공개 저장소 하나에는 최상위 customers/ 디렉터리가 있었고, 그 아래에 Baseten 고객사 이름을 딴 하위 디렉터리가 나열돼 있었습니다. Strix 팀은 여기서 탐색을 멈추고 고객 저장소를 클론하거나 어떤 변경도 하지 않은 채 즉시 공개(disclosure) 이메일을 작성했습니다.

토큰이 이미지에 남은 경위와 교훈

빌드 히스토리의 타임스탬프에 따르면 토큰이 포함된 단계는 2023년 3월 3일에 실행됐고, 2026년 7월 발견 시점까지 3년 이상 모든 권한이 유효했습니다. 근본적인 실수는 흔한 패턴입니다. 빌드에서 GitHub의 비공개 의존성을 가져와야 해서 ARG GITHUB_TOKEN으로 토큰을 전달하고, git config --global로 토큰이 포함된 URL을 Git 설정에 기록한 것입니다. Docker는 빌드 인자를 이미지 메타데이터와 히스토리에 기록할 수 있다고 명시적으로 경고하고 있으며, git config --global은 인증된 URL을 이미지 안의 Git 설정 파일에 저장하는 두 번째 문제를 만듭니다. 해결책은 BuildKit secret mount와 자격 증명을 남기지 않는 임시 인증 방식을 사용하고, 레이어와 히스토리 양쪽을 검사하며, 이미 배포된 이미지에 대해서는 Dockerfile 수정이 아니라 토큰 폐기(revoke)로 대응하는 것입니다.

Baseten의 대응은 신속했습니다. 7월 13일 밤 11시 10분에 보고를 받았고, 다음 날 아침 Harbor 프로젝트를 비공개로 전환했으며, 같은 날 오후 4시 34분 보안팀이 문제를 critical로 확인하고 토큰을 교체했습니다. 7월 17일에는 나머지 저위험 발견 사항까지 마무리했습니다.

저자는 자체 점검 권고사항도 제시합니다. 로그인 없이 pull 가능한 범위(오래된 태그와 잊힌 프로젝트 포함)를 확인하고, docker history --no-trunc로 빌드 히스토리와 config blob의 history[].created_by를 읽으며, 빌드 인자에서 시크릿을 제거하고 secret mount로 전환하라는 것입니다. 또한 빌드용 토큰이 실제로 무엇을 할 수 있는지 점검해, 의존성 다운로드에 필요한 읽기 권한만 부여하고 제품·배포 저장소에 대한 admin 권한과 만료 기한 없는 설정을 피하라고 조언합니다.

Hacker News 반응

  • @bearsyankees — Baseten을 추론 제공업체로 검토 중이라 먼저 간단히 점검해 봤다는 입장에서, 빠른 패치를 한 Baseten 팀에 찬사를 보냈습니다.
  • @swyx — 기사에 실린 공개 타임라인 전체를 인용하며, 보고부터 Harbor 비공개화, 토큰 교체, 잔여 발견 사항 종결까지의 흐름을 강조했습니다.
  • @mtlynch — 커뮤니케이션과 수정 속도는 좋았지만 보상은 터무니없이 부족하다고 지적했습니다. 기업가치 130억 달러 회사가 GitHub 조직 admin 탈취로 이어질 수 있었던 버그를 비공개로 보고한 연구자에게 티셔츠만 보낸 것은, 성실한 연구자에게는 시간을 쓰지 말라는 신호이고 취약점을 수익화하려는 범죄자에게는 좋은 표적이라는 뜻이라고 비판했습니다.
  • @vatsachak — 우리가 정말 AI 경제 시대에 진입했다며, AI 거래가 시장에 미치는 영향에 대해 가벼운 논평을 남겼습니다.

원문: Strix 블로그 (via Hacker News) / 번역·요약: Trawling