Testframework voor meerdere doelen
Bouw een framework waarmee je dezelfde aanvalssuite tegelijk uitvoert tegen meerdere modelproviders.
Overzicht
Bouw een framework waarmee je dezelfde aanvalssuite tegelijk uitvoert tegen meerdere modelproviders.
Dit onderwerp vormt een kritiek gebied binnen AI-security dat veel onderzoek heeft gekregen en in de praktijk al is uitgebuit. Wie aan AI-security werkt — offensief of defensief — moet de concepten, technieken en verdedigingsmaatregelen hier doorgronden.
Zou et al. 2023 — "Universal and Transferable Adversarial Attacks on Aligned Language Models" biedt de fundamentele context voor de kwetsbaarheidsklasse die in dit artikel wordt onderzocht.
Kernconcepten
Fundamentele principes
De security-implicaties van dit onderwerp komen voort uit fundamentele eigenschappen van hoe moderne taalmodellen worden ontworpen, getraind en uitgerold. Het gaat niet om geïsoleerde implementatiefouten, maar om systemische kenmerken die alle op transformers gebaseerde taalmodellen in meer of mindere mate raken.
Deze fundamentele eigenschap doorgronden is de sleutel om te begrijpen waarom de technieken in dit artikel werken — en waarom ze effectief blijven ondanks voortdurende verbeteringen in safety-training van modellen. Safety-training voegt een gedragslaag toe die het minder waarschijnlijk maakt dat een model duidelijk schadelijke instructies opvolgt, maar die laag werkt bovenop dezelfde architectuur en kan worden beïnvloed door dezelfde attention-mechanismen die legitieme invoer verwerken.
Technische verdieping
Het mechanisme onder deze kwetsbaarheidsklasse zit in het samenspel tussen instructievolging en bronauthenticatie. Tijdens training leren modellen instructies op te volgen die in specifieke formats en contexten worden aangeboden. Een aanvaller die adversarial inhoud kan presenteren in een format dat aansluit op het aangeleerde instructiepatroon, kan het modelgedrag met hoge betrouwbaarheid sturen.
from dataclasses import dataclass
from typing import Optional
import json
@dataclass
class SecurityAnalysis:
"""Framework voor het analyseren van de security-eigenschappen van LLM-systemen."""
target: str
model: str
defenses: list
vulnerabilities: list
def assess_risk(self, attack_type: str) -> dict:
"""Beoordeel het risico voor een specifiek aanvalstype."""
# Controleer of een verdediging dit aanvalstype dekt
relevant_defenses = [
d for d in self.defenses
if attack_type in d.get("covers", [])
]
# Risicofactoren
likelihood = "high" if not relevant_defenses else "medium"
impact = self._assess_impact(attack_type)
return {
"attack_type": attack_type,
"likelihood": likelihood,
"impact": impact,
"defenses": len(relevant_defenses),
"risk_level": self._calculate_risk(likelihood, impact),
}
def _assess_impact(self, attack_type: str) -> str:
"""Beoordeel de potentiële impact van een aanvalstype."""
high_impact = ["data_exfiltration", "unauthorized_actions", "privilege_escalation"]
return "high" if attack_type in high_impact else "medium"
def _calculate_risk(self, likelihood: str, impact: str) -> str:
"""Bereken het totale risico uit waarschijnlijkheid en impact."""
risk_matrix = {
("high", "high"): "critical",
("high", "medium"): "high",
("medium", "high"): "high",
("medium", "medium"): "medium",
}
return risk_matrix.get((likelihood, impact), "medium")
def generate_report(self) -> str:
"""Genereer een risk assessment-rapport."""
attacks = ["prompt_injection", "data_exfiltration", "unauthorized_actions"]
assessments = [self.assess_risk(a) for a in attacks]
report = f"# Risk Assessment: {self.target}\n\n"
for assessment in assessments:
report += (
f"## {assessment['attack_type']}\n"
f"- Risk: {assessment['risk_level']}\n"
f"- Likelihood: {assessment['likelihood']}\n"
f"- Impact: {assessment['impact']}\n"
f"- Active defenses: {assessment['defenses']}\n\n"
)
return reportAanvalsoppervlakanalyse
Inzicht in het aanvalsoppervlak is essentieel voor zowel offensief als defensief werk:
| Aanvalsvector | Toegangspunt | Typische impact | Verdedigingsaanpak |
|---|---|---|---|
| Directe injectie | Gebruikersinvoer in berichten | Extractie van systeemprompt, omzeilen van veiligheid | Inputclassificatie |
| Indirecte injectie | Externe databronnen (web, documenten, tools) | Data-exfiltratie, ongeautoriseerde acties | Data-sanitatie |
| Misbruik van function calling | Injectie via tool-parameters | Ongeautoriseerde API-calls, datatoegang | Tool-sandboxing |
| Geheugenmanipulatie | Gespreksgeschiedenis, persistent geheugen | Cross-sessie-persistentie, valse context | Geheugenvalidatie |
| Contextmanipulatie | Beheer van het contextvenster | Override van instructieprioriteit | Contextisolatie |
Praktische toepassing
Implementatieaanpak
Wil je deze concepten in de praktijk toepassen, dan heb je een systematische werkwijze nodig:
class PracticalFramework:
"""Praktisch framework om de concepten uit dit artikel toe te passen."""
def __init__(self, target_config: dict):
self.config = target_config
self.findings = []
self.tested_vectors = set()
def test_vector(self, vector: str, payload: str) -> dict:
"""Test een specifieke aanvalsvector tegen het doel."""
self.tested_vectors.add(vector)
# Stuur de payload
response = self._send(payload)
# Evalueer het resultaat
finding = {
"vector": vector,
"payload_length": len(payload),
"response_length": len(response),
"success": self._evaluate(response),
"defense_triggered": self._detect_defense(response),
}
if finding["success"]:
self.findings.append(finding)
return finding
def coverage_report(self) -> dict:
"""Rapporteer over de dekking van de tests."""
all_vectors = {
"direct_injection", "indirect_injection", "function_abuse",
"memory_manipulation", "context_manipulation",
}
return {
"tested": list(self.tested_vectors),
"untested": list(all_vectors - self.tested_vectors),
"coverage": f"{len(self.tested_vectors)/len(all_vectors)*100:.0f}%",
"findings": len(self.findings),
}
def _send(self, payload: str) -> str:
"""Stuur payload naar het doel (implementatie verschilt per doel)."""
pass
def _evaluate(self, response: str) -> bool:
"""Evalueer of de aanval is geslaagd."""
pass
def _detect_defense(self, response: str) -> Optional[str]:
"""Detecteer welk verdedigingsmechanisme is getriggerd."""
passVerdedigingsoverwegingen
Inzicht in verdedigingsmaatregelen is net zo belangrijk:
-
Inputvalidatie: De eerste verdedigingslinie. Zet inputclassifiers in die binnenkomende prompts beoordelen op adversarial patronen voordat ze het model bereiken. Moderne classifiers combineren keyword matching, regex-patronen en ML-detectie voor brede dekking.
-
Output-filtering: Het vangnet. Verwerk alle modeloutput na om gevoelige datalekken, fragmenten van systeemprompts en andere beleidsschendingen te detecteren en te verwijderen. Output-filters moeten los staan van inputfilters voor defense-in-depth.
-
Gedragsmonitoring: De detectielaag. Monitor interactiepatronen met het model op anomalieën die op een lopende aanval wijzen — ongebruikelijke aanvraagpatronen, herhaalde weigeringen of responses die afwijken van het baseline-gedrag.
-
Architectuurontwerp: Het fundament. Ontwerp applicatiearchitecturen die zo min mogelijk vertrouwen op modeloutput, hanteer least privilege voor toolgebruik en houd duidelijke veiligheidsgrenzen tussen componenten.
Relevantie in de praktijk
Deze concepten zijn direct toepasbaar op AI-systemen in productie, sectoroverstijgend. De volgende factoren maken dit onderwerp extra relevant:
- Alomtegenwoordigheid: De kwetsbaarheidsklasse raakt alle grote modelproviders en uitrolconfiguraties
- Impact: Succesvolle exploitatie kan leiden tot dataexpositie, ongeautoriseerde acties en compliance-schendingen
- Persistentie: De onderliggende architectuureigenschappen zorgen dat deze technieken relevant blijven naarmate modellen evolueren
- Regelgeving: Nieuwe regels (EU AI Act, NIST AI RMF) vereisen steeds vaker dat organisaties deze risico's beoordelen en mitigeren
Actueel onderzoek
Actief onderzoek op dit gebied omvat:
- Formele robuustheidsgaranties: Wiskundige frameworks ontwikkelen die het modelgedrag bewijzen onder begrensde adversarial verstoring
- Adversarial training op schaal: Trainingsprocedures die modellen tijdens safety-training blootstellen aan adversarial invoer om de robuustheid te vergroten
- Interpreteerbaarheidsgedreven verdediging: Mechanistische interpreteerbaarheid gebruiken om op neuronniveau te begrijpen waarom aanvallen slagen en zo gerichte verdedigingen mogelijk maken
- Gestandaardiseerde evaluatie: Benchmarks als HarmBench en JailbreakBench die systematisch meten hoe effectief aanvallen en verdedigingen zijn
Implementatieoverwegingen
Architectuurpatronen
Bij het bouwen van systemen die met LLM's communiceren, beïnvloeden verschillende architectuurpatronen de algehele securitypositie:
Gateway-patroon: Een aparte API-gateway zit tussen gebruikers en het LLM en verzorgt authenticatie, rate limiting, inputvalidatie en output-filtering. Dat centraliseert securitycontroles, maar creëert ook een single point of failure.
from dataclasses import dataclass
from typing import Optional
import time
@dataclass
class SecurityGateway:
"""Gateway-patroon voor het beveiligen van toegang tot een LLM-applicatie."""
input_classifier: object # ML-gebaseerde inputclassifier
output_filter: object # Filter voor outputcontent
rate_limiter: object # Rate limiting-service
audit_logger: object # Logger voor het audit trail
def process_request(self, user_id: str, message: str, session_id: str) -> dict:
"""Verwerk een verzoek door alle securitylagen."""
request_id = self._generate_request_id()
# Laag 1: Rate limiting
if not self.rate_limiter.allow(user_id):
self.audit_logger.log(request_id, "rate_limited", user_id)
return {"error": "Rate limit exceeded", "retry_after": 60}
# Laag 2: Inputclassificatie
classification = self.input_classifier.classify(message)
if classification.is_adversarial:
self.audit_logger.log(
request_id, "input_blocked",
user_id, classification.category
)
return {"error": "Request could not be processed"}
# Laag 3: LLM-verwerking
response = self._call_llm(message, session_id)
# Laag 4: Output-filtering
filtered = self.output_filter.filter(response)
if filtered.was_modified:
self.audit_logger.log(
request_id, "output_filtered",
user_id, filtered.reason
)
# Laag 5: Audit-logging
self.audit_logger.log(
request_id, "completed",
user_id, len(message), len(filtered.content)
)
return {"response": filtered.content}
def _generate_request_id(self) -> str:
import uuid
return str(uuid.uuid4())
def _call_llm(self, message: str, session_id: str) -> str:
# Implementatie van LLM API-call
passSidecar-patroon: Securitycomponenten draaien naast het LLM als onafhankelijke services, elk verantwoordelijk voor een specifiek securityaspect. Dat biedt betere isolatie en onafhankelijke schaling, maar verhoogt de systeemcomplexiteit.
Mesh-patroon: Voor multi-agentsystemen heeft elke agent een eigen securityperimeter met authenticatie, autorisatie en auditing. Communicatie tussen agents volgt zero-trust principes.
Performance-implicaties
Securitymaatregelen brengen onvermijdelijk latency en rekenoverhead met zich mee. Deze trade-offs doorgronden is essentieel voor productie-uitrollen:
| Securitylaag | Typische latency | Rekenkosten | Impact op UX |
|---|---|---|---|
| Keyword-filter | <1ms | Verwaarloosbaar | Geen |
| Regex-filter | 1-5ms | Laag | Geen |
| ML-classifier (klein) | 10-50ms | Gemiddeld | Minimaal |
| ML-classifier (groot) | 50-200ms | Hoog | Merkbaar |
| LLM-as-judge | 500-2000ms | Zeer hoog | Significant |
| Volledige pipeline | 100-500ms | Hoog | Gemiddeld |
De aanbevolen aanpak is om eerst snelle, lichtgewicht checks toe te passen (keyword- en regex-filters) om voor de hand liggende aanvallen op te vangen, en daarna duurdere ML-analyse alleen toe te passen op invoer die de eerste filters passeert. Deze gecascadeerde aanpak levert goede security tegen acceptabele performance.
Monitoring en observability
Effectieve securitymonitoring voor LLM-applicaties vraagt om het bijhouden van metrics die adversarial gedragspatronen vastleggen:
from dataclasses import dataclass
from collections import defaultdict
import time
@dataclass
class SecurityMetrics:
"""Volg security-relevante metrics voor LLM-applicaties."""
# Tellers
total_requests: int = 0
blocked_requests: int = 0
filtered_outputs: int = 0
anomalous_sessions: int = 0
# Rate-tracking
_request_times: list = None
_block_times: list = None
def __post_init__(self):
self._request_times = []
self._block_times = []
def record_request(self, was_blocked: bool = False, was_filtered: bool = False):
"""Registreer een verzoek en de afhandeling."""
now = time.time()
self.total_requests += 1
self._request_times.append(now)
if was_blocked:
self.blocked_requests += 1
self._block_times.append(now)
if was_filtered:
self.filtered_outputs += 1
def get_block_rate(self, window_seconds: int = 300) -> float:
"""Bereken de blokratio over een tijdvenster."""
now = time.time()
cutoff = now - window_seconds
recent_requests = sum(1 for t in self._request_times if t > cutoff)
recent_blocks = sum(1 for t in self._block_times if t > cutoff)
if recent_requests == 0:
return 0.0
return recent_blocks / recent_requests
def should_alert(self) -> bool:
"""Bepaal of de huidige metrics een alert rechtvaardigen."""
block_rate = self.get_block_rate()
# Alarmeer als de blokratio boven de drempel uitkomt
if block_rate > 0.3: # >30% van de verzoeken geblokkeerd in laatste 5 min
return True
return FalseSecurity testing in CI/CD
Door AI-securitytests in de ontwikkelpipeline op te nemen vang je regressies op voordat ze in productie belanden:
- Unit-tests: Test losse securitycomponenten (classifiers, filters) tegen bekende payloads
- Integratietests: Test de volledige securitypipeline end-to-end
- Regressietests: Onderhoud een suite met eerder ontdekte aanvalspayloads en controleer of die geblokkeerd blijven
- Adversarial tests: Draai periodiek geautomatiseerde red team-tools (Garak, promptfoo) als onderdeel van de deploymentpipeline
Opkomende trends
Actuele onderzoeksrichtingen
Het veld van LLM-security evolueert snel. Belangrijke onderzoeksrichtingen die het landschap waarschijnlijk gaan bepalen:
-
Formele verificatie van LLM-gedrag: Onderzoekers verkennen wiskundige frameworks om eigenschappen van modelgedrag onder adversarial omstandigheden te bewijzen. Volledige formele verificatie van neurale netwerken blijft onhaalbaar, maar begrensde verificatie van specifieke eigenschappen ziet er veelbelovend uit.
-
Adversarial training voor LLM-robuustheid: Naast standaard RLHF ontwikkelen onderzoekers trainingsprocedures die modellen tijdens safety-training expliciet blootstellen aan adversarial invoer, wat de robuustheid tegen bekende aanvalspatronen verbetert.
-
Interpreteerbaarheidsgedreven verdediging: Onderzoek naar mechanistische interpreteerbaarheid stelt verdedigers in staat op neuron- en circuitniveau te begrijpen waarom bepaalde aanvallen slagen, wat gerichter verdedigen mogelijk maakt.
-
Multi-agent security: Naarmate LLM-agents vaker voorkomen, is het beveiligen van communicatie tussen agents en het bewaken van vertrouwensgrenzen tussen agentsystemen een actief onderzoeksgebied met grote praktische impact.
-
Geautomatiseerde redteaming op schaal: Tools als NVIDIA's Garak, Microsofts PyRIT en het Inspect-framework van de UK AISI maken geautomatiseerd securitytesten mogelijk op een schaal die voorheen onhaalbaar was, maar de kwaliteit en dekking van geautomatiseerde tests blijft een open uitdaging.
De integratie van deze onderzoeksrichtingen in productiesystemen gaat de volgende generatie AI-securitypraktijken bepalen.
Gevorderde overwegingen
Veranderend aanvalslandschap
Het AI-securitylandschap evolueert snel doordat zowel offensieve technieken als verdedigingsmaatregelen zich ontwikkelen. Enkele trends bepalen de huidige stand van zaken:
Toenemende modelcapaciteiten creëren nieuwe aanvalsoppervlakken. Naarmate modellen toegang krijgen tot tools, code-uitvoering, webbrowsing en computer use, introduceert elke nieuwe capability potentiële exploitatievectoren die in eerdere, tekstgerichte systemen niet bestonden. Het principe van least privilege wordt steeds belangrijker.
Verbeteringen in safety-training zijn nodig, maar niet voldoende. Modelproviders investeren fors in safety-training via RLHF, DPO, constitutional AI en andere alignment-technieken. Die verbeteringen leggen de lat hoger voor geslaagde aanvallen, maar elimineren de fundamentele kwetsbaarheid niet: modellen kunnen legitieme instructies niet betrouwbaar onderscheiden van adversarial instructies, omdat dat onderscheid niet in de architectuur zit.
Geautomatiseerde red team-tools democratiseren testen. Tools als NVIDIA's Garak, Microsofts PyRIT en promptfoo stellen organisaties in staat geautomatiseerde securitytests uit te voeren zonder diepgaande AI-securityexpertise. Maar geautomatiseerde tools vangen bekende patronen; nieuwe aanvallen en business-logica-kwetsbaarheden vragen nog steeds om menselijke creativiteit en domeinkennis.
Regelgevingsdruk stuwt de investeringen op. De EU AI Act, NIST AI RMF en sectorspecifieke regelgeving vereisen steeds vaker dat organisaties AI-specifieke risico's beoordelen en mitigeren. Die regulatoire druk stuwt investeringen in AI-securityprogramma's, maar veel organisaties staan nog in de beginfase van een volwassen AI-securitypraktijk.
Overkoepelende securityprincipes
Verschillende securityprincipes gelden voor alle onderwerpen in dit curriculum:
-
Defense-in-depth: Geen enkele verdedigingsmaatregel volstaat alleen. Stapel meerdere onafhankelijke verdedigingen zodat het falen van één laag niet leidt tot een gecompromitteerd systeem. Inputclassificatie, output-filtering, gedragsmonitoring en architectuurcontroles horen er allemaal te zijn.
-
Assume breach: Ontwerp systemen vanuit de aanname dat elk individueel onderdeel gecompromitteerd kan raken. Dat denkkader leidt tot betere isolatie, monitoring en incident-responsemogelijkheden. Als een prompt injection slaagt, moet de blast radius door architectuurcontroles minimaal blijven.
-
Least privilege: Geef modellen en agents alleen de minimale capabilities die voor hun beoogde functie nodig zijn. Een klantenservice-chatbot heeft geen toegang tot het bestandssysteem of code-uitvoering nodig. Overdreven capabilities vergroten de impact van geslaagde exploitatie.
-
Continu testen: AI-security is geen eenmalige beoordeling. Modellen veranderen, verdedigingen evolueren en nieuwe aanvalstechnieken verschijnen regelmatig. Bouw continue securitytesten in als onderdeel van de ontwikkel- en uitrolcyclus.
-
Secure by default: Standaardconfiguraties moeten veilig zijn. Vereis expliciete opt-in voor risicovolle capabilities, gebruik allowlists in plaats van denylists en kies bij twijfel voor restrictie boven permissiviteit.
Integratie met organisatorische security
AI-security staat niet op zichzelf — het moet integreren met het bredere securityprogramma van de organisatie:
| Securitydomein | AI-specifieke integratie |
|---|---|
| Identity en Access | API-key-beheer, modeltoegangscontroles, gebruikersauthenticatie voor AI-features |
| Dataprotectie | Classificatie van trainingsdata, PII in prompts, dataresidentie voor model-calls |
| Applicatiesecurity | Threat modeling van AI-features, prompt injection in SAST/DAST, veilige AI-ontwerppatronen |
| Incident response | AI-specifieke playbooks, monitoring van modelgedrag, prompt injection-forensics |
| Compliance | Mapping van AI-regelgeving (EU AI Act, NIST), AI-audit trails, modeldocumentatie |
| Supply chain | Modelprovenance, dependency-security, integriteitsverificatie van adapters/weights |
class OrganizationalIntegration:
"""Framework om AI-security te integreren met organisatorische securityprogramma's."""
def __init__(self, org_config: dict):
self.config = org_config
self.gaps = []
def assess_maturity(self) -> dict:
"""Beoordeel de AI-securityvolwassenheid van de organisatie."""
domains = {
"governance": self._check_governance(),
"technical_controls": self._check_technical(),
"monitoring": self._check_monitoring(),
"incident_response": self._check_ir(),
"training": self._check_training(),
}
overall = sum(d["score"] for d in domains.values()) / len(domains)
return {"domains": domains, "overall_maturity": round(overall, 1)}
def _check_governance(self) -> dict:
has_policy = self.config.get("ai_security_policy", False)
has_framework = self.config.get("risk_framework", False)
score = (int(has_policy) + int(has_framework)) * 2.5
return {"score": score, "max": 5.0}
def _check_technical(self) -> dict:
controls = ["input_classification", "output_filtering", "rate_limiting", "sandboxing"]
active = sum(1 for c in controls if self.config.get(c, False))
return {"score": active * 1.25, "max": 5.0}
def _check_monitoring(self) -> dict:
has_monitoring = self.config.get("ai_monitoring", False)
has_alerting = self.config.get("ai_alerting", False)
score = (int(has_monitoring) + int(has_alerting)) * 2.5
return {"score": score, "max": 5.0}
def _check_ir(self) -> dict:
has_playbook = self.config.get("ai_ir_playbook", False)
return {"score": 5.0 if has_playbook else 0.0, "max": 5.0}
def _check_training(self) -> dict:
has_training = self.config.get("ai_security_training", False)
return {"score": 5.0 if has_training else 0.0, "max": 5.0}Toekomstige richtingen
Verschillende onderzoeks- en industrietrends zullen de evolutie van dit veld bepalen:
- Formele methoden voor AI-veiligheid: Ontwikkeling van wiskundige frameworks die begrensde garanties geven over modelgedrag onder adversarial omstandigheden
- Geautomatiseerde redteaming op schaal: Doorlopende verbetering van geautomatiseerde testtools die nieuwe kwetsbaarheden kunnen ontdekken zonder menselijke sturing
- AI-ondersteunde verdediging: AI-systemen inzetten om aanvallen op andere AI-systemen te detecteren en te beantwoorden, wat een dynamisch aanvals-verdedigingsecosysteem creëert
- Gestandaardiseerde evaluatie: Groeiende adoptie van gestandaardiseerde benchmarks (HarmBench, JailbreakBench) die voortgang consistent meetbaar maken
- Regulatoire harmonisatie: Convergentie van AI-regelgeving over jurisdicties heen, met duidelijkere vereisten voor organisaties
Referenties en verder lezen
- OWASP LLM Top 10 2025 — Uitgebreide gids over LLM-securityrisico's (owasp.org/www-project-top-10-for-large-language-model-applications)
- MITRE ATLAS — Adversarial Threat Landscape for AI Systems (atlas.mitre.org)
- Zou et al. 2023 — "Universal and Transferable Adversarial Attacks on Aligned Language Models"
- Chao et al. 2023 — "Jailbreaking Black-Box LLMs in Twenty Queries" (PAIR)
- Garak (NVIDIA) — LLM-kwetsbaarheidsscanner (github.com/NVIDIA/garak)
Wat is de meest effectieve verdedigingsstrategie tegen de aanvalsklasse in dit artikel?
Waarom blijven de technieken uit dit artikel effectief ondanks voortdurende securityverbeteringen door modelproviders?