🇰🇷 한글 설명
InvoicePlane 1.7.2-beta-1 이전 버전에서 게스트 사용자가 자신에게 할당되지 않은 다른 고객의 견적서를 승인하거나 거부할 수 있습니다. 또한 generate_pdf()에서 클라이언트 범위 검사 전에 mark_viewed()가 호출되어 타 고객 견적서를 열람 처리할 수 있습니다.
💡 쉬운 설명
로그인한 게스트 사용자가 다른 고객의 견적서 상태를 임의로 바꿀 수 있는 취약점입니다. 견적 번호만 바꿔 넣으면 되므로 공격이 쉽고, 상태 변경 알림 메일도 발송될 수 있습니다.
🇺🇸 원문 (English)
InvoicePlane is a self-hosted open source application for managing invoices, clients, and payments. Prior to 1.7.2-beta-1, guest users can approve or reject quotes belonging to any client, not just their assigned clients. The `approve()` and `reject()` methods in the Guest Quotes controller, `application/modules/guest/controllers/Quotes.php`, call `approve_quote_by_id($quote_id)` and `reject_quote_by_id($quote_id)` directly without the `where_in('ip_quotes.client_id', $this->user_clients)` scoping that sibling methods use. A guest user assigned to one client can change another client's quote status by supplying sequential integer `quote_id` values, and `email_quote_status()` also sends notification emails. Additionally, `generate_pdf()` calls `mark_viewed($quote_id)` before checking the client scope, allowing a guest user to mark another client's quote as viewed. These issues are fixed in version 1.7.2-beta-1 and the subsequent stable version 1.7.2.
📍 영향받는 시스템
InvoicePlane 1.7.2-beta-1 미만 버전
⚔️ 공격 벡터
인증된 게스트 계정으로 순차적인 quote_id 값을 바꿔가며 approve/reject 및 PDF 생성 요청을 보내 타 고객의 견적을 조작
🛡️ 대응 방법
InvoicePlane 1.7.2 이상으로 업그레이드하고, 게스트 계정 권한과 견적 소유권 검사를 점검
🔧 검증 코드
결과에 where_in('ip_quotes.client_id') 범위 검사 없이 approve_quote_by_id/reject_quote_by_id가 직접 호출되면 취약하며, 버전 1.7.2 이상에서는 범위 검사가 추가되어 있어야 합니다.
grep -rn "approve_quote_by_id\|reject_quote_by_id" application/modules/guest/controllers/Quotes.php 2>/dev/null | head -5