TL;DR

  • PostHog의 공개 설문 링크에서 실행되는 임의 자바스크립트가 로그인 세션을 악용해 피해자 계정의 최대 권한 개인 API 키를 생성할 수 있는 취약점임.
  • 취약점은 새 설문 소개 화면의 설명 필드가 서버에서 정화되지 않은 채 브라우저에서 HTML로 렌더링되는 경로에서 비롯됨.
  • Strix의 테스트에서 공격자는 API 키를 생성하고, 이를 사용해 계정 신원과 조직 소유자 멤버십을 확인했으며 고객 기록과 세션 녹화 메타데이터에도 접근함.
  • PostHog는 9월 2일 수정 사항을 병합해 소개 필드 정화와 공개 설문 격리를 적용했으며, 자체 호스팅 이용자는 서버 측 수정 사항이 배포에 포함됐는지 확인해야 함.
  • 해당 변경의 보안 검사와 단위·브라우저·엔드투엔드 테스트는 통과했지만 취약점을 놓쳤으며, PostHog는 악용 여부를 감사해 자체 테스트 외 악용 사례가 없음을 확인함.

취약점 발견 경위

  • Strix에서 오픈소스 도구인 PostHog를 보호하고 커뮤니티에 기여하기 위해 소스 코드를 Strix에 제공하고 보안 문제를 탐색함.
  • 광범위한 소스 코드 검토 중 Strix 에이전트가 설문 코드의 취약 가능성을 발견함. PostHog는 최근 첫 질문 전에 제목, 설명, ‘시작’ 버튼을 표시하는 선택형 소개 화면을 추가한 상태임.
  • 소개 화면 설명은 설문 API로 저장되고 브라우저 SDK에서 HTML로 렌더링됨. Strix 에이전트는 appearance.introScreenDescription이 API를 거쳐 저장된 뒤, 보고 전용 콘텐츠 보안 정책(Content Security Policy, CSP)만 적용된 공개 설문 페이지에서 배포된 posthog-js 번들의 dangerouslySetInnerHTML을 통해 렌더링되는 경로를 찾아 실제 SDK 번들을 사용하는 헤드리스 브라우저에서 동적으로 검증함.
  • Strix는 백엔드가 안전하지 않은 콘텐츠를 실제로 허용하는지 확인하기 위해 새 소개 필드와 기존 감사 인사 필드에 시험용 HTML을 넣고 PostHog 직렬화 결과를 검사함.
  • 기존 thankYouMessageDescription 필드에서는 이벤트 핸들러가 제거됨.
  • 새 introScreenDescription 필드에서는 이벤트 핸들러가 그대로 남음.
  • 취약한 경로는 posthog-js PR #4436으로 이어짐. 병합 커밋은 introScreenDescription에서 기존 dangerouslySetInnerHTML 렌더러로 이어지는 브라우저 경로를 추가했으며, 백엔드는 기존 설문 필드는 정화했지만 새 필드는 정화 대상에 포함하지 않음.
  • 이 변경은 8월 10일 posthog-js 1.415.0에 포함됨.
  • 공개 설문이 인증된 앱과 같은 출처(origin)의 us.posthog.com에서 호스팅된다는 점도 공격이 성립하는 조건임. 설문은 만든 계정에 속하지만, 설문에 삽입된 자바스크립트는 링크를 연 사용자의 인증된 세션으로 요청을 보낼 수 있음.

설문에서 API 키 생성까지

  • Strix와 함께 통제 가능한 두 계정을 사용해 재현함. 한 계정에서 설문을 만들고, 새 로그인 세션이 있는 다른 계정으로 설문을 열었으며, 삽입된 스크립트가 개인 API 키를 생성함.
  • 수신 결과에는 HTTP 201 응답과 와일드카드 권한 *가 기록됨.
  • 양성 결과인지 확인하기 위해 Strix는 새 키를 별도의 API 요청에 사용함. PostHog는 두 번째 계정의 신원과 조직 소유자 멤버십을 반환했으며, 응답에는 membership_level: 15가 포함됨.
  • 테스트 영상에서는 us.posthog.com의 평범한 ‘Help us improve’ 설문이 표시되고 시작 버튼은 누르지 않은 상태에서 API 키가 이미 생성되는 장면이 나타남.
  • 다른 테스트 설문에서는 계정 및 조직 정보, 고객 기록, 세션 녹화 메타데이터도 반환됨. 키와 계정 이메일, 기타 식별 정보는 공개된 결과에서 가려짐.
  • 피해자는 설문이 정상적으로 작동하는 것으로 보이는 동안 계정이 침해된 사실을 알아챌 방법이 없음.

PR의 여러 검사

  • 해당 PR에서는 CodeQL, Semgrep, Wiz SAST, Wiz Secret Scanner, Wiz Vulnerability Scanner, Wiz IaC Scanner, Wiz Data Scanner와 단위 테스트, 브라우저 테스트, 엔드투엔드 테스트를 실행함.
  • 명시된 보안 검사와 테스트는 모두 통과했지만 취약점은 탐지되지 않음.

수정 및 공개

  • PostHog는 9월 2일 병합한 수정 사항에서 소개 필드 정화를 추가하고, 호스팅 설문을 allow-same-origin 없이 샌드박스 처리해 설문 콘텐츠를 인증된 앱에서 격리함.
  • PostHog를 자체 호스팅하는 경우 배포 환경에 서버 측 수정 사항이 포함됐는지 확인해야 함.
  • PostHog는 이후 안전하지 않은 인라인 자바스크립트를 차단하는 엄격한 CSP를 배포함. 설문 전용 별도 도메인 사용은 여전히 검토 중임.
  • PostHog는 수정 대응이 신속했고 협업에 적극적이었음. PostHog 팀은 전체 설문을 감사해 자체 테스트 외에는 이 문제가 악용된 적이 없음을 확인함.
  • 공개 전 PostHog와 취약점 공개 절차를 조율하고 게시물 초안을 검토용으로 공유함.
  • PostHog를 실제로 사용하는 도구에서 문제를 찾아 실행 가능한 공격으로 검증하고, 수정할 팀에 세부 정보를 전달하는 것이 Strix를 만드는 이유임.