InvoiceShelf가 CVE-2026-55610에 대한 패치를 출시했습니다. 이는 한 회사의 소유자가 다른 회사의 사용자 계정을 탈취할 수 있는 심각한 결함입니다. CVSS 점수 8.7을 기록한 이 취약점은 앱의 Laravel 코드에서 테넌트 범위(tenant-scope) 확인이 누락되어 발생했습니다.

결함 작동 방식

InvoiceShelf는 Laravel 기반의 SaaS 도구로, 기업이 단일 대시보드에서 사용자, 인보이스 및 설정을 관리할 수 있게 해줍니다. 이 플랫폼은 테넌트를 식별하기 위해 커스텀 헤더를 읽습니다. 소유자(Owner)가 사용자 레코드를 요청하면, 코드는 "요청자가 자신의 회사의 소유자인가?"만을 확인합니다.

대상 사용자가 동일한 테넌트에 속해 있는지는 전혀 확인하지 않습니다. Laravel의 암시적 라우트 모델 바인딩(implicit route-model binding)은 사용자 ID를 글로벌 사용자 테이블의 행으로 연결하며, 권한 정책은 오직 요청자의 역할(role)만을 기준으로 요청을 승인합니다.

따라서 공격자는 다음과 같은 행위가 가능합니다:

  • 요청 URL에 임의의 숫자 사용자 ID를 제공합니다.
  • 이메일을 포함한 전체 사용자 레코드를 받습니다.
  • 업데이트를 실행하여 피해자의 이메일과 비밀번호를 덮어쓰고, 심지어 해당 계정을 공격자의 회사에 슈퍼 관리자(super-admin)로 재할당합니다.

실제로 악의적인 소유자는 기업 관리 도구를 범용 계정 탈취 무기로 변질시켰습니다. "소유자" 이상의 권한은 필요하지 않았습니다.

영향 범위

2.4.1 미만 버전을 사용하는 모든 InvoiceShelf 고객이 노출되었습니다. 이 결함은 핵심 요청 처리 경로에 존재하기 때문에, 규모나 보안 태세와 관계없이 어떤 테넌트든 다른 테넌트의 소유자로부터 공격 대상이 될 수 있었습니다. 그 영향으로는 기밀성 상실(이메일 주소) 및 무결성 상실(무단 비밀번호 변경, 슈퍼 관리자로의 권한 상승)이 포함됩니다.

패치 내용

개발자들은 버전 2.4.1을 출시하여 사용자 레코드에 대한 모든 읽기 또는 쓰기 작업 전에 명시적인 테넌트 확인 절차를 추가했습니다. 이 수정 사항은 쿼리의 범위를 활성 회사 식별자로 제한하여, Laravel이 요청자의 테넌트에 속한 행만 반환하도록 강제합니다.

개발자가 배워야 할 점

  • 멀티 테넌트 애플리케이션에서 글로벌 기본 키(primary keys)에 절대 의존하지 마십시오.
  • 삭제 또는 생성 작업뿐만 아니라 모든 데이터베이스 조회에 테넌트 필터를 적용하십시오.
  • 권한 정책이 행위자의 역할 뿐만 아니라 대상 객체의 테넌트 소속 여부도 함께 검증하도록 만드십시오.
  • 라우트 모델 바인딩과 같은 프레임워크의 암시적 기능은 명시적인 범위 지정(scoping)을 추가하지 않으면 보안 허점을 숨길 수 있는 편의 기능으로 취급해야 합니다.

향후 전망

이번 사건은 테이블을 공유하는 모든 SaaS가 직면할 수 있는 광범위한 위험을 보여줍니다. 보안 감사는 식별자를 허용하는 모든 엔드포인트를 검토하고 테넌트 범위 지정이 일관되게 적용되는지 확인해야 합니다.

핵심 요약: 단 한 번의 테넌트 확인 누락이 권한 있는 사용자 역할을 범용 백도어로 바꿀 수 있습니다. 적절한 범위 지정(scoping)은 선택 사항이 아닙니다. 이는 모든 멀티 테넌트 시스템에서 데이터 격리의 기초입니다.