
Plausible Analytics master d44e104 - 높음 - 원격 - 권한 잔여 - 편집자 인원 HTML 유출 전송 nanoid
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · plausible-editor-invite
Plausible Analytics 커뮤니티 에디션, GitHub master d44e104ae3943a9240d5cb6b62e67dff0f069d3a (2026-10-16) - Plausible Insights OÜ
분류: 권한 잔여물(초대 토큰 유출). 도달 범위: 원격(해당 사이트의 게스트 편집자 또는 팀 편집자).
Sites.list_people/1은 원시 guest_invitations.invitation_id와 team_site_transfers.transfer_id를 선택합니다. settings_people.html.heex는 모든 대기 중인 행에 대해 해당 21자 nanoid를 id="invitation-#{invitation.invitation_id}"에 넣습니다. People 설정은 SiteController의 @special_cased_actions에 없으므로 AuthorizeSiteAccess가 :editor를 허용합니다. 게스트 편집자는 사이트 역할 :editor에 매핑됩니다. 게스트 뷰어는 404를 받습니다.
Nanoid.generate/0은 초대에서 등록할 때의 베어러입니다. 인증 없는 GET /register/invitation/:invitation_id는 id로만 조회합니다. LiveView register는 게시된 이메일을 invitation.email로 덮어씁니다. 기본 CE는 DISABLE_REGISTRATION=invite_only이고 ENABLE_EMAIL_VERIFICATION=false입니다. 수락은 citext 이메일 일치를 통한 POST /sites/invitations/:id/accept입니다.
이미 People HTML을 볼 수 있는 게스트 편집자가 대기 중인 소유권 이전 nanoid를 읽고, 초대받은 사람으로 등록한 뒤 수락합니다. 사이트가 공격자의 개인 팀으로 이동합니다.
| ID | 아직 CVE 없음 |
| CWE | CWE-200 / CWE-269 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L |
| 제품 | Plausible Analytics |
| 영향받음 | GitHub master d44e104ae3943a9240d5cb6b62e67dff0f069d3a (2026-10-16). 마지막 CE 태그 v3.2.1 (e4f5a87a5570bd61605217e7ceb376636db8eddb, 2026-05-15)은 다섯 달 뒤처져 있습니다. SECURITY.md는 운영자에게 :latest를 실행하라고 안내합니다. 핀은 현재 HEAD입니다. CE MIX_ENV=ce는 lib/만 컴파일합니다. |
| 인증 | 인증된 게스트 편집자(:guest_member, :editor) 또는 해당 사이트의 팀 편집자. 인증 없음 아님. 게스트 뷰어 아님. |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1:18180 (http) 18181 (postgres) 18182 (clickhouse http) 전용 |
Plausible Analytics leftovers의 잔여물 #1. 동일 핀, 다른 팩: plausible-traffic-notify (PUT traffic-change-notification site_id 대량 할당). 이 팩은 대기 중인 소유권 이전을 탈취하는 쪽입니다.
대기 중인 게스트 초대 및/또는 소유권 이전이 있는 사이트의 인증된 게스트 편집자 또는 팀 편집자. 일반 세션 쿠키가 필요합니다. 소유자, 관리자, 슈퍼 관리자 LiveView는 필요 없습니다. 21자 nanoid를 무차별 대입하지 않습니다. 로드가 허용된 HTML에서 이를 읽은 뒤 초대받은 사람으로 등록합니다.
권한 표(전수). Signal-Server Dropwizard admin과 동일한 기준: 메서드 + 경로, 해당 호출이 부여하는 것, 정찰 대 무결성 대 가용성, 랩에서 입증된 것 대 추론된 것, 닫힌 채로 유지되는 인접 표면.
| 축 | 메서드 + 경로 | 부여되는 것 | 출처 |
|---|---|---|---|
| 정찰 | 게스트/팀 편집자로서 GET /:domain/settings/people | 대기 중인 행이 id="invitation-<nanoid>"를 렌더링한다. Nanoid는 invitation_id 또는 transfer_id이다. 동일 사이트에 한한다. 초대받은 사람의 이메일도 테이블에 있다. | 실험실에서 입증됨. 편집자 people 200이 nanoid Hc8DiBC2q08mv5LFmBysu를 유출함 |
| 정찰 | 인증 없는 GET /register/invitation/:id | 등록 폼에 초대받은 사람의 이메일이 표시된다. 조회는 id로만 이루어진다(find_by_id_unified). | 실험실에서 입증됨. 등록 HTML에 [email protected]가 표시됨 |
| 무결성 | /register/invitation/:id에서의 LiveView register | 게시된 user[email]이 invitation.email로 덮어쓰여진다. 초대받은 사람 주소로 새 CE 계정이 생성된다. 기본 CE 이메일 인증은 꺼져 있다. 초대 전용 모드에서도 :invitation은 여전히 허용된다. | 실험실에서 입증됨. [email protected]를 게시했으나 저장된 이메일은 [email protected]였음 |
| 무결성 | 해당 새 계정으로 POST /sites/invitations/:id/accept | 대기 중인 소유권 이전이 sites.team_id를 newowner 개인 팀으로 옮긴다. 이전 행은 사라진다. | 실험실에서 입증됨. sites.team_id 1 → 2 |
| 무결성 | 해당 이메일에 대한 대기 중인 게스트 초대에 동일한 accept 적용 | 해당 사이트에 새 멤버십이 생성된다(편집자 대 편집자는 이득이 아님). 해당 이메일에 대한 다른 대기 중인 팀/게스트/이전 행들도 수락 가능해진다. | 소스 (InvitationController.accept_invitation) |
| 가용성 | 이전 accept 이후 | 원래 팀은 사이트를 잃는다. 통계는 새 팀에서 계속 제공된다. | 실험실에서 입증됨. team_id 이동됨 |
이 핀에서는 닫혀 있는 항목
| 축 | 메서드 + 경로 | 닫혀 있는 이유 |
|---|---|---|
| 정찰 | 게스트 뷰어 GET /:domain/settings/people | 404. 뷰어는 :editor가 아니다. 실험실에서 입증됨. |
| 무결성 | 유출된 transfer id에 대한 편집자의 POST /sites/invitations/:id/accept | 이메일 불일치. 편집자는 [email protected]가 아니다. 사이트는 팀 1에 그대로 남는다. 실험실에서 입증됨. |
| 무결성 | 유효한 초대 id 없이 인증 없는 등록 | check_registration_enabled(:default) 대 :invitation. whoareme Bug 02, 패치됨. |
| 정찰 | 21자 nanoid 무차별 대입 | URL 안전 알파벳, 21자. 이 잔여 사항의 범위를 벗어남. |
| 정찰 | ClickHouse 이벤트, SMTP, 다른 사이트의 people 페이지 | 동일 사이트에 한함. ClickHouse 관리자 권한 없음. 메일함 읽기 없음. |
| 무결성 | 소유자/관리자 초대 및 이전 | 그들은 이미 할 수 있다. 이 잔여 사항은 할 수 없는 편집자에 관한 것이다. |
| 무결성 | 슈퍼 관리자 LiveView, OS 셸, extra/lib EE SSO | 닫힘. CE 실험실. 셸 없음. |
나는 이미 등록된 사용자에 대한 인증 없는 계정 탈취, 리버스 셸, 또는 ClickHouse 덤프를 주장하지 않는다. High 사례는 기본 CE에서 대기 중인 소유자 이전(또는 해당 이메일에 대한 다른 사이트/팀으로의 초대)이다: 초대 전용에 이메일 인증 꺼짐. EE는 항상 email_verified: false를 설정하며 /activate는 초대받은 사람의 메일함을 필요로 한다.
whoareme Bug 02(2026-05-22 공개)는 유효한 초대 없이 초대 전용 LiveView 등록을 닫았고, Shield/Goal site_id 대량 할당도 닫았다. 나는 그럼에도 현재 master를 그대로 두고 살펴보았다. SECURITY.md는 최신 MAJOR.MINOR만 패치하며 운영자에게 :latest를 실행하라고 안내한다. 마지막 CE 태그 v3.2.1은 HEAD보다 다섯 달 뒤처져 있다.
나는 nanoid invitation_id가 데이터베이스를 떠나는 모든 지점을 읽었다. accept와 register는 이를 베어러로 취급한다. People 설정은 이를 삭제 버튼의 HTML id=에 넣는다. 삭제는 소유자/관리자 전용이다. id=는 그렇지 않다. 편집자가 페이지를 로드한다.
run.sh는 plausible-lab:d44e104ae3943a가 없으면 핀을 클론하고, DISABLE_REGISTRATION=invite_only로 compose를 올리고, 소유자 / 편집자 / 뷰어 / 대기 중인 이전을 시드한 다음, people HTML을 비교한다.
이미 기록된 잘못된 방향들: 게스트 등록을 자동 수락으로 취급함(로그인 후 POST /sites/invitations/:id/accept가 필요함); 유출된 transfer에 대한 편집자의 accept를 탈취로 취급함(이메일 불일치, 이동 없음); CE login_ip=5 분당으로 인한 로그인 429(사용자당 하나의 세션 유지); 뷰어가 people을 읽을 수 있다고 주장함(404). 연극일 뿐이다.
python3 plausible-editor-invite-Abraxas-Labs.py
또는
cd lab
./run.sh
오직 http://127.0.0.1:18180만 대상으로 합니다. 이미지 plausible-lab:d44e104ae3943a (MIX_ENV=ce, pin d44e104ae3943a9240d5cb6b62e67dff0f069d3a). Docker가 필요합니다. 첫 실행 시 해당 SHA에서 https://github.com/plausible/analytics를 클론하고 이미지를 빌드합니다. 런처는 lab/로 chdir한 뒤 run.sh를 exec합니다.
IOC editor-people-leak invitation-id=Hc8DiBC2q08mv5LFmBysu
IOC viewer-people http=404
IOC register-email-overwrite [email protected] [email protected]
IOC editor-accept-no-move team_id=1
IOC newowner-accept team_id 1 -> 2
SUCCESS plausible-editor-invite PLAUSIBLE-H02-EDITOR-INVITE-TOKEN-WITNESS
Witness 문자열: PLAUSIBLE-H02-EDITOR-INVITE-TOKEN-WITNESS. 오라클은 수락 후의 people HTML nanoid와 sites.team_id입니다.
편집자가 로드할 수 있는 HTML에 bearer nanoid를 넣지 마세요. People 설정에서 행을 invitation_id / transfer_id가 아닌 서버 측 id로 키를 지정하거나, DOM용으로 해시할 수 있습니다. 실제 토큰은 소유자/관리자 삭제 폼에만 유지하세요.
편집자 뷰를 위해 Sites.list_people/1에서 원시 invitation_id / transfer_id를 선택하는 것을 중단하세요. 편집자가 대기 중인 테이블을 필요로 하지 않는다면, danger-zone이 이미 그런 것처럼 People을 소유자/관리자로 권한 부여하세요.
초대에서 등록할 때, 새 계정을 CSS id에도 존재하는 nanoid가 아닌 일회용 해시 토큰에 바인딩하세요.
패치된 빌드에 대해 loopback 클라이언트를 다시 실행하세요: 편집자 people HTML에는 invitation-<21-char>가 포함되어서는 안 됩니다. People에만 존재했던 토큰에 대한 Newowner 수락은 실패해야 합니다.