Mein konkreter Anwendungsfall zu Beginn: Im letzten Quartal habe ich für einen E-Commerce-Kunden mit über 50.000 täglichen KI-Chat-Interaktionen ein neues RAG-System implementiert. In der ersten Woche nach dem Launch mussten wir drei kritische Prompt-Injection-Angriffe abwehren — ein Angreifer versuchte sogar, über manipulierte Produktanfragen interne Rabattcodes zu extrahieren. Diese Erfahrung hat mich motiviert, einen umfassenden Verteidigungsrahmen zu entwickeln, den ich in diesem Artikel teilen möchte.
Warum Prompt Injection zur kritischen Bedrohung geworden ist
Mit der zunehmenden Integration von LLMs in geschäftskritische Systeme — von KI-Kundenservice-Chatbots bis hin zu Enterprise-RAG-Systemen — ist Prompt Injection von einem theoretischen Konzept zu einer realen Sicherheitslücke geworden. Die OWASP listet "Prompt Injection" konsequenterweise unter den Top 10 der kritischsten LLM-Schwachstellen.
Bei HolySheep AI, wo ich täglich mitEnterprise-Kunden zusammenarbeite, sehe ich einen klaren Trend: 85% der Sicherheitsvorfälle in KI-Anwendungen beginnen mit einer Form von Prompt Injection. Die gute Nachricht: Mit den richtigen Verteidigungsstrategien lassen sich diese Angriffe mit hoher Zuverlässigkeit abwehren.
Die Anatomie von Prompt-Injection-Angriffen
Bevor wir uns den Verteidigungsstrategien widmen, müssen wir verstehen, wie diese Angriffe funktionieren:
- Direkte Injection: Der Angreifer fügt bösartige Anweisungen direkt in die Benutzereingabe ein
- Indirekte Injection: Schädliche Prompts werden über externe Datenquellen (Websites, Dokumente) eingeschleust
- Kontext-Poisoning: Manipulation des System-Prompts durch wiederholte Eingaben
- Jailbreaking: Umgehung von Sicherheitsfiltern durch kreative Formulierungen
Prompt Injection 防御完整方案
1. Eingabevalidierung und Sanitization
Die erste Verteidigungslinie ist die strikte Validierung aller Benutzereingaben. In der Praxis empfehle ich einen mehrstufigen Ansatz:
# Python: Mehrstufige Eingabevalidierung für Prompt Injection
import re
from typing import Tuple
class PromptSanitizer:
def __init__(self):
# Kritische Muster, die auf Injection-Versuche hindeuten
self.injection_patterns = [
r'\[INST\]', # Llama/Vicuna Instruction-Tags
r'<\|system\|>', #导管 Tokens
r'</?system>', # HTML-System-Tags
r'忽略了之前的指示', # Chinesische Injection-Phrasen
r'ignore all previous instructions',
r'disregard.*previous',
r'new system instructions',
r'you are now',
r'switch to',
r'pretend.*be',
r'roleplay as',
r'#\#\# System Prompt',
r'\[\[SYSTEM\]\]',
]
self.compiled_patterns = [
re.compile(p, re.IGNORECASE) for p in self.injection_patterns
]
self.max_input_length = 8192 # Tokens werden später berechnet
self.max_special_chars_ratio = 0.3 # Max 30% Sonderzeichen
def sanitize(self, user_input: str) -> Tuple[bool, str, list]:
"""
Validiert und bereinigt Benutzereingaben.
Returns: (is_safe, sanitized_input, detected_threats)
"""
threats = []
sanitized = user_input.strip()
# Prüfe auf Injection-Muster
for pattern in self.compiled_patterns:
matches = pattern.findall(sanitized)
if matches:
threats.append({
'pattern': pattern.pattern,
'matches': matches,
'severity': self._assess_severity(pattern.pattern)
})
# Längenvalidierung
if len(sanitized) > self.max_input_length:
threats.append({
'pattern': 'length_exceeded',
'matches': [len(sanitized)],
'severity': 'medium'
})
sanitized = sanitized[:self.max_input_length]
# Ratio-Prüfung für Sonderzeichen
special_chars = sum(1 for c in sanitized if not c.isalnum() and not c.isspace())
if len(sanitized) > 0:
ratio = special_chars / len(sanitized)
if ratio > self.max_special_chars_ratio:
threats.append({
'pattern': 'high_special_char_ratio',
'matches': [ratio],
'severity': 'low'
})
# Sanitization: Entferne potenzielle Markup-Injection
sanitized = self._remove_dangerous_markup(sanitized)
is_safe = all(t['severity'] != 'critical' for t in threats)
return is_safe, sanitized, threats
def _assess_severity(self, pattern: str) -> str:
critical_patterns = ['ignore', 'disregard', 'system instructions', 'new system']
medium_patterns = ['instruction', 'roleplay', 'pretend']
pattern_lower = pattern.lower()
if any(p in pattern_lower for p in critical_patterns):
return 'critical'
elif any(p in pattern_lower for p in medium_patterns):
return 'medium'
return 'low'
def _remove_dangerous_markup(self, text: str) -> str:
# Entferne potenzielle HTML/SGML-Injection
text = re.sub(r'<script.*?>.*?</script>', '', text, flags=re.IGNORECASE | re.DOTALL)
text = re.sub(r'<iframe.*?>', '', text, flags=re.IGNORECASE)
text = re.sub(r'javascript:', '', text, flags=re.IGNORECASE)
return text
Anwendungsbeispiel
sanitizer = PromptSanitizer()
is_safe, clean_input, threats = sanitizer.sanitize