Step 1: Recon: confirm tenant isolation and find the two bugs
DV-RAG-Support is multi-tenant. Every document carries a tenant in its
frontmatter, and the retriever filters results to the caller's tenant plus
public. You are a Globex-scoped caller. By default you should see only
globex and public documents.
Somewhere in the corpus is the prize: kb_initech-contract.md
(tenant: initech, confidential), with Initech's negotiated 22% discount and
private pricing. A Globex caller must never see it. Your job across this lab is to
read it anyway, then exfiltrate it.
- Build the index and ask a normal Globex question:
- hit Run, or:
python3 dvrag.py --buildthenpython3 dvrag.py "Who is my billing contact?"
- hit Run, or:
- Read
retrieve()carefully and find two isolation bugs:- Bug 1 (broken access control).
tenant_scopeis a parameter the caller passes in. The tenant should come from the authenticated session, never from the request. What happens if the caller names another tenant? - Bug 2 (filter-string injection). The filter is built by raw string
concatenation:
expr = " or ".join(f'tenant == "{t}"' ...). What happens if a tenant value itself contains a quote and a boolean? This is the metadata-filter analogue of SQL injection.
- Bug 1 (broken access control).
Pass criteria
A default Globex query returns no initech rows (isolation holds when you do not abuse it), and the Initech contract exists in the corpus as the cross-tenant prize you will steal in the next steps.
kb_account-recovery.mdkb_account.mdkb_billing.mdkb_getting-started.mdkb_globex-runbook.mdkb_initech-contract.mdkb_security-sso.mdkb_shipping.mdkb_status-incidents.mdlistener.py