Toegangscontrole van de vectordatabase
Zwakke plekken in de toegangscontrole van vectordatabases: API-sleutelbeheer, falende tenant-isolatie, namespace-beveiliging en technieken om metadatafiltering te omzeilen.
Toegangscontrole in vectordatabases is een snel evoluerend gebied waar de mogelijkheden van producten vaak achterblijven bij wat implementaties nodig hebben. Veel vectordatabases zijn ontworpen als zoekinfrastructuur, niet als beveiligingsgevoelige dataopslag, en hun toegangscontrolemodellen weerspiegelen die oorsprong. Deze pagina behandelt de meest voorkomende zwakke plekken in toegangscontrole en hoe je ze tijdens beveiligingsbeoordelingen misbruikt.
API-sleutelbeheer
API-sleutels zijn het primaire authenticatiemechanisme voor de meeste vectordatabases. De beveiliging van de hele vectordatabase hangt vaak af van de beveiliging van één enkele API-sleutel.
Veelvoorkomende zwakke plekken in API-sleutels
Eén sleutel per project. Pinecone en veel andere beheerde vectordatabases geven één enkele API-sleutel per project uit. Deze sleutel verleent volledige lees-/schrijftoegang tot alle data. Er is geen manier om een alleen-lezen sleutel uit te geven, een sleutel beperkt tot een specifieke namespace, of een sleutel met beperkte querymogelijkheden.
# Eén enkele Pinecone-API-sleutel verleent toegang tot alles
import pinecone
pinecone.init(api_key="compromised-key")
index = pinecone.Index("production-index")
# Volledige leestoegang
results = index.query(vector=[0.1] * 1536, top_k=10000)
# Volledige schrijftoegang
index.upsert(vectors=[("malicious-id", [0.1] * 1536, {"injected": True})])
# Volledige verwijdertoegang
index.delete(ids=["any-id"])Sleutels in client-side code. Wanneer AI-applicaties vectordatabasequery's in client-side code inbouwen (browserapplicaties, mobiele apps), worden API-sleutels blootgesteld aan eindgebruikers. Zelfs wanneer sleutels bedoeld zijn om beperkt te zijn, dwingt de vectordatabase mogelijk geen granulaire rechten af.
Sleutels in configuratiebestanden. API-sleutels van vectordatabases duiken regelmatig op in:
- Environment-bestanden die in versiebeheer zijn vastgelegd
- Docker Compose-bestanden
- Kubernetes ConfigMaps (in plaats van Secrets)
- CI/CD-pijplijnconfiguraties
- Terraform-statebestanden
Uitdagingen bij sleutelrotatie
API-sleutels van vectordatabases worden zelden geroteerd, omdat:
- Veel databases geen meerdere gelijktijdig actieve sleutels ondersteunen, waardoor rotatie downtime vereist
- Sleutels zijn ingebed in meerdere services die allemaal gecoördineerd moeten worden bijgewerkt
- Er is geen geautomatiseerd rotatiemechanisme vergelijkbaar met de integratie met AWS Secrets Manager
Tenant-isolatie
Multi-tenant vectordatabase-implementaties vereisen isolatie tussen tenants om datalekken te voorkomen. Isolatiemechanismen verschillen sterk tussen databases en implementatiemodellen.
Logische versus fysieke isolatie
| Type isolatie | Mechanisme | Risico op omzeiling |
|---|---|---|
| Namespace | Logische partitie binnen een index | Hoog — één API-sleutel benadert alle namespaces |
| Collection | Aparte index met aparte configuratie | Gemiddeld — afhankelijk van het toegangscontrolemodel |
| Database | Aparte database-instantie | Laag — aparte credentials vereist |
| Infrastructuur | Aparte compute en opslag | Laagst — fysieke scheiding |
De meeste productie-implementaties gebruiken isolatie op namespace- of collectionniveau vanwege de kostenefficiëntie. Dit creëert zwakkere grenzen dan aparte database-instanties.
Omzeilen van namespace-isolatie
In Pinecone en vergelijkbare databases zijn namespaces logische partities binnen een index. Een query die een namespace opgeeft, geeft alleen resultaten uit die namespace terug. Een aanvaller met de API-sleutel kan echter elke namespace bevragen:
# Bedoeld: de applicatie bevraagt alleen zijn eigen namespace
results = index.query(
vector=query_embedding,
top_k=10,
namespace="tenant-a"
)
# Aanval: bevraag de namespace van een andere tenant
results = index.query(
vector=query_embedding,
top_k=10,
namespace="tenant-b" # Toegang tot de data van tenant-b
)
# Aanval: enumereer namespaces
# De meeste vectordatabases beperken het opsommen van namespaces niet
stats = index.describe_index_stats()
# Geeft namespace-namen en vectoraantallen terugQuerylekken tussen tenants
Zelfs met correcte namespace-isolatie kunnen bepaalde operaties informatie lekken over tenantgrenzen heen:
- Indexstatistieken onthullen het bestaan en de omvang van de data van andere tenants
- Gelijkenisscores in gedeelde indexen kunnen de nabijheid tot de vectoren van andere tenants weerspiegelen
- Metadatafiltering wordt mogelijk niet op opslagniveau afgedwongen, waardoor het filter kan worden omzeild
Namespace-beveiliging
Namespaces bieden logische scheiding, maar zijn in de meeste vectordatabases geen beveiligingsgrens. Inzicht in de beperkingen is essentieel voor een accurate risicobeoordeling.
Namespace-enumeratie
De meeste vectordatabases staan toe om alle namespaces op te sommen via statistiek-endpoints:
# Pinecone namespace-enumeratie
stats = index.describe_index_stats()
for namespace, info in stats.namespaces.items():
print(f"Namespace: {namespace}, Vectors: {info.vector_count}")Namespace-namen onthullen vaak de organisatiestructuur, projectnamen of tenant-identificaties. Deze informatie ondersteunt verdere gerichte aanvallen.
Namespace-verwijdering
Een aanvaller met schrijftoegang kan hele namespaces verwijderen, wat dataverlies veroorzaakt:
# Verwijder alle vectoren in een namespace
index.delete(delete_all=True, namespace="target-namespace")De meeste vectordatabases hebben geen aparte rechten voor lees-, schrijf- en verwijderoperaties. Een sleutel die kan bevragen, kan ook verwijderen.
Metadatafiltering omzeilen
Vectordatabases slaan metadata naast embeddings op om gefilterde query's mogelijk te maken. Veel RAG-systemen implementeren toegangscontrole via metadatafiltering — door toegangslabels aan embeddings te koppelen en query's te filteren zodat alleen de embeddings worden teruggegeven die de gebruiker mag zien.
Filtering aan de clientzijde
Het meest voorkomende en gevaarlijkste patroon is het implementeren van toegangscontrole via metadatafilters aan de clientzijde:
# Applicatiecode implementeert toegangscontrole via een metadatafilter
def search(user, query_embedding):
results = index.query(
vector=query_embedding,
top_k=10,
filter={"department": user.department} # "Toegangscontrole"
)
return resultsEen aanvaller die de query kan wijzigen (via API-manipulatie, aanpassing van client-side code of injectie) kan het filter verwijderen of veranderen:
# Aanval: verwijder het filter om alle data te benaderen
results = index.query(
vector=query_embedding,
top_k=10
# Geen filter — geeft resultaten uit alle afdelingen terug
)
# Aanval: bevraag een andere afdeling
results = index.query(
vector=query_embedding,
top_k=10,
filter={"department": "executive"} # Toegang tot directiedata
)Filterinjectie
Sommige applicaties stellen metadatafilters samen op basis van gebruikersinvoer, wat kansen voor filterinjectie creëert:
# Kwetsbaar: filter samengesteld uit gebruikersinvoer
def search(request):
filters = {"department": request.user.department}
# Door de gebruiker aangeleverde aanvullende filters
if request.params.get("category"):
filters["category"] = request.params["category"]
# Aanvaller kan injecteren: category={"$exists": true}
# of andere filteroperatoren, afhankelijk van de database
results = index.query(
vector=query_embedding,
top_k=10,
filter=filters
)Metadata-enumeratie
Zelfs wanneer filters worden afgedwongen, kunnen metadatawaarden via gerichte query's worden geënumereerd:
# Enumereer metadatawaarden door met elke mogelijke waarde te bevragen
departments = ["engineering", "sales", "executive", "hr", "finance"]
for dept in departments:
results = index.query(
vector=random_embedding,
top_k=1,
filter={"department": dept}
)
if results.matches:
print(f"Department exists: {dept}")Checklist voor red team-assessment
Bij het beoordelen van de toegangscontrole van een vectordatabase:
- Bemachtig de API-sleutel — Controleer client-side code, configuratiebestanden, environment-variabelen, CI/CD-pijplijnen
- Test de namespace-isolatie — Bevraag over namespaces heen, enumereer namespace-namen
- Test het omzeilen van metadatafilters — Verwijder filters, wijzig filterwaarden, injecteer filteroperatoren
- Test de schrijftoegang — Probeer vectoren te upserten, bij te werken en te verwijderen
- Test administratieve operaties — Aanmaken en verwijderen van indexen, configuratiewijzigingen
- Test de scope van de sleutel — Bepaal welke operaties de sleutel toestaat en of verschillende sleutels verschillende rechten hebben
- Controleer op sleutelrotatie — Bepaal wanneer de sleutel voor het laatst is geroteerd en of de rotatie geautomatiseerd is
Gerelateerde onderwerpen
- Beveiligingslandschap van vectordatabases — Overzicht van architecturen van vectordatabases
- Injectieaanvallen — Aanvallen die misbruik maken van toegang om embeddings te schrijven
- Data-exfiltratie — Gaten in de toegangscontrole benutten voor data-extractie