+ Hinweise verwendet: {currentHint.hintsUsed} | Abzug: {currentHint.totalPointsDeducted} Punkte
+
+)}
+```
+
+**6. Start Timer on Mount**
+```jsx
+useEffect(() => {
+ participantAPI.executeLessonAction(eventLessonId, 'start-timer', {
+ stepId: 'xss-demo'
+ });
+}, []);
+```
+
+**7. Lock Previous Button (LessonView.jsx)**
+```jsx
+const [completedInteractive, setCompletedInteractive] = useState(false);
+
+// After interactive step
+if (currentStep.type === 'interactive' && !completedInteractive) {
+ setCompletedInteractive(true);
+}
+
+
+```
+
+## API Endpoints to Add
+
+The backend module methods need to be exposed via `executeLessonAction`:
+
+### In lesson controller (already supports executeLessonAction):
+```javascript
+// Actions to handle:
+- 'start-timer' â module.startStepTimer(participantId, stepId)
+- 'get-hint' â module.getHint(participantId, stepId)
+- 'test-xss' â module.testXSSPayload(participantId, payload, stepId)
+- 'add-comment' â module.addComment(participantId, author, content, stepId)
+```
+
+## Testing Steps
+
+1. â Backend module created with all tracking
+2. âł Rebuild backend container
+3. âł Update XSSDeeplinkDemo.jsx
+4. âł Update ForumScriptDemo.jsx
+5. âł Update LessonView.jsx
+6. âł Rebuild frontend container
+7. âł Test in browser:
+ - Timer counts down
+ - Progress updates when discovering variants
+ - Hints work with point deduction
+ - Free hints visible
+ - Previous button locks after interactive step
+
+## File Locations
+
+- Backend: `/backend/lessons/modules/xss-comprehensive/index.js` â
+- Frontend Demos:
+ - `/frontend/src/components/lessons/InteractiveContent/XSSDeeplinkDemo.jsx` âł
+ - `/frontend/src/components/lessons/InteractiveContent/ForumScriptDemo.jsx` âł
+- Lesson View: `/frontend/src/pages/LessonView.jsx` âł
+
+## Next Steps
+
+1. Update controller to expose hint and timer endpoints
+2. Implement frontend components with new UI
+3. Test complete workflow
+4. Verify point deductions work correctly
+5. Confirm timer enforcement
diff --git a/XSS_LESSON_MERGE.md b/XSS_LESSON_MERGE.md
new file mode 100644
index 0000000..1388f93
--- /dev/null
+++ b/XSS_LESSON_MERGE.md
@@ -0,0 +1,128 @@
+# XSS Lessons Merge - Summary
+
+## Changes Made
+
+Successfully combined the two XSS lessons into a single comprehensive lesson:
+
+### New Files Created
+
+1. **Backend Config:**
+ - `/backend/lessons/configs/xss-comprehensive.yaml`
+ - Combines content from both `xss-deeplink-demo.yaml` and `script-injection-forum.yaml`
+ - Duration: 35 minutes (combined from 20 + 25)
+ - Total points: 100 (distributed across 4 questions)
+
+2. **Backend Module:**
+ - `/backend/lessons/modules/xss-comprehensive/index.js`
+ - Merges functionality from both XSS modules
+ - Handles both interactive components:
+ - `testXSSPayload()` for reflected XSS demo (XSSDeeplinkDemo)
+ - `addComment()` for stored XSS demo (ForumScriptDemo)
+
+### Lesson Structure
+
+The combined lesson flows as follows:
+
+1. **Introduction** - What is XSS? (covers both reflected and stored)
+2. **Reflected XSS** - URL parameter injection explanation
+3. **Interactive Demo 1** - XSSDeeplinkDemo (reflected XSS)
+4. **Question 1** - Multiple choice (25 pts): Identify reflected XSS payloads
+5. **Stored XSS** - Persistent attacks explanation
+6. **Real-World Examples** - Samy Worm, TweetDeck, eBay, British Airways
+7. **Interactive Demo 2** - ForumScriptDemo (stored XSS)
+8. **Question 2** - Multiple choice (25 pts): Identify stored XSS payloads
+9. **Attack Vectors** - Common XSS techniques
+10. **Question 3** - Single choice (30 pts): Why stored XSS is more dangerous
+11. **Prevention** - Defense-in-depth approach
+12. **Question 4** - Single choice (20 pts): Most effective prevention method
+
+### Content Removed
+
+â **Free text questions removed:**
+- Old Question 3 from xss-deeplink-demo (30 pts)
+- Old Question 3 from script-injection-forum (30 pts)
+
+â **Developer-specific content removed:**
+- Framework security features (React, Angular, Vue)
+- Dangerous functions to avoid (dangerouslySetInnerHTML, bypassSecurityTrust, v-html)
+- Framework-specific implementation details
+
+### Content Retained
+
+â **User-focused prevention techniques:**
+- Output encoding (HTML, JavaScript, URL, CSS contexts)
+- Content Security Policy (CSP)
+- Input validation
+- HTTPOnly and Secure cookies
+- Web Application Firewall (WAF)
+- Regular security audits
+
+## Old Files
+
+The following files are now **deprecated** but kept for reference:
+
+- `/backend/lessons/configs/xss-deeplink-demo.yaml` (deprecated)
+- `/backend/lessons/configs/script-injection-forum.yaml` (deprecated)
+- `/backend/lessons/modules/xss-deeplink-demo/index.js` (deprecated)
+- `/backend/lessons/modules/script-injection-forum/index.js` (deprecated)
+
+**Note:** The frontend components are still used and should NOT be removed:
+- `/frontend/src/components/lessons/InteractiveContent/XSSDeeplinkDemo.jsx` (ACTIVE)
+- `/frontend/src/components/lessons/InteractiveContent/ForumScriptDemo.jsx` (ACTIVE)
+
+## How to Use the New Lesson
+
+### 1. Add to Database
+
+If you have a seed script, add the new lesson:
+
+```javascript
+// In your seed script
+const xssComprehensive = await Lesson.create({
+ lessonKey: 'xss-comprehensive',
+ title: 'Cross-Site Scripting (XSS) - Reflected & Stored Angriffe',
+ description: 'Lernen Sie, wie XSS-Angriffe durch URL-Manipulation und benutzergenerierte Inhalte funktionieren und wie man sie erkennt',
+ difficultyLevel: 'intermediate',
+ estimatedDuration: 35,
+ configPath: 'backend/lessons/configs/xss-comprehensive.yaml',
+ modulePath: 'backend/lessons/modules/xss-comprehensive'
+});
+```
+
+### 2. Remove Old Lessons (Optional)
+
+If desired, you can remove the old separate XSS lessons from the database:
+
+```sql
+-- Mark old lessons as inactive or delete them
+UPDATE lessons SET is_active = false
+WHERE lesson_key IN ('xss-deeplink-demo', 'script-injection-forum');
+```
+
+### 3. Assign to Events
+
+The new comprehensive lesson can now be assigned to events just like any other lesson.
+
+## Testing Checklist
+
+- [ ] Backend module loads correctly
+- [ ] XSSDeeplinkDemo interactive component works
+- [ ] ForumScriptDemo interactive component works
+- [ ] All 4 questions validate correctly
+- [ ] Scoring totals to 100 points
+- [ ] 70% passing score works (70 out of 100)
+- [ ] No developer-specific content visible to users
+- [ ] No free text questions present
+- [ ] All content is in German
+
+## Point Distribution
+
+| Question | Type | Points | Topic |
+|----------|------|--------|-------|
+| Q1 | Multiple Choice | 25 | Identify reflected XSS payloads |
+| Q2 | Multiple Choice | 25 | Identify stored XSS payloads |
+| Q3 | Single Choice | 30 | Why stored XSS is more dangerous |
+| Q4 | Single Choice | 20 | Most effective prevention method |
+| **Total** | | **100** | |
+
+**Passing Score:** 70 points (70%)
diff --git a/backend/lessons/configs/browser-in-browser-attack.yaml b/backend/lessons/configs/browser-in-browser-attack.yaml
index e3cec24..f075649 100644
--- a/backend/lessons/configs/browser-in-browser-attack.yaml
+++ b/backend/lessons/configs/browser-in-browser-attack.yaml
@@ -1,6 +1,6 @@
lessonKey: "browser-in-browser-attack"
-title: "Browser-in-the-Browser (BitB) Attack"
-description: "Learn to identify sophisticated phishing attacks that mimic legitimate browser windows"
+title: "Browser-in-the-Browser (BitB) Angriff"
+description: "Lernen Sie, ausgeklĂźgelte Phishing-Angriffe zu erkennen, die legitime Browserfenster nachahmen"
difficultyLevel: "advanced"
estimatedDuration: 25
module: "browser-in-browser-attack"
@@ -8,167 +8,153 @@ module: "browser-in-browser-attack"
steps:
- id: "intro"
type: "content"
- title: "What is Browser-in-the-Browser?"
+ title: "Was ist Browser-in-the-Browser?"
content: |
- Browser-in-the-Browser (BitB) is an advanced phishing technique that creates a fake browser window inside a webpage. It's designed to trick users into thinking they're interacting with a legitimate OAuth/SSO login popup.
+ Browser-in-the-Browser (BitB) ist eine fortgeschrittene Phishing-Technik, die ein gefälschtes Browserfenster innerhalb einer Webseite erstellt. Sie ist darauf ausgelegt, Benutzer dazu zu bringen, zu glauben, sie wßrden mit einem legitimen OAuth/SSO-Login-Popup interagieren.
- Why it's dangerous:
- ⢠Looks identical to real browser popup windows
- ⢠Shows a fake address bar with HTTPS lock icon
- ⢠Mimics trusted services (Google, Microsoft, Facebook)
- ⢠Can steal credentials even from security-aware users
- ⢠Bypasses traditional phishing detection
+ Warum es gefährlich ist:
+ ⢠Sieht identisch aus wie echte Browser-Popup-Fenster
+ ⢠Zeigt eine gefälschte Adressleiste mit HTTPS-Schloss-Symbol
+ ⢠Imitiert vertrauenswßrdige Dienste (Google, Microsoft, Facebook)
+ ⢠Kann Anmeldedaten auch von sicherheitsbewussten Benutzern stehlen
+ ⢠Umgeht traditionelle Phishing-Erkennung
- This attack gained prominence in 2022 and has been used in targeted attacks against organizations.
+ Dieser Angriff wurde 2022 bekannt und wurde in gezielten Angriffen gegen Organisationen eingesetzt.
- id: "how-it-works"
type: "content"
- title: "How the Attack Works"
+ title: "Wie der Angriff funktioniert"
content: |
- Traditional OAuth Flow:
- 1. User clicks "Sign in with Google" on a website
- 2. Browser opens a REAL popup to google.com
- 3. User enters credentials on Google's actual site
- 4. Google redirects back with authentication token
+ Traditioneller OAuth-Ablauf:
+ 1. Benutzer klickt auf "Mit Google anmelden" auf einer Website
+ 2. Browser Ăśffnet ein ECHTES Popup zu google.com
+ 3. Benutzer gibt Anmeldedaten auf der tatsächlichen Google-Seite ein
+ 4. Google leitet mit Authentifizierungstoken zurĂźck
- BitB Attack Flow:
- 1. User clicks "Sign in with Google" on malicious site
- 2. Site creates a FAKE popup using HTML/CSS/JavaScript
- 3. Fake popup shows fake address bar displaying "accounts.google.com"
- 4. User enters credentials on attacker's fake page
- 5. Attacker captures credentials and simulates success
+ BitB-Angriff-Ablauf:
+ 1. Benutzer klickt auf "Mit Google anmelden" auf bĂśsartiger Seite
+ 2. Seite erstellt ein GEFĂLSCHTES Popup mit HTML/CSS/JavaScript
+ 3. Gefälschtes Popup zeigt gefälschte Adressleiste mit "accounts.google.com"
+ 4. Benutzer gibt Anmeldedaten auf der gefälschten Seite des Angreifers ein
+ 5. Angreifer erfasst Anmeldedaten und simuliert Erfolg
- The entire "browser window" is actually just HTML elements styled to look like a browser!
+ Das gesamte "Browserfenster" ist eigentlich nur HTML-Elemente, die so gestaltet sind, dass sie wie ein Browser aussehen!
- id: "bitb-demo"
type: "interactive"
- title: "Interactive BitB Demo"
+ title: "Interaktive BitB-Demo"
interactiveComponent: "BitBDemo"
content: |
- Below you'll see two login scenarios. One uses a REAL browser popup (secure), and one uses a BitB attack (malicious).
+ Unten sehen Sie zwei Login-Szenarien. Eines verwendet ein ECHTES Browser-Popup (sicher), und eines verwendet einen BitB-Angriff (bĂśsartig).
- Can you identify the fake? Pay close attention to the details!
+ KÜnnen Sie die Fälschung erkennen? Achten Sie genau auf die Details!
- id: "question-1"
type: "question"
questionType: "multiple_choice"
- question: "What are the key indicators that can help identify a Browser-in-the-Browser attack?"
+ question: "Was sind die wichtigsten Indikatoren, die helfen kĂśnnen, einen Browser-in-the-Browser-Angriff zu erkennen?"
options:
- id: "https-lock"
- text: "The presence of HTTPS and a lock icon in the address bar"
+ text: "Das Vorhandensein von HTTPS und einem Schloss-Symbol in der Adressleiste"
isCorrect: false
points: 0
- id: "window-behavior"
- text: "The popup window cannot be dragged outside the main browser window"
+ text: "Das Popup-Fenster kann nicht auĂerhalb des Hauptbrowserfensters gezogen werden"
isCorrect: true
points: 20
- id: "inspect-element"
- text: "Right-clicking allows you to 'Inspect Element' on the address bar"
+ text: "Rechtsklick ermĂśglicht 'Element untersuchen' auf der Adressleiste"
isCorrect: true
points: 20
- id: "domain-name"
- text: "The domain name shown in the address bar"
+ text: "Der in der Adressleiste angezeigte Domainname"
isCorrect: false
points: 0
maxPoints: 40
feedback:
- correct: "Excellent! Real browser windows can be moved anywhere and their UI cannot be inspected as HTML elements."
- incorrect: "Think about what differentiates a real browser window from HTML/CSS elements on a webpage. The lock icon and domain can both be faked!"
+ correct: "Ausgezeichnet! Echte Browserfenster kÜnnen ßberall hin bewegt werden und ihre Benutzeroberfläche kann nicht als HTML-Elemente untersucht werden."
+ incorrect: "Denken Sie darßber nach, was ein echtes Browserfenster von HTML/CSS-Elementen auf einer Webseite unterscheidet. Das Schloss-Symbol und die Domain kÜnnen beide gefälscht werden!"
- id: "detection-techniques"
type: "content"
- title: "Detecting BitB Attacks"
+ title: "BitB-Angriffe erkennen"
content: |
- How to spot a Browser-in-the-Browser attack:
+ Wie man einen Browser-in-the-Browser-Angriff erkennt:
- 1. **Try to Drag the Window**
- ⢠Real popups can be dragged outside the browser
- ⢠Fake popups are trapped within the main window
+ 1. **Versuchen Sie, das Fenster zu ziehen**
+ ⢠Echte Popups kĂśnnen auĂerhalb des Browsers gezogen werden
+ ⢠Gefälschte Popups sind im Hauptfenster gefangen
- 2. **Check if Address Bar is Selectable**
- ⢠Real address bars: text is selectable
- ⢠Fake address bars: usually just an image or styled div
+ 2. **Prßfen Sie, ob die Adressleiste auswählbar ist**
+ ⢠Echte Adressleisten: Text ist auswählbar
+ ⢠Gefälschte Adressleisten: normalerweise nur ein Bild oder gestyltes div
- 3. **Right-Click the Address Bar**
- ⢠Real browser: no "Inspect Element" option
- ⢠Fake browser: shows HTML inspection menu
+ 3. **Klicken Sie mit der rechten Maustaste auf die Adressleiste**
+ ⢠Echter Browser: keine "Element untersuchen"-Option
+ ⢠Gefälschter Browser: zeigt HTML-Inspektionsmenß
- 4. **Look for Pixel-Perfect Details**
- ⢠Fake windows may have slight styling differences
- ⢠Shadow effects, fonts, or spacing might be off
+ 4. **Achten Sie auf pixelgenaue Details**
+ ⢠Gefälschte Fenster kÜnnen leichte Styling-Unterschiede haben
+ ⢠Schatteneffekte, Schriftarten oder Abstände kÜnnten abweichen
- 5. **Check Your Browser's Task Bar**
- ⢠Real popups appear as separate windows in taskbar
- ⢠Fake popups don't create new window entries
+ 5. **ĂberprĂźfen Sie die Taskleiste Ihres Browsers**
+ ⢠Echte Popups erscheinen als separate Fenster in der Taskleiste
+ ⢠Gefälschte Popups erstellen keine neuen Fenstereinträge
- 6. **Use Browser Extensions**
- ⢠Some extensions can detect fake browser UI
+ 6. **Verwenden Sie Browser-Erweiterungen**
+ ⢠Einige Erweiterungen kÜnnen gefälschte Browser-Benutzeroberflächen erkennen
- id: "question-2"
type: "question"
questionType: "single_choice"
- question: "A website asks you to 'Sign in with Microsoft' and a popup appears. What is the SAFEST approach?"
+ question: "Eine Website fordert Sie auf, sich 'Mit Microsoft anmelden' und ein Popup erscheint. Was ist der SICHERSTE Ansatz?"
options:
- id: "trust-https"
- text: "Check for HTTPS in the address bar and proceed if present"
+ text: "In der Adressleiste nach HTTPS suchen und fortfahren, wenn vorhanden"
isCorrect: false
points: 0
- id: "test-window"
- text: "Try to drag the popup outside the browser window to verify it's real"
+ text: "Versuchen, das Popup auĂerhalb des Browserfensters zu ziehen, um zu ĂźberprĂźfen, ob es echt ist"
isCorrect: true
points: 35
- id: "check-domain"
- text: "Carefully read the domain name to ensure it's Microsoft's real domain"
+ text: "Den Domainnamen sorgfältig lesen, um sicherzustellen, dass es Microsofts echte Domain ist"
isCorrect: false
points: 0
- id: "close-and-manual"
- text: "Close the popup and manually navigate to Microsoft's site"
+ text: "Das Popup schlieĂen und manuell zur Microsoft-Seite navigieren"
isCorrect: false
points: 10
maxPoints: 35
feedback:
- correct: "Perfect! Testing if the window can be dragged outside the browser is the most reliable quick check. Though manually navigating is also very safe!"
- incorrect: "While checking the domain helps, it can be faked in a BitB attack. The physical behavior of the window (can it be dragged out?) reveals the truth."
+ correct: "Perfekt! Zu testen, ob das Fenster auĂerhalb des Browsers gezogen werden kann, ist die zuverlässigste SchnellprĂźfung. Obwohl manuelle Navigation auch sehr sicher ist!"
+ incorrect: "Während die ĂberprĂźfung der Domain hilft, kann sie bei einem BitB-Angriff gefälscht werden. Das physische Verhalten des Fensters (kann es herausgezogen werden?) offenbart die Wahrheit."
- id: "prevention"
type: "content"
- title: "Protecting Against BitB Attacks"
+ title: "Schutz vor BitB-Angriffen"
content: |
- For Users:
- ⢠Always test if popup windows can be moved freely
- ⢠Use password managers (they check actual domains)
- ⢠Enable 2FA/MFA for additional security layer
- ⢠Be suspicious of unexpected login prompts
- ⢠Manually navigate to sites instead of clicking links
+ FĂźr Benutzer:
+ ⢠Testen Sie immer, ob Popup-Fenster frei bewegt werden kÜnnen
+ ⢠Verwenden Sie Passwort-Manager (sie prßfen tatsächliche Domains)
+ ⢠Aktivieren Sie 2FA/MFA fßr zusätzliche Sicherheitsebene
+ ⢠Seien Sie misstrauisch bei unerwarteten Login-Aufforderungen
+ ⢠Navigieren Sie manuell zu Seiten, anstatt auf Links zu klicken
- For Developers:
- ⢠Educate users about OAuth popup behavior
- ⢠Use OAuth redirect flow instead of popups when possible
- ⢠Implement additional verification steps
- ⢠Consider passwordless authentication methods
- ⢠Show clear security indicators in your app
+ FĂźr Entwickler:
+ ⢠Schulen Sie Benutzer ßber OAuth-Popup-Verhalten
+ ⢠Verwenden Sie OAuth-Redirect-Flow statt Popups, wenn mÜglich
+ ⢠Implementieren Sie zusätzliche Verifizierungsschritte
+ ⢠Erwägen Sie passwortlose Authentifizierungsmethoden
+ ⢠Zeigen Sie klare Sicherheitsindikatoren in Ihrer App
- For Organizations:
- ⢠Train employees to recognize advanced phishing
- ⢠Deploy anti-phishing browser extensions
- ⢠Use hardware security keys (FIDO2/WebAuthn)
- ⢠Monitor for suspicious authentication attempts
- ⢠Implement conditional access policies
-
- - id: "question-3"
- type: "question"
- questionType: "free_text"
- question: "Why are password managers particularly effective at protecting against BitB attacks?"
- validationRules:
- keywords:
- required: ["domain", "autofill", "real"]
- partialCredit: 8
- minLength: 40
- maxPoints: 25
- feedback:
- correct: "Excellent! Password managers check the actual domain of the page and won't autofill credentials on fake domains, even if they look legitimate."
- incorrect: "Think about how password managers verify which site they're on before filling in credentials. They check the real URL, not what's displayed visually."
+ FĂźr Organisationen:
+ ⢠Schulen Sie Mitarbeiter, fortgeschrittenes Phishing zu erkennen
+ ⢠Setzen Sie Anti-Phishing-Browser-Erweiterungen ein
+ ⢠Verwenden Sie Hardware-Sicherheitsschlßssel (FIDO2/WebAuthn)
+ ⢠Ăberwachen Sie verdächtige Authentifizierungsversuche
+ ⢠Implementieren Sie bedingte Zugriffsrichtlinien
scoring:
- passingScore: 75
- maxTotalPoints: 100
+ passingScore: 55
+ maxTotalPoints: 75
diff --git a/backend/lessons/configs/idor-demo.yaml b/backend/lessons/configs/idor-demo.yaml
new file mode 100644
index 0000000..835dc1d
--- /dev/null
+++ b/backend/lessons/configs/idor-demo.yaml
@@ -0,0 +1,426 @@
+lessonKey: "idor-demo"
+title: "IDOR - Unsichere direkte Objektreferenz"
+description: "Erfahre, wie unsichere direkte Objektreferenzen durch URL-Manipulation den unbefugten Zugriff auf Daten anderer Benutzer ermĂśglichen"
+difficultyLevel: "intermediate"
+estimatedDuration: 22
+module: "idor-demo"
+
+steps:
+ - id: "intro"
+ type: "content"
+ title: "Was ist IDOR?"
+ content: |
+ IDOR (Insecure Direct Object Reference - Unsichere direkte Objektreferenz) ist eine Sicherheitslßcke, die auftritt, wenn eine Anwendung direkten Zugriff auf Objekte basierend auf vom Benutzer bereitgestellten Eingaben ermÜglicht. Wenn die Anwendung nicht ordnungsgemäà ßberprßft, ob der Benutzer berechtigt ist, auf das angeforderte Objekt zuzugreifen, kÜnnen Angreifer auf unbefugte Daten zugreifen.
+
+ **Wie IDOR funktioniert:**
+
+ Eine anfällige URL kÜnnte so aussehen:
+ https://bank.com/profile?userId=123
+
+ Wenn die Anwendung nicht prßft, ob der angemeldete Benutzer auf die Daten von Benutzer 123 zugreifen darf, kann ein Angreifer einfach den Parameter ändern:
+ https://bank.com/profile?userId=124 â Zugriff auf die Daten eines anderen Benutzers!
+
+ **IDOR in den OWASP Top 10:**
+ IDOR fällt unter **A01:2021 - Fehlerhafte Zugriffskontrolle**, das kritischste Sicherheitsrisiko fßr Webanwendungen.
+
+ **Häufige IDOR-Ziele:**
+ ⢠Benutzerprofile und Kontodaten
+ ⢠Private Nachrichten und E-Mails
+ ⢠Finanzdaten und Transaktionen
+ ⢠Medizinische Aufzeichnungen
+ ⢠Bestellhistorien
+ ⢠Private Dateien und Dokumente
+ ⢠Verwaltungsfunktionen
+
+ **Warum es gefährlich ist:**
+ ⢠Einfach auszunutzen (nur einen URL-Parameter ändern)
+ ⢠Bleibt oft unentdeckt
+ ⢠Kann sensible persÜnliche Daten offenlegen
+ ⢠Kann Datenschutzgesetze verletzen (DSGVO, HIPAA, etc.)
+ ⢠Kann zu Identitätsdiebstahl fßhren
+ ⢠Keine speziellen Werkzeuge erforderlich
+
+ - id: "auth-vs-authz"
+ type: "content"
+ title: "Authentifizierung vs. Autorisierung"
+ content: |
+ Das Verständnis des Unterschieds zwischen Authentifizierung und Autorisierung ist entscheidend zur Verhinderung von IDOR:
+
+ **Authentifizierung (AuthN):**
+ "Wer bist du?"
+
+ ⢠Verifiziert die Benutzeridentität
+ ⢠Verwendet Anmeldedaten (Benutzername/Passwort, Tokens, etc.)
+ ⢠Bestätigt, dass du die Person bist, fßr die du dich ausgibst
+ ⢠Beispiel: Anmeldung in deinem Konto
+
+ **Autorisierung (AuthZ):**
+ "Was darfst du tun?"
+
+ ⢠Verifiziert Benutzerberechtigungen
+ ⢠Prßft, ob du auf bestimmte Ressourcen zugreifen kannst
+ ⢠Bestimmt, was du sehen oder ändern kannst
+ ⢠Beispiel: ĂberprĂźfung, ob du ein bestimmtes Profil ansehen darfst
+
+ **Das IDOR-Problem:**
+
+ Viele Anwendungen implementieren Authentifizierung, vergessen aber die Autorisierung!
+
+ â Benutzer ist authentifiziert (angemeldet)
+ â Anwendung prĂźft nicht, ob der Benutzer auf diese spezifische Ressource zugreifen darf
+ = IDOR-SicherheitslĂźcke
+
+ **Analogie aus der realen Welt:**
+
+ Authentifizierung = Einen Schlßssel zum Betreten des Gebäudes haben
+ Autorisierung = Die Erlaubnis haben, bestimmte Räume zu betreten
+
+ Bei IDOR hast du einen Schlßssel zum Gebäude (du bist angemeldet), aber die Anwendung prßft nicht, welche Räume du betreten darfst. Du kannst jede Tßr Üffnen, indem du verschiedene Raumnummern ausprobierst!
+
+ **Beispielszenarien:**
+
+ **Szenario 1: Soziale Medien**
+ ⢠Du bist angemeldet (authentifiziert â )
+ ⢠Du versuchst, eine Nachricht anzusehen: /messages/12345
+ ⢠App prĂźft nicht, ob Nachricht 12345 dir gehĂśrt (keine Autorisierung â)
+ ⢠Du kannst private Nachrichten von jedem lesen, indem du die ID änderst
+
+ **Szenario 2: E-Commerce**
+ ⢠Du bist angemeldet (authentifiziert â )
+ ⢠Du siehst deine Bestellung: /orders/5001
+ ⢠App ĂźberprĂźft nicht den Bestellbesitz (keine Autorisierung â)
+ ⢠Du kannst die Bestellungen, Adressen und Kaufhistorie von jedem sehen
+
+ **Szenario 3: Gesundheitswesen**
+ ⢠Du bist als Patient angemeldet (authentifiziert â )
+ ⢠Du siehst Laborergebnisse: /results/patient/789
+ ⢠App prĂźft nicht, ob du Patient 789 bist (keine Autorisierung â)
+ ⢠Du kannst auf medizinische Aufzeichnungen von jedem zugreifen, indem du die ID änderst
+
+ - id: "idor-demo"
+ type: "interactive"
+ title: "IDOR-SicherheitslĂźcken-Demo"
+ interactiveComponent: "IDORDemo"
+ content: |
+ Unten ist eine simulierte Online-Banking-Anwendung mit einer IDOR-SicherheitslĂźcke. Du bist als "Max Mustermann" (Benutzer-ID 55) angemeldet.
+
+ Die Anwendung verwendet einen URL-Parameter zum Abrufen von Benutzerprofilen:
+
+ `https://securebank.example/profile?ref=dashboard&userId=55`
+
+ **Deine Aufgabe:**
+
+ 1. Untersuche die URL-Struktur und identifiziere den anfälligen Parameter
+
+ 2. Versuche, den userId-Parameter zu ändern, um auf andere Benutzer zuzugreifen
+
+ 3. Beobachte, wie du auf private Informationen zugreifen kannst, die du nicht sehen solltest
+
+ 4. Finde versteckte Benutzer durch systematisches Testen verschiedener IDs
+
+ 5. Du hast 5 Minuten Zeit - versuche so viele Benutzer wie mĂśglich zu entdecken!
+
+ **Hinweise:**
+
+ - Nicht alle IDs existieren - manche Benutzer wurden gelĂśscht
+
+ - Es gibt besondere Belohnungen fĂźr bestimmte Entdeckungen
+
+ - Achte auf die Entdeckungsanzeige oben
+
+ Dies demonstriert, warum Anwendungen Autorisierung ĂźberprĂźfen mĂźssen, nicht nur Authentifizierung.
+
+ - id: "question-1"
+ type: "question"
+ questionType: "multiple_choice"
+ question: "Welche der folgenden URL-Muster deuten auf potenzielle IDOR-SicherheitslĂźcken hin?"
+ options:
+ - id: "user-id-param"
+ text: "/api/user?id=123"
+ isCorrect: true
+ points: 10
+ - id: "order-id-param"
+ text: "/orders/view?orderId=5001"
+ isCorrect: true
+ points: 10
+ - id: "document-id-param"
+ text: "/documents/download/42"
+ isCorrect: true
+ points: 10
+ - id: "session-token"
+ text: "/profile (verwendet Session-Token im Header)"
+ isCorrect: false
+ points: 0
+ - id: "message-id-param"
+ text: "/messages/inbox/msg_789"
+ isCorrect: true
+ points: 10
+ maxPoints: 40
+ feedback:
+ correct: "Ausgezeichnet! All diese Muster mit direkten Objekt-IDs in URLs oder Parametern sind potenzielle IDOR-Ziele, wenn keine ordnungsgemäĂe Autorisierung implementiert ist."
+ partial: "Gut! Du hast einige IDOR-Muster erkannt. Jede URL, die Ressourcen-IDs (Benutzer, Bestellungen, Dokumente, Nachrichten) enthält, benÜtigt Autorisierungsprßfungen."
+ incorrect: "Suche nach URLs, die identifizierbare Ressourcen-IDs (Zahlen oder Kennungen) enthalten. Diese benĂśtigen alle eine ordnungsgemäĂe Autorisierung, um IDOR zu verhindern. Session-Tokens sind sicher, weil sie serverseitig verifiziert werden."
+
+ - id: "real-world-impact"
+ type: "content"
+ title: "IDOR-Datenlecks in der realen Welt"
+ content: |
+ IDOR-SicherheitslĂźcken haben zu massiven Datenlecks und Datenschutzverletzungen gefĂźhrt:
+
+ **Facebook (2019) - 419 Millionen Datensätze**
+ ⢠Telefonnummern durch IDOR offengelegt
+ ⢠Angreifer konnten Benutzer-IDs aufzählen
+ ⢠Datenbank enthielt Facebook-IDs und Telefonnummern
+ ⢠Betraf Benutzer weltweit
+ ⢠Fßhrte zu erheblichen Datenschutzbedenken
+
+ **Bumble Dating App (2019)**
+ ⢠IDOR ermÜglichte Zugriff auf jedes Benutzerprofil
+ ⢠Angreifer konnten private Fotos ansehen
+ ⢠Konnte auf als "versteckt" markierte Benutzer zugreifen
+ ⢠Echtzeit-Standortdaten offengelegt
+ ⢠Profile von 95 Millionen Benutzern erfasst
+
+ **Parler Social Network (2021)**
+ ⢠IDOR in Post- und Benutzer-APIs
+ ⢠Alle Beiträge waren sequentiell nummeriert
+ ⢠Angreifer erfassten 70TB Daten
+ ⢠Enthielt gelÜschte Beiträge und Metadaten
+ ⢠Enthielt GPS-Koordinaten aus Videos
+
+ **Verizon (2017)**
+ ⢠IDOR legte 14 Millionen Kundendatensätze offen
+ ⢠Kontodetails, Telefonnummern und PINs
+ ⢠Einfache Parametermanipulation
+ ⢠Ohne Authentifizierung zugänglich
+ ⢠BenÜtigte 6 Monate zur Entdeckung
+
+ **USPS Informed Visibility (2018)**
+ ⢠IDOR legte 60 Millionen Benutzer offen
+ ⢠E-Mail-Adressen, Telefonnummern und Adressen
+ ⢠Mailingkampagnendaten
+ ⢠Kontodetails und Präferenzen
+ ⢠Wildcard-Suchsicherheitslßcke
+
+ **PizzaHut Australia (2020)**
+ ⢠IDOR in Bestell-API
+ ⢠Kundennamen, Adressen und Bestellhistorie
+ ⢠Kreditkartendetails (teilweise)
+ ⢠Lieferanweisungen
+ ⢠Telefonnummern
+
+ **Auswirkungsstatistiken:**
+ ⢠IDOR erscheint in ~15% aller Webanwendungen
+ ⢠Durchschnittliche Kosten eines IDOR-Lecks: 3,86 Millionen Dollar
+ ⢠Durchschnittliche Zeit zur Entdeckung: 197 Tage
+ ⢠Durchschnittliche Zeit zur Eindämmung: 69 Tage
+ ⢠60% der Organisationen erlebten IDOR in den letzten 2 Jahren
+
+ **Rechtliche Konsequenzen:**
+ ⢠DSGVO-Strafen bis zu 20 Millionen Euro oder 4% des Umsatzes
+ ⢠CCPA-Strafen bis zu 7.500 Dollar pro VerstoĂ
+ ⢠Sammelklagen von betroffenen Benutzern
+ ⢠Verlust von Kundenvertrauen und Reputation
+ ⢠BehÜrdliche Untersuchungen
+ ⢠Verpflichtende Benachrichtigungen ßber Datenlecks
+
+ - id: "question-2"
+ type: "question"
+ questionType: "single_choice"
+ question: "Was ist der BESTE Weg, um IDOR-SicherheitslĂźcken zu verhindern?"
+ options:
+ - id: "hide-ids"
+ text: "Alle Objekt-IDs in URLs verstecken oder verschlĂźsseln"
+ isCorrect: false
+ points: 0
+ - id: "session-check"
+ text: "ĂberprĂźfen, dass der authentifizierte Benutzer die Berechtigung hat, auf die angeforderte Ressource zuzugreifen"
+ isCorrect: true
+ points: 30
+ - id: "rate-limiting"
+ text: "Rate-Limiting implementieren, um ID-Aufzählung zu verhindern"
+ isCorrect: false
+ points: 0
+ - id: "complex-ids"
+ text: "Komplexe, zufällige IDs anstelle von sequentiellen Nummern verwenden"
+ isCorrect: false
+ points: 0
+ maxPoints: 30
+ feedback:
+ correct: "Perfekt! OrdnungsgemäĂe AutorisierungsprĂźfungen sind unerlässlich. Jede Anfrage muss ĂźberprĂźfen, ob der Benutzer die Berechtigung hat, auf die spezifische Ressource zuzugreifen, unabhängig davon, wie die ID formatiert ist."
+ incorrect: "Obwohl Verschleierung und Rate-Limiting helfen kĂśnnen, lĂśsen sie nicht das Grundproblem. Die Anwendung MUSS ĂźberprĂźfen, dass der authentifizierte Benutzer die Autorisierung hat, auf jede spezifische Ressource zuzugreifen, bevor sie zurĂźckgegeben wird."
+
+ - id: "secure-design"
+ type: "content"
+ title: "Sichere Designmuster"
+ content: |
+ **IDOR verhindern: Best Practices**
+
+ **1. ZugriffskontrollprĂźfungen implementieren**
+
+ Jeder Ressourcenzugriff muss die Autorisierung ĂźberprĂźfen:
+
+ // â ANFĂLLIG - Keine AutorisierungsprĂźfung
+ app.get('/api/profile/:userId', authenticate, (req, res) => {
+ const user = db.getUserById(req.params.userId);
+ res.json(user); // Gibt die Daten eines beliebigen Benutzers zurĂźck!
+ });
+
+ // â SICHER - OrdnungsgemäĂe Autorisierung
+ app.get('/api/profile/:userId', authenticate, (req, res) => {
+ const requestedUserId = req.params.userId;
+ const currentUserId = req.session.userId;
+
+ // PrĂźfen, ob Benutzer Berechtigung hat
+ if (requestedUserId !== currentUserId && !req.session.isAdmin) {
+ return res.status(403).json({ error: 'Forbidden' });
+ }
+
+ const user = db.getUserById(requestedUserId);
+ res.json(user);
+ });
+
+ **2. Indirekte Referenzen verwenden**
+
+ Datenbank-IDs nicht direkt offenlegen:
+
+ // â Direkte Referenz auf Datenbank-ID
+ GET /api/messages/12345
+
+ // â Indirekte Referenz durch Benutzerkontext
+ GET /api/messages/inbox (gibt nur Nachrichten des Benutzers zurĂźck)
+ GET /api/messages/sent (gibt nur gesendete Nachrichten des Benutzers zurĂźck)
+
+ // Wenn du IDs verwenden musst, ĂźberprĂźfe den Besitz:
+ GET /api/messages/msg_abc123
+ // Dann prĂźfen: db.isMessageOwnedBy(msg_abc123, currentUserId)
+
+ **3. Rollenbasierte Zugriffskontrolle (RBAC) implementieren**
+
+ Klare Berechtigungsmodelle definieren:
+
+ const permissions = {
+ user: {
+ canViewOwnProfile: true,
+ canViewOtherProfiles: false,
+ canEditOwnProfile: true,
+ canEditOtherProfiles: false
+ },
+ admin: {
+ canViewOwnProfile: true,
+ canViewOtherProfiles: true,
+ canEditOwnProfile: true,
+ canEditOtherProfiles: true
+ }
+ };
+
+ function checkPermission(user, action, resource) {
+ if (action === 'view' && resource.ownerId !== user.id) {
+ return permissions[user.role].canViewOtherProfiles;
+ }
+ return permissions[user.role][`can${action}`];
+ }
+
+ **4. Sitzungsbasierten Ressourcenzugriff verwenden**
+
+ Lass die Sitzung bestimmen, auf welche Ressourcen zugegriffen werden kann:
+
+ // â Aktuelle Benutzerdaten aus Sitzung abrufen
+ app.get('/api/profile', authenticate, (req, res) => {
+ const userId = req.session.userId; // Aus verifizierter Sitzung
+ const user = db.getUserById(userId);
+ res.json(user);
+ });
+
+ // â Bestellungen des aktuellen Benutzers aus Sitzung abrufen
+ app.get('/api/orders', authenticate, (req, res) => {
+ const userId = req.session.userId;
+ const orders = db.getOrdersByUserId(userId);
+ res.json(orders);
+ });
+
+ **5. Zugriffskontrolllisten (ACLs) implementieren**
+
+ FĂźr komplexe Berechtigungen:
+
+ class AccessControl {
+ canAccess(userId, resourceType, resourceId) {
+ // Besitz prĂźfen
+ const resource = db.getResource(resourceType, resourceId);
+ if (resource.ownerId === userId) return true;
+
+ // Freigabeberechtigungen prĂźfen
+ const acl = db.getACL(resourceType, resourceId);
+ if (acl.sharedWith.includes(userId)) return true;
+
+ // Gruppenberechtigungen prĂźfen
+ const user = db.getUser(userId);
+ if (acl.groupsWithAccess.some(g => user.groups.includes(g))) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ **6. Zugriffsversuche protokollieren und Ăźberwachen**
+
+ app.get('/api/resource/:id', authenticate, (req, res) => {
+ const resourceId = req.params.id;
+ const userId = req.session.userId;
+
+ // Zugriffsversuch protokollieren
+ logger.info('Ressourcenzugriffsversuch', {
+ userId,
+ resourceId,
+ timestamp: Date.now()
+ });
+
+ // Autorisierung prĂźfen
+ if (!canAccess(userId, 'resource', resourceId)) {
+ // Unbefugten Versuch protokollieren
+ logger.warn('Unbefugter Zugriffsversuch', {
+ userId,
+ resourceId,
+ ip: req.ip
+ });
+
+ // Sicherheitsteam bei mehreren Versuchen benachrichtigen
+ securityMonitor.recordUnauthorizedAccess(userId, resourceId);
+
+ return res.status(403).json({ error: 'Forbidden' });
+ }
+
+ // Mit autorisiertem Zugriff fortfahren
+ const resource = db.getResource(resourceId);
+ res.json(resource);
+ });
+
+ **7. Auf IDOR testen**
+
+ **Manuelles Testen:**
+ 1. Als Benutzer A anmelden
+ 2. Auf eine Ressource zugreifen: `/api/profile/123`
+ 3. Die ID in der URL/dem Parameter notieren
+ 4. Auf eine andere ID ändern: `/api/profile/124`
+ 5. Wenn du auf die Daten von Benutzer B zugreifen kannst â IDOR-SicherheitslĂźcke!
+
+ **Automatisiertes Testen:**
+ ⢠Tools wie Burp Suite, OWASP ZAP verwenden
+ ⢠Alle Endpunkte mit verschiedenen Benutzerrollen testen
+ ⢠IDs aufzählen, um zugängliche Ressourcen zu finden
+ ⢠Auf horizontale Rechteausweitung prßfen (gleiche Rolle, anderer Benutzer)
+ ⢠Auf vertikale Rechteausweitung prßfen (andere Rolle)
+
+ **Sicherheits-Checkliste:**
+ â Alle Ressourcenzugriffe haben AutorisierungsprĂźfungen
+ â Datenbank-IDs werden wenn mĂśglich nicht direkt offengelegt
+ â Rollenbasierte Zugriffskontrolle ist implementiert
+ â Zugriffsversuche werden protokolliert und Ăźberwacht
+ â Sensible Operationen erfordern zusätzliche Verifizierung
+ â RegelmäĂige Sicherheitsaudits und Penetrationstests
+ â Entwicklerschulung zur IDOR-Prävention
+
+scoring:
+ passingScore: 105
+ maxTotalPoints: 210 # 70 from questions + up to 140 from interactive discoveries
diff --git a/backend/lessons/configs/phishing-email-basics.yaml b/backend/lessons/configs/phishing-email-basics.yaml
index a1181a4..d6d40af 100644
--- a/backend/lessons/configs/phishing-email-basics.yaml
+++ b/backend/lessons/configs/phishing-email-basics.yaml
@@ -1,6 +1,6 @@
lessonKey: "phishing-email-basics"
-title: "Phishing Email Detection Basics"
-description: "Learn to identify common phishing tactics in emails and protect yourself from email-based attacks"
+title: "Grundlagen der Phishing-E-Mail-Erkennung"
+description: "Lernen Sie, gängige Phishing-Taktiken in E-Mails zu erkennen und sich vor E-Mail-basierten Angriffen zu schßtzen"
difficultyLevel: "beginner"
estimatedDuration: 15
module: "phishing-email-basics"
@@ -8,110 +8,95 @@ module: "phishing-email-basics"
steps:
- id: "intro"
type: "content"
- title: "What is Phishing?"
+ title: "Was ist Phishing?"
content: |
- Phishing is a type of cyber attack where attackers impersonate legitimate organizations
- to steal sensitive information like passwords, credit card numbers, or personal data.
+ Phishing ist eine Art von Cyberangriff, bei dem Angreifer sich als legitime Organisationen ausgeben,
+ um sensible Informationen wie PasswĂśrter, Kreditkartennummern oder persĂśnliche Daten zu stehlen.
- Phishing emails often:
- - Create a sense of urgency
- - Contain suspicious links or attachments
- - Have spelling and grammar errors
- - Use generic greetings like "Dear Customer"
- - Request sensitive information
+ Phishing-E-Mails haben oft folgende Merkmale:
+ - Erzeugen ein GefĂźhl der Dringlichkeit
+ - Enthalten verdächtige Links oder Anhänge
+ - Weisen Rechtschreib- und Grammatikfehler auf
+ - Verwenden allgemeine BegrĂźĂungen wie "Sehr geehrter Kunde"
+ - Fordern sensible Informationen an
- id: "example-1"
type: "content"
- title: "Example Phishing Email"
+ title: "Beispiel einer Phishing-E-Mail"
content: |
- **From:** security@paypa1-verify.com
- **Subject:** Urgent: Verify Your Account Now!
+ **Von:** security@paypa1-verify.com
+ **Betreff:** Dringend: Verifizieren Sie jetzt Ihr Konto!
- Dear Valued Customer,
+ Sehr geehrter Kunde,
- Your PayPal account has been temporarily suspended due to unusual activity.
- To restore your account, please verify your information immediately by clicking
- the link below:
+ Ihr PayPal-Konto wurde aufgrund ungewÜhnlicher Aktivitäten vorßbergehend gesperrt.
+ Um Ihr Konto wiederherzustellen, verifizieren Sie bitte sofort Ihre Informationen,
+ indem Sie auf den untenstehenden Link klicken:
- [Verify Account Now]
+ [Konto jetzt verifizieren]
- Failure to verify within 24 hours will result in permanent account suspension.
+ Wenn Sie nicht innerhalb von 24 Stunden verifizieren, wird Ihr Konto dauerhaft gesperrt.
- Thank you,
+ Vielen Dank,
PayPal Security Team
- id: "question-1"
type: "question"
questionType: "multiple_choice"
- question: "What are the suspicious elements in this email? (Select all that apply)"
+ question: "Was sind die verdächtigen Elemente in dieser E-Mail? (Wählen Sie alle zutreffenden)"
options:
- id: "misspelled-domain"
- text: "The sender's domain is misspelled (paypa1 instead of paypal)"
+ text: "Die Domain des Absenders ist falsch geschrieben (paypa1 statt paypal)"
isCorrect: true
points: 15
- id: "urgent-language"
- text: "Uses urgent/threatening language to create pressure"
+ text: "Verwendet dringende/drohende Sprache, um Druck zu erzeugen"
isCorrect: true
points: 15
- id: "generic-greeting"
- text: "Uses generic greeting 'Dear Valued Customer'"
+ text: "Verwendet allgemeine BegrĂźĂung 'Sehr geehrter Kunde'"
isCorrect: true
points: 10
- id: "requests-action"
- text: "Requests immediate action via a link"
+ text: "Fordert sofortige Handlung Ăźber einen Link"
isCorrect: true
points: 10
- id: "legitimate"
- text: "This appears to be a legitimate email"
+ text: "Dies scheint eine legitime E-Mail zu sein"
isCorrect: false
points: 0
maxPoints: 50
feedback:
- correct: "Excellent! You identified all the key phishing indicators."
- partial: "Good job! You spotted some red flags, but review the email again carefully."
- incorrect: "Not quite. Let's review the common signs of phishing emails."
+ correct: "Ausgezeichnet! Sie haben alle wichtigen Phishing-Indikatoren erkannt."
+ partial: "Gut gemacht! Sie haben einige Warnsignale erkannt, aber ßberprßfen Sie die E-Mail noch einmal sorgfältig."
+ incorrect: "Nicht ganz. Lassen Sie uns die häufigen Anzeichen von Phishing-E-Mails noch einmal ansehen."
- id: "question-2"
type: "question"
questionType: "single_choice"
- question: "What should you do if you receive a suspicious email like this?"
+ question: "Was sollten Sie tun, wenn Sie eine verdächtige E-Mail wie diese erhalten?"
options:
- id: "click-link"
- text: "Click the link to verify my account"
+ text: "Auf den Link klicken, um mein Konto zu verifizieren"
isCorrect: false
points: 0
- id: "reply-email"
- text: "Reply to the email asking if it's legitimate"
+ text: "Auf die E-Mail antworten und fragen, ob sie legitim ist"
isCorrect: false
points: 0
- id: "delete-report"
- text: "Delete the email and report it as phishing"
+ text: "Die E-Mail lĂśschen und als Phishing melden"
isCorrect: true
points: 25
- id: "forward-friends"
- text: "Forward it to friends to warn them"
+ text: "Sie an Freunde weiterleiten, um sie zu warnen"
isCorrect: false
points: 0
maxPoints: 25
feedback:
- correct: "Perfect! Deleting and reporting phishing emails is the right approach."
- incorrect: "That's not safe. Never click links or reply to suspicious emails. Delete and report them."
-
- - id: "question-3"
- type: "question"
- questionType: "free_text"
- question: "Describe at least three things you should check before clicking a link in an email."
- validationRules:
- - type: "contains_keywords"
- keywords: ["sender", "domain", "url", "link", "https", "hover", "address", "spelling", "grammar"]
- minMatches: 3
- - type: "min_length"
- value: 50
- maxPoints: 25
- feedback:
- correct: "Great answer! You understand the importance of verifying emails before taking action."
- incorrect: "Consider checking the sender's email address, hovering over links to see the real URL, and looking for HTTPS."
+ correct: "Perfekt! Das LĂśschen und Melden von Phishing-E-Mails ist der richtige Ansatz."
+ incorrect: "Das ist nicht sicher. Klicken Sie niemals auf Links oder antworten Sie auf verdächtige E-Mails. LÜschen und melden Sie sie."
scoring:
- passingScore: 70
- maxTotalPoints: 100
+ passingScore: 50
+ maxTotalPoints: 75
diff --git a/backend/lessons/configs/script-injection-forum.yaml b/backend/lessons/configs/script-injection-forum.yaml
new file mode 100644
index 0000000..bbcefc8
--- /dev/null
+++ b/backend/lessons/configs/script-injection-forum.yaml
@@ -0,0 +1,283 @@
+lessonKey: "script-injection-forum"
+title: "Stored XSS - Forum Comment Injection"
+description: "Lernen Sie, wie Script-Injection in benutzergenerierten Inhalten ganze Plattformen durch Stored-XSS-Angriffe kompromittieren kann"
+difficultyLevel: "intermediate"
+estimatedDuration: 25
+module: "script-injection-forum"
+
+steps:
+ - id: "intro"
+ type: "content"
+ title: "Was ist Stored XSS?"
+ content: |
+ Stored XSS (Cross-Site Scripting) ist eine Art von Injection-Angriff, bei dem bĂśsartige Skripte dauerhaft auf einem Zielserver gespeichert werden. Im Gegensatz zu Reflected XSS, bei dem das Opfer auf einen bĂśsartigen Link klicken muss, betrifft Stored XSS alle Benutzer, die den kompromittierten Inhalt ansehen.
+
+ **Häufige Ziele:**
+ ⢠Forum-Beiträge und Kommentare
+ ⢠Benutzerprofile und Biografien
+ ⢠Produktbewertungen
+ ⢠Feedback-Formulare
+ ⢠Social-Media-Beiträge
+ ⢠Blog-Kommentare
+ ⢠Wiki-Seiten
+
+ **Auswirkungen:**
+ ⢠Cookie-Diebstahl und Session-Hijacking
+ ⢠Kontoßbernahme
+ ⢠Malware-Verteilung
+ ⢠Website-Verunstaltung
+ ⢠Phishing-Angriffe auf andere Benutzer
+ ⢠Keylogging
+ ⢠Datendiebstahl
+
+ **Warum es gefährlich ist:**
+ Stored XSS ist besonders gefährlich, weil:
+ 1. Es bleibt in der Datenbank bestehen
+ 2. Es betrifft automatisch mehrere Benutzer
+ 3. Es erfordert kein Social Engineering zur Verbreitung
+ 4. Es kann ßber lange Zeiträume unentdeckt bleiben
+
+ - id: "real-world"
+ type: "content"
+ title: "Reale Stored-XSS-Angriffe"
+ content: |
+ **Samy Worm (MySpace, 2005)**
+ Samy Kamkar erstellte einen sich selbst verbreitenden XSS-Wurm in seinem MySpace-Profil, der ihn automatisch als Freund zu jedem Profil hinzufĂźgte, das ihn ansah. Der Wurm kopierte sich auch auf jedes infizierte Profil und verbreitete sich exponentiell.
+
+ Innerhalb von 20 Stunden waren Ăźber 1 Million Benutzer betroffen, was Samy zur beliebtesten Person auf MySpace machte. Die Website musste offline genommen werden, um den Wurm zu entfernen.
+
+ **TweetDeck XSS (Twitter, 2014)**
+ Eine Stored-XSS-Schwachstelle in TweetDeck ermĂśglichte es Angreifern, bĂśsartigen Code Ăźber Tweets einzuschleusen. Als andere Benutzer diese Tweets in TweetDeck ansahen, wurde der Code automatisch ausgefĂźhrt und verursachte:
+ ⢠Automatische Retweets der bÜsartigen Payload
+ ⢠Pop-up-Benachrichtigungen fßr alle Betrachter
+ ⢠Schnelle Verbreitung ßber die Plattform
+
+ **eBay Stored XSS (2015-2016)**
+ Mehrere Stored-XSS-Schwachstellen wurden in den Artikelbeschreibungen von eBay entdeckt. Angreifer konnten:
+ ⢠Code in Produktbeschreibungen einschleusen
+ ⢠Benutzeranmeldeinformationen stehlen, wenn Käufer Angebote ansahen
+ ⢠Benutzer auf Phishing-Seiten umleiten
+ ⢠Konten von Käufern und Verkäufern kompromittieren
+
+ **British Airways XSS (2018)**
+ Angreifer schleusten bĂśsartiges JavaScript Ăźber eine Stored-XSS-Schwachstelle in die Zahlungsseite von British Airways ein. Das Skript:
+ ⢠Erfasste Kreditkarteninformationen
+ ⢠Sendete Daten an vom Angreifer kontrollierte Server
+ ⢠Betraf ßber 380.000 Transaktionen
+ ⢠Kostete British Airways ßber 20 Millionen Pfund an Strafen
+
+ Diese Angriffe demonstrieren, warum Eingabevalidierung und Output-Encoding fĂźr jede Anwendung, die benutzergenerierte Inhalte akzeptiert, kritisch sind.
+
+ - id: "forum-demo"
+ type: "interactive"
+ title: "Anfälliges Forum Demo"
+ interactiveComponent: "ForumScriptDemo"
+ content: |
+ Unten sehen Sie ein vereinfachtes Forum, das Benutzerkommentare OHNE ordnungsgemäĂe Eingabevalidierung oder Output-Encoding akzeptiert. Versuchen Sie zuerst, normale Kommentare zu posten, und experimentieren Sie dann mit Script-Injection-Payloads.
+
+ Beachten Sie, wie die bĂśsartigen Skripte gespeichert werden und alle Benutzer betreffen wĂźrden, die das Forum ansehen. In dieser Demo zeigen wir die Payloads sicher als Text an, anstatt sie auszufĂźhren, mit klaren Warnungen, wenn eine Injection erkannt wird.
+
+ **Probieren Sie diese Aktionen:**
+ 1. Posten Sie einen normalen Kommentar, um sicheres Verhalten zu sehen
+ 2. Versuchen Sie Beispiel-XSS-Payloads, um die Erkennung zu sehen
+ 3. Verwenden Sie die Reload-Schaltfläche, um das Forum zurßckzusetzen
+
+ - id: "question-1"
+ type: "question"
+ questionType: "multiple_choice"
+ question: "Welche der folgenden Payloads kĂśnnten fĂźr Stored-XSS-Angriffe in einem Forum verwendet werden?"
+ options:
+ - id: "script-cookie"
+ text: ""
+ isCorrect: true
+ points: 10
+ - id: "img-steal"
+ text: ""
+ isCorrect: true
+ points: 10
+ - id: "svg-payload"
+ text: ""
+ isCorrect: true
+ points: 10
+ - id: "iframe-phishing"
+ text: ""
+ isCorrect: true
+ points: 10
+ - id: "normal-comment"
+ text: "Dies ist ein normaler Kommentar ohne bĂśsartigen Code"
+ isCorrect: false
+ points: 0
+ maxPoints: 40
+ feedback:
+ correct: "Ausgezeichnet! Sie haben alle gefährlichen Payloads identifiziert, die auf dem Server bestehen bleiben und mehrere Benutzer betreffen kÜnnen."
+ partial: "Gut! Sie haben einige Bedrohungen erkannt, aber ĂźberprĂźfen Sie die Muster, die Code-AusfĂźhrung durch HTML-Tags und Event-Handler ermĂśglichen."
+ incorrect: "ĂberprĂźfen Sie die Demo. Suchen Sie nach Mustern, die Script-Tags, Event-Handler wie onerror oder onload oder eingebettete Inhalte wie iframes enthalten."
+
+ - id: "attack-vectors"
+ type: "content"
+ title: "Stored-XSS-Angriffsvektoren"
+ content: |
+ Gängige Techniken, die Angreifer bei Stored XSS verwenden:
+
+ **1. Cookie-Diebstahl**
+
+ Stiehlt Authentifizierungs-Cookies und ermĂśglicht KontoĂźbernahme. Der Angreifer kann dann jeden Benutzer imitieren, der den Kommentar angesehen hat.
+
+ **2. Session-Hijacking**
+
+ Extrahiert Session-Token aus dem Browser-Speicher und kompromittiert Benutzersitzungen.
+
+ **3. Keylogging**
+
+ Zeichnet jeden Tastendruck auf der Seite auf und erfasst PasswĂśrter und sensible Informationen.
+
+ **4. Verunstaltung**
+
+ Ăndert den sichtbaren Inhalt fĂźr alle Benutzer und beschädigt Reputation und Vertrauen.
+
+ **5. Phishing-Overlay**
+
+
+
+ Zeigt ein gefälschtes Login-Formular ßber der echten Seite an und erfasst Anmeldeinformationen.
+
+ **6. Kryptowährungs-Mining**
+
+ Mined heimlich Kryptowährung mit den CPU-Ressourcen der Besucher.
+
+ **7. Malware-Verteilung**
+
+ Leitet Benutzer zu Malware-Downloads oder Drive-by-Download-Angriffen um.
+
+ - id: "question-2"
+ type: "question"
+ questionType: "single_choice"
+ question: "Warum gilt Stored XSS im Allgemeinen als GEFĂHRLICHER als Reflected XSS?"
+ options:
+ - id: "easier-exploit"
+ text: "Es ist einfacher auszunutzen, da es keine Sonderzeichen erfordert"
+ isCorrect: false
+ points: 0
+ - id: "persistent-victims"
+ text: "Es bleibt auf dem Server bestehen und betrifft alle Benutzer, die den Inhalt ansehen, nicht nur diejenigen, die auf einen bĂśsartigen Link klicken"
+ isCorrect: true
+ points: 30
+ - id: "no-detection"
+ text: "Es kann nicht von Sicherheitstools oder Antiviren-Software erkannt werden"
+ isCorrect: false
+ points: 0
+ - id: "admin-access"
+ text: "Es gewährt Angreifern automatisch Administratorzugriff auf den Server"
+ isCorrect: false
+ points: 0
+ maxPoints: 30
+ feedback:
+ correct: "Perfekt! Stored XSS ist eine persistente Bedrohung, die viele Benutzer Ăźber die Zeit betreffen kann, ohne dass eine individuelle Zielerfassung erforderlich ist. Es bleibt in der Datenbank und wird jedes Mal ausgefĂźhrt, wenn jemand es ansieht."
+ incorrect: "Denken Sie Ăźber den Unterschied zwischen einer Payload, die an jedes Opfer gesendet werden muss, und einer, die einmal gespeichert wird und jeden betrifft. Persistenz und automatische Verbreitung sind die Hauptgefahren."
+
+ - id: "prevention"
+ type: "content"
+ title: "Stored XSS verhindern"
+ content: |
+ **Defense-in-Depth-Ansatz:**
+
+ **1. Eingabevalidierung (Erste Linie)**
+ ⢠Validieren Sie alle Benutzereingaben gegen das erwartete Format
+ ⢠Verwenden Sie Allowlists fßr akzeptable Zeichen
+ ⢠Lehnen Sie Eingaben ab, die verdächtige Muster enthalten
+ ⢠Validieren Sie Datentyp, Länge und Format
+ ⢠Vertrauen Sie niemals "bereinigten" Eingaben - validieren Sie immer
+
+ **2. Output-Encoding (Kritisch)**
+ Kodieren Sie alle Ausgaben kontextabhängig:
+
+ **HTML-Kontext:**
+ ⢠< wird zu <
+ ⢠> wird zu >
+ ⢠& wird zu &
+ ⢠" wird zu "
+ ⢠' wird zu '
+
+ **JavaScript-Kontext:**
+ ⢠Verwenden Sie JSON.stringify() fßr Daten
+ ⢠Escapieren Sie Backslashes und Anfßhrungszeichen
+
+ **URL-Kontext:**
+ ⢠Verwenden Sie encodeURIComponent()
+
+ **Vertrauen Sie niemals Inhalten aus der Datenbank** - selbst wenn sie bei der Eingabe validiert wurden, kodieren Sie immer bei der Ausgabe!
+
+ **3. Content Security Policy (Verteidigungsebene)**
+ Content-Security-Policy:
+ default-src 'self';
+ script-src 'self' 'nonce-{random}';
+ style-src 'self' 'unsafe-inline';
+ img-src 'self' https:;
+ object-src 'none';
+ base-uri 'self';
+ form-action 'self';
+
+ CSP-Vorteile:
+ ⢠Verhindert Ausfßhrung von Inline-Skripten
+ ⢠Beschränkt Ressourcen-Laden auf vertrauenswßrdige Quellen
+ ⢠Mindert Auswirkungen, selbst wenn XSS durchkommt
+ ⢠Bietet Verletzungsberichte zur Ăberwachung
+
+ **4. HTTPOnly und Secure Cookies**
+ Set-Cookie: sessionId=abc123;
+ HttpOnly;
+ Secure;
+ SameSite=Strict
+
+ ⢠**HttpOnly** - Verhindert JavaScript-Zugriff auf Cookies
+ ⢠**Secure** - Stellt HTTPS-only-Ăbertragung sicher
+ ⢠**SameSite** - Verhindert CSRF-Angriffe
+
+ **5. Framework-Sicherheitsfunktionen**
+ Moderne Frameworks bieten eingebauten XSS-Schutz:
+
+ ⢠**React:** Escapt JSX-Inhalte automatisch
+ ⢠**Angular:** Eingebaute Bereinigung mit DomSanitizer
+ ⢠**Vue:** Template-Escaping standardmäĂig
+
+ â ď¸ **Verwenden Sie NIEMALS gefährliche Funktionen:**
+ ⢠React: `dangerouslySetInnerHTML`
+ ⢠Angular: `bypassSecurityTrust...` Methoden
+ ⢠Vue: `v-html` mit Benutzerinhalten
+ ⢠JavaScript: `eval()`, `innerHTML` mit Benutzerdaten
+
+ **6. RegelmäĂige Sicherheitsaudits**
+ ⢠Statische Code-Analyse (SAST-Tools)
+ ⢠Dynamische Sicherheitstests (DAST-Tools)
+ ⢠Penetrationstests
+ ⢠Code-Reviews mit Fokus auf Benutzereingabe-Verarbeitung
+ ⢠Sicherheitsbewusstseins-Schulungen fßr Entwickler
+
+ **7. Web Application Firewall (WAF)**
+ ⢠Kann XSS-Versuche erkennen und blockieren
+ ⢠Sollte als zusätzliche Ebene verwendet werden, nicht als primäre Verteidigung
+ ⢠Bietet Ăberwachung und Alarmierung
+ ⢠Updates zum Blockieren neuer Angriffsmuster
+
+scoring:
+ passingScore: 58
+ maxTotalPoints: 115 # 70 from questions + up to 45 from discovering XSS vectors
diff --git a/backend/lessons/configs/social-engineering-password.yaml b/backend/lessons/configs/social-engineering-password.yaml
new file mode 100644
index 0000000..9874033
--- /dev/null
+++ b/backend/lessons/configs/social-engineering-password.yaml
@@ -0,0 +1,290 @@
+lessonKey: "social-engineering-password"
+title: "Social Engineering - Passwortsicherheit"
+description: "Lernen Sie, wie persĂśnliche Informationen aus sozialen Medien zu schwachen PasswĂśrtern fĂźhren kĂśnnen"
+difficultyLevel: "beginner"
+estimatedDuration: 20
+module: "social-engineering-password"
+
+steps:
+ - id: "intro"
+ type: "content"
+ title: "Was ist Social Engineering?"
+ content: |
+ Social Engineering ist eine Manipulation von Menschen, um vertrauliche Informationen preiszugeben oder SicherheitsmaĂnahmen zu umgehen. Anders als technische Angriffe zielen Social-Engineering-Angriffe auf die menschliche Psychologie ab.
+
+ **Häufige Social-Engineering-Taktiken:**
+ ⢠Informationen aus sozialen Medien sammeln (OSINT)
+ ⢠PersÜnliche Details fßr PasswÜrter nutzen
+ ⢠Vertrauen ausnutzen
+ ⢠Dringlichkeit vortäuschen
+ ⢠Autorität vortäuschen
+ ⢠Neugier ausnutzen
+
+ **Warum ist das gefährlich?**
+ Menschen teilen freiwillig Informationen in sozialen Medien, die Angreifer nutzen kĂśnnen:
+ ⢠Namen von Haustieren
+ ⢠Geburtsdaten von Kindern
+ ⢠Lieblingsorte oder -teams
+ ⢠Geburtstage und Jubiläen
+ ⢠Arbeitgeber und Positionen
+ ⢠Hobbys und Interessen
+
+ Diese Informationen kĂśnnen verwendet werden, um:
+ ⢠PasswÜrter zu erraten
+ ⢠Sicherheitsfragen zu beantworten
+ ⢠Phishing-Angriffe zu personalisieren
+ ⢠Vertrauen zu gewinnen
+
+ - id: "osint"
+ type: "content"
+ title: "OSINT - Open Source Intelligence"
+ content: |
+ Open Source Intelligence (OSINT) bezeichnet das Sammeln von Informationen aus Üffentlich zugänglichen Quellen. Soziale Medien sind eine Goldgrube fßr OSINT.
+
+ **Was Angreifer aus Social Media lernen kĂśnnen:**
+
+ **Facebook/Instagram:**
+ ⢠Freunde und Familienmitglieder
+ ⢠Wohnort und Arbeitgeber
+ ⢠Reisen und Aufenthaltsorte
+ ⢠Haustiere (oft mit Namen)
+ ⢠Kinder (oft mit Alter/Geburtsjahr)
+ ⢠Hobbys und Interessen
+
+ **LinkedIn:**
+ ⢠Vollständige Berufshistorie
+ ⢠Bildungsweg
+ ⢠Fähigkeiten und Zertifizierungen
+ ⢠Geschäftskontakte
+ ⢠Arbeitszeiten und Verantwortlichkeiten
+
+ **Twitter/X:**
+ ⢠Echtzeitaktivitäten
+ ⢠Politische Ansichten
+ ⢠Tägliche Routinen
+ ⢠Technologie-Präferenzen
+
+ **Wie wird das ausgenutzt?**
+
+ 1. **Passwort-Erraten:**
+ ⢠Haustiername + Geburtsjahr des Kindes
+ ⢠Lieblingsverein + Hochzeitsjahr
+ ⢠Spitzname + Hausnummer
+
+ 2. **Sicherheitsfragen:**
+ ⢠"Name Ihres ersten Haustieres?" â Auf Instagram gepostet
+ ⢠"Geburtsort Ihrer Mutter?" â Im Profil erwähnt
+ ⢠"Name Ihrer ersten Schule?" â LinkedIn Bildung
+
+ 3. **Spear-Phishing:**
+ ⢠Personalisierte E-Mails mit echten Details
+ ⢠Vorwand, der auf Interessen basiert
+ ⢠Zeitlich abgestimmte Angriffe (wenn Sie im Urlaub sind)
+
+ **Beispiel:**
+ Ein Angreifer sieht auf Instagram:
+ ⢠Post ßber Hund "Max" (2019)
+ ⢠Post ßber Zwillinge "Emma & Liam" (geboren 2020)
+ ⢠Lieblingsverein "FC Bayern"
+
+ MĂśgliche PasswĂśrter zum Testen:
+ ⢠max2019
+ ⢠emma2020
+ ⢠bayern2020
+ ⢠maxbayern
+ ⢠emmaliam
+
+ - id: "social-media-demo"
+ type: "interactive"
+ title: "Social Media Profil & Passwort-Demo"
+ interactiveComponent: "SocialMediaPasswordDemo"
+ content: |
+ Unten sehen Sie ein simuliertes Social-Media-Profil einer fiktiven Person namens Sophia MĂźller. Ihre Aufgabe ist es, ihr Passwort zu erraten, indem Sie Informationen aus ihren Posts verwenden.
+
+ **Anleitung:**
+ 1. Lesen Sie die Posts im Social-Media-Profil sorgfältig
+ 2. Achten Sie auf persĂśnliche Details (Namen, Jahreszahlen, etc.)
+ 3. Versuchen Sie, das Passwort im Login-Formular zu erraten
+ 4. Nutzen Sie die Hinweise, wenn Sie feststecken
+
+ Dies demonstriert, wie leicht PasswĂśrter erraten werden kĂśnnen, wenn sie auf Ăśffentlich verfĂźgbaren Informationen basieren.
+
+ - id: "question-1"
+ type: "question"
+ questionType: "multiple_choice"
+ question: "Welche Informationen aus Social-Media-Profilen kĂśnnen fĂźr PasswĂśrter missbraucht werden?"
+ options:
+ - id: "pet-names"
+ text: "Namen von Haustieren"
+ isCorrect: true
+ points: 10
+ - id: "birth-years"
+ text: "Geburtsjahre von Kindern"
+ isCorrect: true
+ points: 10
+ - id: "favorite-teams"
+ text: "Lieblingssportvereine oder -teams"
+ isCorrect: true
+ points: 10
+ - id: "profile-picture"
+ text: "Das Profilbild selbst"
+ isCorrect: false
+ points: 0
+ - id: "anniversaries"
+ text: "Hochzeitstage oder Jubiläen"
+ isCorrect: true
+ points: 10
+ maxPoints: 40
+ feedback:
+ correct: "Richtig! Alle diese persÜnlichen Informationen werden häufig in unsicheren PasswÜrtern verwendet und sind leicht aus Social-Media-Profilen zu extrahieren."
+ partial: "Gut! Sie haben einige der gefährlichen Informationen erkannt. Denken Sie daran, dass fast alle persÜnlichen Details missbraucht werden kÜnnen."
+ incorrect: "ĂberprĂźfen Sie das Demo. Namen, Jahreszahlen und persĂśnliche Vorlieben aus Social Media kĂśnnen alle fĂźr PasswĂśrter verwendet werden."
+
+ - id: "password-patterns"
+ type: "content"
+ title: "Häufige Passwort-Muster"
+ content: |
+ **Die häufigsten unsicheren Passwort-Muster:**
+
+ **1. Name + Jahreszahl**
+ ⢠bella2018
+ ⢠max2020
+ ⢠luna2019
+ Warum unsicher: Beide Teile sind oft Ăśffentlich bekannt
+
+ **2. Wort + einfache Ziffernfolge**
+ ⢠passwort123
+ ⢠sommer2024
+ ⢠welcome1
+ Warum unsicher: Sehr vorhersagbar, oft in WĂśrterbĂźchern
+
+ **3. Tastaturmuster**
+ ⢠qwertz
+ ⢠asdfgh
+ ⢠123456
+ Warum unsicher: Erste Option bei Brute-Force-Angriffen
+
+ **4. PersĂśnliche Informationen**
+ ⢠vorname.nachname
+ ⢠geburtsdatum
+ ⢠telefonnummer
+ Warum unsicher: Leicht zu recherchieren
+
+ **5. Einfache Substitutionen**
+ ⢠P@ssw0rt (Passwort)
+ ⢠H3ll0 (Hello)
+ Warum unsicher: Angreifer kennen diese Tricks
+
+ **Statistiken:**
+ ⢠73% der Menschen verwenden PasswÜrter, die persÜnliche Informationen enthalten
+ ⢠50% der PasswÜrter sind kßrzer als 10 Zeichen
+ ⢠35% verwenden denselben Passwort-Typen ßberall
+ ⢠Die häufigsten Passwort-Bestandteile:
+ 1. Namen (Personen, Haustiere)
+ 2. Geburtsjahre
+ 3. Einfache WĂśrter ("Passwort", "Admin")
+ 4. Zahlenfolgen (123456, 111111)
+ 5. Sportvereine oder Marken
+
+ **Warum verwenden Menschen schwache PasswĂśrter?**
+ ⢠Leicht zu merken
+ ⢠Bequemlichkeit
+ ⢠Mangelndes Sicherheitsbewusstsein
+ ⢠Zu viele Konten zum Verwalten
+ ⢠Unterschätzung des Risikos
+
+ - id: "question-2"
+ type: "question"
+ questionType: "single_choice"
+ question: "Was ist die BESTE Methode fĂźr sichere PasswĂśrter?"
+ options:
+ - id: "same-password"
+ text: "Ein sehr langes Passwort fĂźr alle Konten verwenden"
+ isCorrect: false
+ points: 0
+ - id: "password-manager"
+ text: "Einen Passwort-Manager mit zufällig generierten PasswÜrtern verwenden"
+ isCorrect: true
+ points: 30
+ - id: "write-down"
+ text: "Komplexe PasswĂśrter aufschreiben und sicher aufbewahren"
+ isCorrect: false
+ points: 0
+ - id: "substitution"
+ text: "WĂśrter mit Zahlen und Sonderzeichen ersetzen (z.B. P@ssw0rt)"
+ isCorrect: false
+ points: 0
+ maxPoints: 30
+ feedback:
+ correct: "Ausgezeichnet! Passwort-Manager generieren einzigartige, zufällige PasswÜrter fßr jedes Konto und speichern sie verschlßsselt. Sie mßssen sich nur ein Master-Passwort merken."
+ incorrect: "Passwort-Manager sind die beste LÜsung. Sie generieren starke, zufällige PasswÜrter fßr jedes Konto, sodass Sie sich nur ein Master-Passwort merken mßssen. Einfache Substitutionen oder wiederverwendete PasswÜrter sind nicht sicher."
+
+ - id: "digital-footprint"
+ type: "content"
+ title: "Digitaler FuĂabdruck und Privatsphäre"
+ content: |
+ **Was Sie NICHT in Social Media teilen sollten:**
+
+ **đŤ Vermeiden Sie diese Informationen:**
+
+ **Passwort-relevante Details:**
+ ⢠Namen von Haustieren (besonders mit Geburtsjahren)
+ ⢠Geburtsdaten von Kindern
+ ⢠Mädchenname der Mutter
+ ⢠Erste Schule oder Wohnort
+ ⢠Lieblingsteam oder -verein
+ ⢠Hochzeitsdatum
+ ⢠Wichtige Jubiläen
+
+ **Sicherheitsrelevante Details:**
+ ⢠Vollständige Adresse
+ ⢠Reisepläne (vor der Reise)
+ ⢠Arbeitspläne und Routinen
+ ⢠Finanzdaten oder Erfolge
+ ⢠Vollständiges Geburtsdatum
+ ⢠Telefonnummer
+ ⢠E-Mail-Adresse (Üffentlich)
+
+ **Kinder-bezogene Informationen:**
+ ⢠Vollständige Namen und Alter
+ ⢠Schule oder Kindergarten
+ ⢠Routinen und Zeitpläne
+ ⢠Genauer Wohnort
+ ⢠Fotos mit Standort-Tags
+
+ **Best Practices fĂźr Social Media:**
+
+ **â Datenschutz-Einstellungen:**
+ ⢠Profil auf "privat" stellen
+ ⢠Freundesliste verbergen
+ ⢠Standortdienste deaktivieren
+ ⢠Gesichtserkennung deaktivieren
+ ⢠Suchmaschinen-Indexierung verhindern
+
+ **â Vorsichtiges Teilen:**
+ ⢠Ăberlegen Sie, wer es sehen kann
+ ⢠Posten Sie Urlaubsfotos NACH der Rßckkehr
+ ⢠Verwenden Sie Spitznamen statt echte Namen
+ ⢠Vermeiden Sie detaillierte Standortangaben
+ ⢠Keine Fotos von Haus/Auto mit erkennbaren Merkmalen
+
+ **â RegelmäĂige ĂberprĂźfung:**
+ ⢠Alte Posts durchgehen und lÜschen
+ ⢠Freundesliste aufräumen
+ ⢠Datenschutz-Einstellungen aktualisieren
+ ⢠Verknßpfte Apps ßberprßfen
+ ⢠Suchmaschinen-Ergebnisse fßr Ihren Namen prßfen
+
+ **Denken Sie daran:**
+ Alles, was Sie online posten, kann:
+ ⢠Fßr immer gespeichert werden
+ ⢠Screenshot und geteilt werden
+ ⢠Von Arbeitgebern gefunden werden
+ ⢠Gegen Sie verwendet werden
+ ⢠Nicht vollständig gelÜscht werden
+
+ **"Wenn Sie es nicht jedem Fremden auf der StraĂe erzählen wĂźrden, posten Sie es nicht online!"**
+
+scoring:
+ passingScore: 65
+ maxTotalPoints: 130 # 70 from questions + 30-60 from cracking password (based on attempts)
diff --git a/backend/lessons/configs/sql-injection-shop.yaml b/backend/lessons/configs/sql-injection-shop.yaml
index e9b4438..e1f9b30 100644
--- a/backend/lessons/configs/sql-injection-shop.yaml
+++ b/backend/lessons/configs/sql-injection-shop.yaml
@@ -1,6 +1,6 @@
lessonKey: "sql-injection-shop"
-title: "SQL Injection Attack - Online Shop Demo"
-description: "Learn how SQL injection vulnerabilities work through a realistic online shop scenario"
+title: "SQL Injection Angriff - Online Shop Demo"
+description: "Lernen Sie, wie SQL Injection-Schwachstellen funktionieren, anhand eines realistischen Online-Shop-Szenarios"
difficultyLevel: "intermediate"
estimatedDuration: 20
module: "sql-injection-shop"
@@ -8,30 +8,30 @@ module: "sql-injection-shop"
steps:
- id: "intro"
type: "content"
- title: "What is SQL Injection?"
+ title: "Was ist SQL Injection?"
content: |
- SQL Injection is one of the most dangerous web application vulnerabilities. It occurs when an attacker can insert malicious SQL code into a query, allowing them to:
+ SQL Injection ist eine der gefährlichsten Schwachstellen in Webanwendungen. Sie tritt auf, wenn ein Angreifer bÜsartigen SQL-Code in eine Abfrage einfßgen kann, wodurch er folgendes tun kann:
- ⢠Access unauthorized data
- ⢠Modify or delete database records
- ⢠Bypass authentication
- ⢠Execute administrative operations
+ ⢠Auf nicht autorisierte Daten zugreifen
+ ⢠Datenbankeinträge ändern oder lÜschen
+ ⢠Authentifizierung umgehen
+ ⢠Administrative Operationen ausfßhren
- In this lesson, you'll explore a vulnerable online shop to understand how SQL injection works and why proper input validation is critical.
+ In dieser Lektion werden Sie einen verwundbaren Online-Shop erkunden, um zu verstehen, wie SQL Injection funktioniert und warum korrekte Eingabevalidierung entscheidend ist.
- id: "shop-demo"
type: "interactive"
- title: "Vulnerable Online Shop"
+ title: "Verwundbarer Online-Shop"
interactiveComponent: "SQLShopDemo"
content: |
- Below is a simplified online shop with a product search feature. The search functionality is vulnerable to SQL injection.
+ Unten sehen Sie einen vereinfachten Online-Shop mit einer Produktsuchfunktion. Die Suchfunktion ist anfällig fßr SQL Injection.
- Try searching for normal products first, then experiment with SQL injection techniques.
+ Versuchen Sie zunächst, nach normalen Produkten zu suchen, und experimentieren Sie dann mit SQL Injection-Techniken.
- id: "question-1"
type: "question"
questionType: "multiple_choice"
- question: "Which of the following search inputs could be used to exploit SQL injection?"
+ question: "Welche der folgenden Sucheingaben kĂśnnten verwendet werden, um SQL Injection auszunutzen?"
options:
- id: "normal-search"
text: "laptop"
@@ -51,93 +51,79 @@ steps:
points: 10
maxPoints: 40
feedback:
- correct: "Correct! These inputs manipulate the SQL query structure."
- incorrect: "Review the demo. SQL injection exploits use special characters like quotes and SQL keywords."
+ correct: "Richtig! Diese Eingaben manipulieren die SQL-Abfragestruktur."
+ incorrect: "ĂberprĂźfen Sie die Demo. SQL Injection-Exploits verwenden Sonderzeichen wie AnfĂźhrungszeichen und SQL-SchlĂźsselwĂśrter."
- id: "detection"
type: "content"
- title: "How SQL Injection Works"
+ title: "Wie SQL Injection funktioniert"
content: |
- A vulnerable query might look like:
+ Eine verwundbare Abfrage kĂśnnte so aussehen:
SELECT * FROM products WHERE name LIKE '%[USER_INPUT]%'
- When a user searches for "laptop", the query becomes:
+ Wenn ein Benutzer nach "laptop" sucht, wird die Abfrage zu:
SELECT * FROM products WHERE name LIKE '%laptop%'
- But if they enter "' OR '1'='1", it becomes:
+ Wenn er aber "' OR '1'='1" eingibt, wird sie zu:
SELECT * FROM products WHERE name LIKE '%' OR '1'='1%'
- The OR '1'='1' condition is always true, so ALL products are returned!
+ Die Bedingung OR '1'='1' ist immer wahr, also werden ALLE Produkte zurĂźckgegeben!
- More dangerous attacks can extract data from other tables or even delete data.
+ Gefährlichere Angriffe kÜnnen Daten aus anderen Tabellen extrahieren oder sogar Daten lÜschen.
- id: "question-2"
type: "question"
questionType: "single_choice"
- question: "What is the BEST way to prevent SQL injection vulnerabilities?"
+ question: "Was ist der BESTE Weg, um SQL Injection-Schwachstellen zu verhindern?"
options:
- id: "input-filtering"
- text: "Filter out dangerous characters like quotes and semicolons"
+ text: "Gefährliche Zeichen wie Anfßhrungszeichen und Semikolons herausfiltern"
isCorrect: false
points: 0
- id: "parameterized-queries"
- text: "Use parameterized queries (prepared statements)"
+ text: "Parametrisierte Abfragen (Prepared Statements) verwenden"
isCorrect: true
points: 30
- id: "stored-procedures"
- text: "Only use stored procedures for database access"
+ text: "Nur gespeicherte Prozeduren fĂźr den Datenbankzugriff verwenden"
isCorrect: false
points: 0
- id: "input-length"
- text: "Limit the length of user inputs"
+ text: "Die Länge von Benutzereingaben begrenzen"
isCorrect: false
points: 0
maxPoints: 30
feedback:
- correct: "Excellent! Parameterized queries separate SQL code from user data, making injection impossible."
- incorrect: "While filtering helps, parameterized queries are the gold standard. They ensure user input is always treated as data, never as SQL code."
+ correct: "Ausgezeichnet! Parametrisierte Abfragen trennen SQL-Code von Benutzerdaten und machen Injection unmĂśglich."
+ incorrect: "Während Filterung hilft, sind parametrisierte Abfragen der Goldstandard. Sie stellen sicher, dass Benutzereingaben immer als Daten behandelt werden, niemals als SQL-Code."
- id: "mitigation"
type: "content"
- title: "Preventing SQL Injection"
+ title: "SQL Injection verhindern"
content: |
- Best practices to prevent SQL injection:
+ Best Practices zur Verhinderung von SQL Injection:
- 1. **Parameterized Queries** (Most Important)
- ⢠Use prepared statements with bound parameters
- ⢠Never concatenate user input into SQL strings
+ 1. **Parametrisierte Abfragen** (Am wichtigsten)
+ ⢠Prepared Statements mit gebundenen Parametern verwenden
+ ⢠Niemals Benutzereingaben in SQL-Strings konkatenieren
- 2. **Input Validation**
- ⢠Validate data types (numbers, emails, etc.)
- ⢠Use allowlists for expected values
+ 2. **Eingabevalidierung**
+ ⢠Datentypen validieren (Zahlen, E-Mails, etc.)
+ ⢠Allowlists fßr erwartete Werte verwenden
- 3. **Least Privilege**
- ⢠Database accounts should have minimal permissions
- ⢠Read-only accounts for read operations
+ 3. **Minimale Berechtigungen**
+ ⢠Datenbankkonten sollten minimale Berechtigungen haben
+ ⢠Nur-Lese-Konten fßr Leseoperationen
4. **Web Application Firewalls**
- ⢠Can detect and block SQL injection attempts
- ⢠Should be used as an additional layer, not primary defense
+ ⢠KÜnnen SQL Injection-Versuche erkennen und blockieren
+ ⢠Sollten als zusätzliche Ebene verwendet werden, nicht als primäre Verteidigung
- 5. **Regular Security Audits**
- ⢠Code reviews and penetration testing
- ⢠Automated vulnerability scanning
-
- - id: "question-3"
- type: "question"
- questionType: "free_text"
- question: "In your own words, explain why parameterized queries prevent SQL injection."
- validationRules:
- keywords:
- required: ["parameter", "data", "separate"]
- partialCredit: 10
- minLength: 50
- maxPoints: 30
- feedback:
- correct: "Great explanation! You understand that parameterized queries keep SQL structure separate from user data."
- incorrect: "Think about how parameterized queries treat user input differently than string concatenation. Key concepts: separation of code and data."
+ 5. **RegelmäĂige Sicherheitsaudits**
+ ⢠Code-Reviews und Penetrationstests
+ ⢠Automatisiertes Schwachstellen-Scanning
scoring:
- passingScore: 70
- maxTotalPoints: 100
+ passingScore: 90
+ maxTotalPoints: 180 # 70 from questions + up to 110 from 3 simplified challenges (30+40+80) with time bonuses
diff --git a/backend/lessons/configs/xss-comprehensive.yaml b/backend/lessons/configs/xss-comprehensive.yaml
new file mode 100644
index 0000000..450d2f9
--- /dev/null
+++ b/backend/lessons/configs/xss-comprehensive.yaml
@@ -0,0 +1,387 @@
+lessonKey: "xss-comprehensive"
+title: "Cross-Site Scripting (XSS) - Reflected & Stored Angriffe"
+description: "Lernen Sie, wie XSS-Angriffe durch URL-Manipulation und benutzergenerierte Inhalte funktionieren und wie man sie erkennt"
+difficultyLevel: "intermediate"
+estimatedDuration: 35
+module: "xss-comprehensive"
+
+steps:
+ - id: "intro"
+ type: "content"
+ title: "Was ist Cross-Site Scripting (XSS)?"
+ content: |
+ Cross-Site Scripting (XSS) ist eine SicherheitslĂźcke, die es Angreifern ermĂśglicht, bĂśsartigen JavaScript-Code in Webseiten einzuschleusen, die von anderen Benutzern angesehen werden.
+
+ XSS kann auftreten, wenn:
+ ⢠Benutzereingaben ohne ordnungsgemäĂe Bereinigung angezeigt werden
+ ⢠URL-Parameter im Seiteninhalt wiedergegeben werden
+ ⢠Benutzergenerierte Inhalte als HTML gerendert werden
+
+ **Arten von XSS:**
+ ⢠**Reflected XSS** - Payload ist Teil der Anfrage (z.B. URL-Parameter)
+ ⢠**Stored XSS** - Payload wird in der Datenbank gespeichert und anderen Benutzern angezeigt
+ ⢠**DOM-basiertes XSS** - Payload manipuliert direkt das Document Object Model
+
+ **Was Angreifer mit XSS tun kĂśnnen:**
+ ⢠Session-Cookies stehlen und Konten ßbernehmen
+ ⢠Benutzer auf Phishing-Seiten umleiten
+ ⢠Websites verunstalten
+ ⢠Keylogger installieren
+ ⢠Auf sensible Daten zugreifen
+ ⢠Malware verteilen
+
+ - id: "reflected-xss"
+ type: "content"
+ title: "Reflected XSS - URL-Parameter-Injection"
+ content: |
+ **Wie URL-Parameter funktionieren:**
+
+ Viele Websites verwenden URL-Parameter (auch Query-Strings genannt), um Daten zu Ăźbergeben:
+
+ https://beispiel-shop.com/produkt?name=Laptop&kategorie=Elektronik
+
+ In dieser URL:
+ ⢠name=Laptop ist ein Parameter
+ ⢠kategorie=Elektronik ist ein weiterer Parameter
+
+ **Deeplinks:**
+ Deeplinks sind URLs, die direkt auf bestimmte Inhalte innerhalb einer Website oder App verlinken. Sie enthalten oft Parameter, die den angezeigten Inhalt anpassen.
+
+ **Die SicherheitslĂźcke:**
+ Wenn eine Website URL-Parameterwerte ohne Bereinigung anzeigt, kann ein Angreifer bĂśsartigen Code einschleusen:
+
+ https://beispiel-shop.com/produkt?name=
+
+ Wenn die Seite den "name"-Parameter anzeigt, wird das Skript ausgefĂźhrt!
+
+ **Wie Reflected XSS funktioniert:**
+
+ Wenn eine anfällige Anwendung empfängt:
+ https://shop.com/suche?q=
+
+ Und es so anzeigt:
+
Suchergebnisse fĂźr:
+
+ Der Browser fĂźhrt das Script-Tag aus und fĂźhrt den Code des Angreifers aus!
+
+ - id: "xss-demo"
+ type: "interactive"
+ title: "Reflected XSS Demo"
+ interactiveComponent: "XSSDeeplinkDemo"
+ content: |
+ Unten sehen Sie eine Demonstration, wie Reflected XSS durch URL-Parameter-Injection funktioniert. Die anfällige Version zeigt Benutzereingaben direkt an, während die sichere Version Sonderzeichen kodiert.
+
+ Probieren Sie die Beispiel-Payloads aus, um zu sehen, wie verschiedene XSS-Techniken funktionieren. Beachten Sie, wie die Kodierung verhindert, dass der bĂśsartige Code ausgefĂźhrt wird.
+
+ - id: "question-1"
+ type: "question"
+ questionType: "multiple_choice"
+ question: "Welche der folgenden sind gĂźltige XSS-Payloads, die Ăźber URL-Parameter eingeschleust werden kĂśnnen?"
+ options:
+ - id: "script-alert"
+ text: ""
+ isCorrect: true
+ points: 6
+ - id: "img-onerror"
+ text: ""
+ isCorrect: true
+ points: 6
+ - id: "svg-onload"
+ text: ""
+ isCorrect: true
+ points: 6
+ - id: "iframe-src"
+ text: ""
+ isCorrect: true
+ points: 7
+ - id: "normal-text"
+ text: "Nur ein normaler Produktname"
+ isCorrect: false
+ points: 0
+ maxPoints: 25
+ feedback:
+ correct: "Ausgezeichnet! Sie haben alle XSS-Payloads identifiziert. Diese Muster kÜnnen JavaScript in anfälligen Anwendungen ausfßhren."
+ partial: "Gut! Sie haben einige XSS-Payloads erkannt. ĂberprĂźfen Sie die Muster: Script-Tags, Event-Handler und Protocol-Injections."
+ incorrect: "Schauen Sie sich die Demo an und suchen Sie nach Mustern, die HTML-Tags, Event-Handler oder JavaScript-Protokolle enthalten."
+
+ - id: "stored-xss"
+ type: "content"
+ title: "Stored XSS - Persistente Angriffe"
+ content: |
+ Stored XSS (Cross-Site Scripting) ist eine Art von Injection-Angriff, bei dem bĂśsartige Skripte dauerhaft auf einem Zielserver gespeichert werden. Im Gegensatz zu Reflected XSS, bei dem das Opfer auf einen bĂśsartigen Link klicken muss, betrifft Stored XSS alle Benutzer, die den kompromittierten Inhalt ansehen.
+
+ **Häufige Ziele:**
+ ⢠Forum-Beiträge und Kommentare
+ ⢠Benutzerprofile und Biografien
+ ⢠Produktbewertungen
+ ⢠Feedback-Formulare
+ ⢠Social-Media-Beiträge
+ ⢠Blog-Kommentare
+ ⢠Wiki-Seiten
+
+ **Auswirkungen:**
+ ⢠Cookie-Diebstahl und Session-Hijacking
+ ⢠Kontoßbernahme
+ ⢠Malware-Verteilung
+ ⢠Website-Verunstaltung
+ ⢠Phishing-Angriffe auf andere Benutzer
+ ⢠Keylogging
+ ⢠Datendiebstahl
+
+ **Warum Stored XSS besonders gefährlich ist:**
+ 1. Es bleibt in der Datenbank bestehen
+ 2. Es betrifft automatisch mehrere Benutzer
+ 3. Es erfordert kein Social Engineering zur Verbreitung
+ 4. Es kann ßber lange Zeiträume unentdeckt bleiben
+
+ - id: "real-world"
+ type: "content"
+ title: "Reale Stored-XSS-Angriffe"
+ content: |
+ **Samy Worm (MySpace, 2005)**
+ Samy Kamkar erstellte einen sich selbst verbreitenden XSS-Wurm in seinem MySpace-Profil, der ihn automatisch als Freund zu jedem Profil hinzufĂźgte, das ihn ansah. Der Wurm kopierte sich auch auf jedes infizierte Profil und verbreitete sich exponentiell.
+
+ Innerhalb von 20 Stunden waren Ăźber 1 Million Benutzer betroffen, was Samy zur beliebtesten Person auf MySpace machte. Die Website musste offline genommen werden, um den Wurm zu entfernen.
+
+ **TweetDeck XSS (Twitter, 2014)**
+ Eine Stored-XSS-Schwachstelle in TweetDeck ermĂśglichte es Angreifern, bĂśsartigen Code Ăźber Tweets einzuschleusen. Als andere Benutzer diese Tweets in TweetDeck ansahen, wurde der Code automatisch ausgefĂźhrt und verursachte:
+ ⢠Automatische Retweets der bÜsartigen Payload
+ ⢠Pop-up-Benachrichtigungen fßr alle Betrachter
+ ⢠Schnelle Verbreitung ßber die Plattform
+
+ **eBay Stored XSS (2015-2016)**
+ Mehrere Stored-XSS-Schwachstellen wurden in den Artikelbeschreibungen von eBay entdeckt. Angreifer konnten:
+ ⢠Code in Produktbeschreibungen einschleusen
+ ⢠Benutzeranmeldeinformationen stehlen, wenn Käufer Angebote ansahen
+ ⢠Benutzer auf Phishing-Seiten umleiten
+ ⢠Konten von Käufern und Verkäufern kompromittieren
+
+ **British Airways XSS (2018)**
+ Angreifer schleusten bĂśsartiges JavaScript Ăźber eine Stored-XSS-Schwachstelle in die Zahlungsseite von British Airways ein. Das Skript:
+ ⢠Erfasste Kreditkarteninformationen
+ ⢠Sendete Daten an vom Angreifer kontrollierte Server
+ ⢠Betraf ßber 380.000 Transaktionen
+ ⢠Kostete British Airways ßber 20 Millionen Pfund an Strafen
+
+ Diese Angriffe demonstrieren, warum Eingabevalidierung und Output-Encoding fĂźr jede Anwendung, die benutzergenerierte Inhalte akzeptiert, kritisch sind.
+
+ - id: "forum-demo"
+ type: "interactive"
+ title: "Stored XSS Forum Demo"
+ interactiveComponent: "ForumScriptDemo"
+ content: |
+ Unten sehen Sie ein vereinfachtes Forum, das Benutzerkommentare OHNE ordnungsgemäĂe Eingabevalidierung oder Output-Encoding akzeptiert. Versuchen Sie zuerst, normale Kommentare zu posten, und experimentieren Sie dann mit Script-Injection-Payloads.
+
+ Beachten Sie, wie die bĂśsartigen Skripte gespeichert werden und alle Benutzer betreffen wĂźrden, die das Forum ansehen. In dieser Demo zeigen wir die Payloads sicher als Text an, anstatt sie auszufĂźhren, mit klaren Warnungen, wenn eine Injection erkannt wird.
+
+ **Probieren Sie diese Aktionen:**
+ 1. Posten Sie einen normalen Kommentar, um sicheres Verhalten zu sehen
+ 2. Versuchen Sie Beispiel-XSS-Payloads, um die Erkennung zu sehen
+ 3. Verwenden Sie die Reload-Schaltfläche, um das Forum zurßckzusetzen
+
+ - id: "question-2"
+ type: "question"
+ questionType: "multiple_choice"
+ question: "Welche der folgenden Payloads kĂśnnten fĂźr Stored-XSS-Angriffe in einem Forum verwendet werden?"
+ options:
+ - id: "script-cookie"
+ text: ""
+ isCorrect: true
+ points: 6
+ - id: "img-steal"
+ text: ""
+ isCorrect: true
+ points: 6
+ - id: "svg-payload"
+ text: ""
+ isCorrect: true
+ points: 6
+ - id: "iframe-phishing"
+ text: ""
+ isCorrect: true
+ points: 7
+ - id: "normal-comment"
+ text: "Dies ist ein normaler Kommentar ohne bĂśsartigen Code"
+ isCorrect: false
+ points: 0
+ maxPoints: 25
+ feedback:
+ correct: "Ausgezeichnet! Sie haben alle gefährlichen Payloads identifiziert, die auf dem Server bestehen bleiben und mehrere Benutzer betreffen kÜnnen."
+ partial: "Gut! Sie haben einige Bedrohungen erkannt, aber ĂźberprĂźfen Sie die Muster, die Code-AusfĂźhrung durch HTML-Tags und Event-Handler ermĂśglichen."
+ incorrect: "ĂberprĂźfen Sie die Demo. Suchen Sie nach Mustern, die Script-Tags, Event-Handler wie onerror oder onload oder eingebettete Inhalte wie iframes enthalten."
+
+ - id: "attack-vectors"
+ type: "content"
+ title: "XSS-Angriffsvektoren"
+ content: |
+ Gängige Techniken, die Angreifer bei XSS-Angriffen verwenden:
+
+ **1. Cookie-Diebstahl**
+
+ Stiehlt Authentifizierungs-Cookies und ermĂśglicht KontoĂźbernahme. Der Angreifer kann dann jeden Benutzer imitieren, der den Kommentar angesehen hat.
+
+ **2. Session-Hijacking**
+
+ Extrahiert Session-Token aus dem Browser-Speicher und kompromittiert Benutzersitzungen.
+
+ **3. Keylogging**
+
+ Zeichnet jeden Tastendruck auf der Seite auf und erfasst PasswĂśrter und sensible Informationen.
+
+ **4. Verunstaltung**
+
+ Ăndert den sichtbaren Inhalt fĂźr alle Benutzer und beschädigt Reputation und Vertrauen.
+
+ **5. Phishing-Overlay**
+
+
+
+ Zeigt ein gefälschtes Login-Formular ßber der echten Seite an und erfasst Anmeldeinformationen.
+
+ **6. Kryptowährungs-Mining**
+
+ Mined heimlich Kryptowährung mit den CPU-Ressourcen der Besucher.
+
+ **7. Malware-Verteilung**
+
+ Leitet Benutzer zu Malware-Downloads oder Drive-by-Download-Angriffen um.
+
+ - id: "question-3"
+ type: "question"
+ questionType: "single_choice"
+ question: "Warum gilt Stored XSS im Allgemeinen als GEFĂHRLICHER als Reflected XSS?"
+ options:
+ - id: "easier-exploit"
+ text: "Es ist einfacher auszunutzen, da es keine Sonderzeichen erfordert"
+ isCorrect: false
+ points: 0
+ - id: "persistent-victims"
+ text: "Es bleibt auf dem Server bestehen und betrifft alle Benutzer, die den Inhalt ansehen, nicht nur diejenigen, die auf einen bĂśsartigen Link klicken"
+ isCorrect: true
+ points: 30
+ - id: "no-detection"
+ text: "Es kann nicht von Sicherheitstools oder Antiviren-Software erkannt werden"
+ isCorrect: false
+ points: 0
+ - id: "admin-access"
+ text: "Es gewährt Angreifern automatisch Administratorzugriff auf den Server"
+ isCorrect: false
+ points: 0
+ maxPoints: 30
+ feedback:
+ correct: "Perfekt! Stored XSS ist eine persistente Bedrohung, die viele Benutzer Ăźber die Zeit betreffen kann, ohne dass eine individuelle Zielerfassung erforderlich ist. Es bleibt in der Datenbank und wird jedes Mal ausgefĂźhrt, wenn jemand es ansieht."
+ incorrect: "Denken Sie Ăźber den Unterschied zwischen einer Payload, die an jedes Opfer gesendet werden muss, und einer, die einmal gespeichert wird und jeden betrifft. Persistenz und automatische Verbreitung sind die Hauptgefahren."
+
+ - id: "prevention"
+ type: "content"
+ title: "XSS-Angriffe verhindern"
+ content: |
+ **Defense-in-Depth-Ansatz:**
+
+ **1. Output-Encoding (Am wichtigsten)**
+ Kodieren Sie Ausgaben immer kontextabhängig:
+
+ ⢠**HTML-Kontext:** < wird zu <, > wird zu >
+ ⢠**JavaScript-Kontext:** Verwenden Sie JSON.stringify() fßr Daten
+ ⢠**URL-Kontext:** Verwenden Sie encodeURIComponent()
+ ⢠**CSS-Kontext:** Vermeiden Sie Benutzereingaben in CSS
+
+ **Vertrauen Sie niemals Inhalten aus der Datenbank** - selbst wenn sie bei der Eingabe validiert wurden, kodieren Sie immer bei der Ausgabe!
+
+ **2. Content Security Policy (CSP)**
+ Setzen Sie HTTP-Header, um Script-Quellen einzuschränken:
+
+ Content-Security-Policy:
+ default-src 'self';
+ script-src 'self' 'nonce-{random}';
+ object-src 'none';
+ base-uri 'self';
+ form-action 'self';
+
+ CSP-Vorteile:
+ ⢠Verhindert Ausfßhrung von Inline-Skripten
+ ⢠Beschränkt Ressourcen-Laden auf vertrauenswßrdige Quellen
+ ⢠Mindert Auswirkungen, selbst wenn XSS durchkommt
+ ⢠Bietet Verletzungsberichte zur Ăberwachung
+
+ **3. Eingabevalidierung**
+ ⢠Validieren Sie alle Benutzereingaben gegen das erwartete Format
+ ⢠Verwenden Sie Allowlists fßr akzeptable Zeichen
+ ⢠Lehnen Sie Eingaben ab, die verdächtige Muster enthalten
+ ⢠Validieren Sie Datentyp, Länge und Format
+ ⢠Vertrauen Sie niemals allein auf clientseitige Validierung
+
+ **4. HTTPOnly und Secure Cookies**
+ Setzen Sie das HTTPOnly-Flag auf Session-Cookies:
+ Set-Cookie: sessionId=abc123;
+ HttpOnly;
+ Secure;
+ SameSite=Strict
+
+ ⢠**HttpOnly** - Verhindert JavaScript-Zugriff auf Cookies
+ ⢠**Secure** - Stellt HTTPS-only-Ăbertragung sicher
+ ⢠**SameSite** - Verhindert CSRF-Angriffe
+
+ Dies verhindert, dass JavaScript auf Cookies zugreift und begrenzt die Auswirkungen von XSS.
+
+ **5. Web Application Firewall (WAF)**
+ ⢠Kann XSS-Versuche erkennen und blockieren
+ ⢠Sollte als zusätzliche Ebene verwendet werden, nicht als primäre Verteidigung
+ ⢠Bietet Ăberwachung und Alarmierung
+ ⢠Updates zum Blockieren neuer Angriffsmuster
+
+ **6. RegelmäĂige Sicherheitsaudits**
+ ⢠Statische Code-Analyse (SAST-Tools)
+ ⢠Dynamische Sicherheitstests (DAST-Tools)
+ ⢠Penetrationstests
+ ⢠Code-Reviews mit Fokus auf Benutzereingabe-Verarbeitung
+ ⢠Sicherheitsbewusstseins-Schulungen
+
+ - id: "question-4"
+ type: "question"
+ questionType: "single_choice"
+ question: "Was ist der EFFEKTIVSTE Weg, XSS-Angriffe zu verhindern?"
+ options:
+ - id: "input-length"
+ text: "Die Länge der Benutzereingabe begrenzen"
+ isCorrect: false
+ points: 0
+ - id: "output-encoding"
+ text: "Alle Ausgaben kodieren und Content Security Policy (CSP) implementieren"
+ isCorrect: true
+ points: 20
+ - id: "remove-tags"
+ text: "Alle HTML-Tags aus Benutzereingaben entfernen"
+ isCorrect: false
+ points: 0
+ - id: "client-validation"
+ text: "Nur clientseitige JavaScript-Validierung verwenden"
+ isCorrect: false
+ points: 0
+ maxPoints: 20
+ feedback:
+ correct: "Perfekt! Output-Encoding wandelt Sonderzeichen um, sodass Browser sie als Text und nicht als Code behandeln. CSP bietet eine zusätzliche Sicherheitsebene."
+ incorrect: "Während Eingabefilterung helfen kann, ist Output-Encoding unerlässlich. Sonderzeichen wie < und > mßssen in < und > umgewandelt werden, damit Browser sie als Text anzeigen, anstatt sie als HTML auszufßhren."
+
+scoring:
+ passingScore: 70
+ maxTotalPoints: 100
diff --git a/backend/lessons/configs/xss-deeplink-demo.yaml b/backend/lessons/configs/xss-deeplink-demo.yaml
new file mode 100644
index 0000000..78209c8
--- /dev/null
+++ b/backend/lessons/configs/xss-deeplink-demo.yaml
@@ -0,0 +1,211 @@
+lessonKey: "xss-deeplink-demo"
+title: "Cross-Site Scripting (XSS) - Deeplink Injection"
+description: "Lernen Sie, wie XSS-Angriffe durch URL-Parameter-Manipulation und Deeplink-Injection funktionieren"
+difficultyLevel: "intermediate"
+estimatedDuration: 20
+module: "xss-deeplink-demo"
+
+steps:
+ - id: "intro"
+ type: "content"
+ title: "Was ist Cross-Site Scripting (XSS)?"
+ content: |
+ Cross-Site Scripting (XSS) ist eine SicherheitslĂźcke, die es Angreifern ermĂśglicht, bĂśsartigen JavaScript-Code in Webseiten einzuschleusen, die von anderen Benutzern angesehen werden.
+
+ XSS kann auftreten, wenn:
+ ⢠Benutzereingaben ohne ordnungsgemäĂe Bereinigung angezeigt werden
+ ⢠URL-Parameter im Seiteninhalt wiedergegeben werden
+ ⢠Benutzergenerierte Inhalte als HTML gerendert werden
+
+ **Arten von XSS:**
+ ⢠**Reflected XSS** - Payload ist Teil der Anfrage (z.B. URL-Parameter)
+ ⢠**Stored XSS** - Payload wird in der Datenbank gespeichert und anderen Benutzern angezeigt
+ ⢠**DOM-basiertes XSS** - Payload manipuliert direkt das Document Object Model
+
+ **Was Angreifer mit XSS tun kĂśnnen:**
+ ⢠Session-Cookies stehlen und Konten ßbernehmen
+ ⢠Benutzer auf Phishing-Seiten umleiten
+ ⢠Websites verunstalten
+ ⢠Keylogger installieren
+ ⢠Auf sensible Daten zugreifen
+
+ - id: "url-params"
+ type: "content"
+ title: "Wie URL-Parameter funktionieren"
+ content: |
+ Viele Websites verwenden URL-Parameter (auch Query-Strings genannt), um Daten zu Ăźbergeben:
+
+ https://beispiel-shop.com/produkt?name=Laptop&kategorie=Elektronik
+
+ In dieser URL:
+ ⢠name=Laptop ist ein Parameter
+ ⢠kategorie=Elektronik ist ein weiterer Parameter
+
+ **Deeplinks:**
+ Deeplinks sind URLs, die direkt auf bestimmte Inhalte innerhalb einer Website oder App verlinken. Sie enthalten oft Parameter, die den angezeigten Inhalt anpassen.
+
+ **Die SicherheitslĂźcke:**
+ Wenn eine Website URL-Parameterwerte ohne Bereinigung anzeigt, kann ein Angreifer bĂśsartigen Code einschleusen:
+
+ https://beispiel-shop.com/produkt?name=
+
+ Wenn die Seite den "name"-Parameter anzeigt, wird das Skript ausgefĂźhrt!
+
+ - id: "xss-demo"
+ type: "interactive"
+ title: "XSS Deeplink Demo"
+ interactiveComponent: "XSSDeeplinkDemo"
+ content: |
+ Unten sehen Sie eine Demonstration, wie XSS durch URL-Parameter-Injection funktioniert. Die anfällige Version zeigt Benutzereingaben direkt an, während die sichere Version Sonderzeichen kodiert.
+
+ Probieren Sie die Beispiel-Payloads aus, um zu sehen, wie verschiedene XSS-Techniken funktionieren. Beachten Sie, wie die Kodierung verhindert, dass der bĂśsartige Code ausgefĂźhrt wird.
+
+ - id: "question-1"
+ type: "question"
+ questionType: "multiple_choice"
+ question: "Welche der folgenden sind gĂźltige XSS-Payloads, die Ăźber URL-Parameter eingeschleust werden kĂśnnen?"
+ options:
+ - id: "script-alert"
+ text: ""
+ isCorrect: true
+ points: 10
+ - id: "img-onerror"
+ text: ""
+ isCorrect: true
+ points: 10
+ - id: "svg-onload"
+ text: ""
+ isCorrect: true
+ points: 10
+ - id: "iframe-src"
+ text: ""
+ isCorrect: true
+ points: 10
+ - id: "normal-text"
+ text: "Nur ein normaler Produktname"
+ isCorrect: false
+ points: 0
+ maxPoints: 40
+ feedback:
+ correct: "Ausgezeichnet! Sie haben alle XSS-Payloads identifiziert. Diese Muster kÜnnen JavaScript in anfälligen Anwendungen ausfßhren."
+ partial: "Gut! Sie haben einige XSS-Payloads erkannt. ĂberprĂźfen Sie die Muster: Script-Tags, Event-Handler und Protocol-Injections."
+ incorrect: "Schauen Sie sich die Demo an und suchen Sie nach Mustern, die HTML-Tags, Event-Handler oder JavaScript-Protokolle enthalten."
+
+ - id: "detection-impact"
+ type: "content"
+ title: "XSS-Erkennung und Auswirkungen"
+ content: |
+ **Wie XSS funktioniert:**
+
+ Wenn eine anfällige Anwendung empfängt:
+ https://shop.com/suche?q=
+
+ Und es so anzeigt:
+
Suchergebnisse fĂźr:
+
+ Der Browser fĂźhrt das Script-Tag aus und fĂźhrt den Code des Angreifers aus!
+
+ **Auswirkungen in der Praxis:**
+
+ **Cookie-Diebstahl:**
+
+ Sendet die Cookies des Opfers an den Server des Angreifers.
+
+ **Session-Hijacking:**
+ Sobald der Angreifer den Session-Cookie hat, kann er sich als Benutzer ausgeben und auf dessen Konto zugreifen.
+
+ **Phishing:**
+
+ Ersetzt die Seite durch ein gefälschtes Login-Formular.
+
+ **Keylogging:**
+
+ Zeichnet jeden Tastendruck auf der Seite auf.
+
+ - id: "question-2"
+ type: "question"
+ questionType: "single_choice"
+ question: "Was ist der EFFEKTIVSTE Weg, XSS-Angriffe zu verhindern?"
+ options:
+ - id: "input-length"
+ text: "Die Länge der Benutzereingabe begrenzen"
+ isCorrect: false
+ points: 0
+ - id: "output-encoding"
+ text: "Alle Ausgaben kodieren und Content Security Policy (CSP) implementieren"
+ isCorrect: true
+ points: 30
+ - id: "remove-tags"
+ text: "Alle HTML-Tags aus Benutzereingaben entfernen"
+ isCorrect: false
+ points: 0
+ - id: "client-validation"
+ text: "Nur clientseitige JavaScript-Validierung verwenden"
+ isCorrect: false
+ points: 0
+ maxPoints: 30
+ feedback:
+ correct: "Perfekt! Output-Encoding wandelt Sonderzeichen um, sodass Browser sie als Text und nicht als Code behandeln. CSP bietet eine zusätzliche Sicherheitsebene."
+ incorrect: "Während Eingabefilterung helfen kann, ist Output-Encoding unerlässlich. Sonderzeichen wie < und > mßssen in < und > umgewandelt werden, damit Browser sie als Text anzeigen, anstatt sie als HTML auszufßhren."
+
+ - id: "mitigation"
+ type: "content"
+ title: "XSS-Angriffe verhindern"
+ content: |
+ **Best Practices:**
+
+ **1. Output-Encoding (Am wichtigsten)**
+ Kodieren Sie Ausgaben immer kontextabhängig:
+
+ ⢠**HTML-Kontext:** < wird zu <, > wird zu >
+ ⢠**JavaScript-Kontext:** Verwenden Sie JSON.stringify() fßr Daten
+ ⢠**URL-Kontext:** Verwenden Sie encodeURIComponent()
+ ⢠**CSS-Kontext:** Vermeiden Sie Benutzereingaben in CSS
+
+ **2. Content Security Policy (CSP)**
+ Setzen Sie HTTP-Header, um Script-Quellen einzuschränken:
+
+ Content-Security-Policy:
+ default-src 'self';
+ script-src 'self' 'nonce-{random}';
+ object-src 'none';
+
+ Dies verhindert Inline-Skripte und schränkt ein, woher Skripte geladen werden kÜnnen.
+
+ **3. Eingabevalidierung**
+ ⢠Validieren Sie Datentypen (Zahlen, E-Mails, etc.)
+ ⢠Verwenden Sie Allowlists fßr erwartete Werte
+ ⢠Lehnen Sie unerwartete Muster ab
+ ⢠Vertrauen Sie niemals allein auf clientseitige Validierung
+
+ **4. Framework-Sicherheitsfunktionen**
+ Moderne Frameworks helfen, XSS zu verhindern:
+
+ ⢠**React:** Escapt JSX-Inhalte automatisch
+ ⢠**Angular:** Eingebaute Bereinigung
+ ⢠**Vue:** Template-Escaping standardmäĂig
+
+ â ď¸ **Verwenden Sie NIEMALS gefährliche Funktionen:**
+ ⢠React: `dangerouslySetInnerHTML`
+ ⢠Angular: `bypassSecurityTrust...`
+ ⢠Vue: `v-html` mit Benutzerinhalten
+
+ **5. HTTPOnly Cookies**
+ Setzen Sie das HTTPOnly-Flag auf Session-Cookies:
+ Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict
+
+ Dies verhindert, dass JavaScript auf Cookies zugreift und begrenzt die Auswirkungen von XSS.
+
+scoring:
+ passingScore: 55
+ maxTotalPoints: 110 # 70 from questions + up to 40 from discovering XSS vectors
diff --git a/backend/lessons/modules/base/LessonModule.js b/backend/lessons/modules/base/LessonModule.js
index a7c7a6b..0b785af 100644
--- a/backend/lessons/modules/base/LessonModule.js
+++ b/backend/lessons/modules/base/LessonModule.js
@@ -183,20 +183,20 @@ class LessonModule {
/**
* Get lesson content for rendering (without answers)
*/
- getContent() {
- return {
- lessonKey: this.lessonKey,
- title: this.config.title,
- description: this.config.description,
- difficultyLevel: this.config.difficultyLevel,
- estimatedDuration: this.config.estimatedDuration,
- steps: this.config.steps.map(step => ({
+ async getContent() {
+ // Map steps and fetch interactive data for interactive steps
+ const steps = await Promise.all(this.config.steps.map(async step => {
+ const baseStep = {
id: step.id,
type: step.type,
title: step.title,
- content: step.content,
- // For question steps, don't send correct answers
- ...(step.type === 'question' && {
+ content: step.content
+ };
+
+ // For question steps, don't send correct answers
+ if (step.type === 'question') {
+ return {
+ ...baseStep,
questionType: step.questionType,
question: step.question,
maxPoints: step.maxPoints,
@@ -205,13 +205,30 @@ class LessonModule {
text: opt.text
// isCorrect and points are intentionally omitted
}))
- }),
- // For interactive steps, send component info
- ...(step.type === 'interactive' && {
+ };
+ }
+
+ // For interactive steps, fetch and include interactive data
+ if (step.type === 'interactive') {
+ const interactiveData = await this.getInteractiveData(step.id);
+ return {
+ ...baseStep,
interactiveComponent: step.interactiveComponent,
- componentProps: step.componentProps
- })
- })),
+ componentProps: step.componentProps,
+ interactiveData
+ };
+ }
+
+ return baseStep;
+ }));
+
+ return {
+ lessonKey: this.lessonKey,
+ title: this.config.title,
+ description: this.config.description,
+ difficultyLevel: this.config.difficultyLevel,
+ estimatedDuration: this.config.estimatedDuration,
+ steps,
scoring: {
maxTotalPoints: this.config.scoring?.maxTotalPoints || 100,
passingScore: this.config.scoring?.passingScore || 70
@@ -219,6 +236,44 @@ class LessonModule {
};
}
+ /**
+ * Award points for interactive component discoveries
+ * This method can be called by lesson modules to award points dynamically
+ * @param {number} participantId - Participant ID
+ * @param {number} eventLessonId - Event lesson ID
+ * @param {number} points - Points to award
+ * @param {string} reason - Reason for points (for tracking)
+ * @returns {Promise} New total score
+ */
+ async awardPoints(participantId, eventLessonId, points, reason) {
+ const progressQueries = require('../../src/models/queries/progress.queries');
+
+ // Get or create progress
+ let progress = await progressQueries.getLessonProgress(participantId, eventLessonId);
+
+ if (!progress) {
+ // Auto-start lesson if not started
+ progress = await progressQueries.startLesson(participantId, eventLessonId);
+ }
+
+ // Award points
+ const newScore = await progressQueries.updateScore(progress.id, points);
+
+ // Optionally save the discovery reason for tracking
+ if (reason) {
+ await progressQueries.saveAnswer(
+ progress.id,
+ `interactive-${Date.now()}`,
+ { type: 'interactive', reason },
+ true,
+ points,
+ reason
+ );
+ }
+
+ return newScore;
+ }
+
/**
* Get full configuration (for debugging/admin)
*/
diff --git a/backend/lessons/modules/idor-demo/index.js b/backend/lessons/modules/idor-demo/index.js
new file mode 100644
index 0000000..196968a
--- /dev/null
+++ b/backend/lessons/modules/idor-demo/index.js
@@ -0,0 +1,259 @@
+const LessonModule = require('../base/LessonModule');
+
+/**
+ * IDOR (Insecure Direct Object Reference) Demo Lesson
+ * Demonstrates how URL parameter manipulation can expose other users' data
+ */
+class IDORDemoLesson extends LessonModule {
+ constructor(config) {
+ super(config);
+ }
+
+ /**
+ * Get mock user database
+ * @returns {Array} Mock user data
+ */
+ getMockUsers() {
+ return [
+ {
+ id: 1,
+ name: 'System Administrator',
+ email: 'admin@securebank.example',
+ accountBalance: '$999,999.99',
+ accountNumber: '****0001',
+ lastLogin: '2026-02-08 10:00',
+ address: '1 Admin Tower, Capital City, USA',
+ phone: '(555) 000-0001',
+ isCurrentUser: false,
+ accountType: 'Administrative Account',
+ isHighValue: true,
+ adminAccess: true,
+ isEasterEgg: true,
+ easterEggType: 'admin',
+ bonusPoints: 25,
+ easterEggMessage: 'đŻ Admin Account Found! You discovered the system administrator account.'
+ },
+ {
+ id: 42,
+ name: 'Douglas Adams',
+ email: 'dont.panic@example.com',
+ accountBalance: '$42,000,000.00',
+ accountNumber: '****4242',
+ lastLogin: '2026-02-07 16:45',
+ address: '42 Galaxy Street, Universe, Space',
+ phone: '(555) 424-2424',
+ isCurrentUser: false,
+ accountType: 'Millionaire Account',
+ isHighValue: true,
+ isEasterEgg: true,
+ easterEggType: 'millionaire',
+ bonusPoints: 20,
+ easterEggMessage: 'đ° Millionaire Discovered! The answer to life, universe, and everything.'
+ },
+ {
+ id: 54,
+ name: 'Jane Smith',
+ email: 'jane.smith@example.com',
+ accountBalance: '$45,890.50',
+ accountNumber: '****5454',
+ lastLogin: '2026-02-08 08:30',
+ address: '456 Oak Avenue, Springfield, USA',
+ phone: '(555) 234-5678',
+ isCurrentUser: false,
+ accountType: 'Premium Savings',
+ securityLevel: 'high',
+ isNeighbor: true,
+ bonusPoints: 10
+ },
+ {
+ id: 55,
+ name: 'Max Mustermann',
+ email: 'max.mustermann@example.com',
+ accountBalance: '$2,340.75',
+ accountNumber: '****5555',
+ lastLogin: '2026-02-08 09:15',
+ address: '123 Main Street, Anytown, USA',
+ phone: '(555) 123-4567',
+ isCurrentUser: true,
+ accountType: 'Standard Checking'
+ },
+ {
+ id: 56,
+ name: 'Lisa Wagner',
+ email: 'lisa.w@example.com',
+ accountBalance: '$18,250.00',
+ accountNumber: '****5656',
+ lastLogin: '2026-02-08 07:45',
+ address: '789 Pine Road, Neighborhood, USA',
+ phone: '(555) 567-8901',
+ isCurrentUser: false,
+ accountType: 'Business Checking',
+ isNeighbor: true,
+ bonusPoints: 10
+ },
+ {
+ id: 67,
+ name: 'ÂŻ\\_(ă)_/ÂŻ',
+ email: 'mystery@example.com',
+ accountBalance: '$6,700.00',
+ accountNumber: '****6767',
+ lastLogin: '2026-01-01 00:00',
+ address: 'ÂŻ\\_(ă)_/ÂŻ',
+ phone: 'ÂŻ\\_(ă)_/ÂŻ',
+ isCurrentUser: false,
+ accountType: 'Mystery Account',
+ isEasterEgg: true,
+ easterEggType: 'shrug',
+ bonusPoints: 15,
+ easterEggMessage: 'ÂŻ\\_(ă)_/ÂŻ'
+ },
+ {
+ id: 100,
+ name: 'Diana Prince',
+ email: 'diana.p@example.com',
+ accountBalance: '$125,000.00',
+ accountNumber: '****1000',
+ lastLogin: '2026-02-08 07:00',
+ address: '100 Hero Boulevard, Metro City, USA',
+ phone: '(555) 100-0001',
+ isCurrentUser: false,
+ accountType: 'Premium Investment',
+ securityLevel: 'maximum'
+ }
+ ];
+ }
+
+ /**
+ * Fetch user profile by ID (vulnerable simulation)
+ * Called via executeLessonAction endpoint
+ * @param {number} userId - User ID to fetch
+ * @returns {Object} User profile data or error
+ */
+ async fetchUserProfile(userId, participantId, eventLessonId) {
+ const users = this.getMockUsers();
+ const requestedId = parseInt(userId);
+
+ // Find user
+ const user = users.find(u => u.id === requestedId);
+
+ if (!user) {
+ return {
+ success: false,
+ error: 'USER_NOT_FOUND',
+ message: 'Benutzer nicht gefunden',
+ statusCode: 404
+ };
+ }
+
+ // Detect unauthorized access
+ const isUnauthorized = !user.isCurrentUser;
+
+ // Award points for discoveries
+ let pointsAwarded = 0;
+ let discoveryMessage = null;
+
+ if (isUnauthorized && participantId && eventLessonId) {
+ // Award points for any IDOR discovery
+ pointsAwarded = 10;
+
+ // Check for easter eggs and award bonus points
+ if (user.isEasterEgg) {
+ pointsAwarded += user.bonusPoints;
+ discoveryMessage = user.easterEggMessage;
+ } else if (user.isNeighbor) {
+ pointsAwarded += user.bonusPoints;
+ }
+
+ // Award points (don't duplicate if same user accessed multiple times)
+ try {
+ await this.awardPoints(participantId, eventLessonId, pointsAwarded,
+ `IDOR discovered: User ${requestedId}`);
+ } catch (error) {
+ console.error('Failed to award IDOR points:', error);
+ }
+ }
+
+ return {
+ success: true,
+ user: {
+ id: user.id,
+ name: user.name,
+ email: user.email,
+ accountBalance: user.accountBalance,
+ accountNumber: user.accountNumber,
+ lastLogin: user.lastLogin,
+ address: user.address,
+ phone: user.phone,
+ accountType: user.accountType,
+ ...(user.isHighValue && { isHighValue: true }),
+ ...(user.adminAccess && { adminAccess: true }),
+ ...(user.securityLevel && { securityLevel: user.securityLevel })
+ },
+ isCurrentUser: user.isCurrentUser,
+ isUnauthorized,
+ pointsAwarded: pointsAwarded > 0 ? pointsAwarded : undefined,
+ easterEgg: user.isEasterEgg ? {
+ type: user.easterEggType,
+ message: discoveryMessage
+ } : undefined,
+ vulnerability: isUnauthorized ? {
+ type: 'IDOR',
+ severity: user.isHighValue || user.adminAccess ? 'CRITICAL' : 'HIGH',
+ description: 'â ď¸ IDOR-Schwachstelle entdeckt!',
+ message: `Sie sehen ${user.name}s private Daten ohne Berechtigung!`,
+ impact: 'Ein Angreifer kann auf sensible Informationen eines beliebigen Benutzers zugreifen, indem er einfach den userId-Parameter in der URL ändert.',
+ recommendation: 'Implementieren Sie ordnungsgemäĂe AutorisierungsprĂźfungen. ĂberprĂźfen Sie, ob der authentifizierte Benutzer die Berechtigung hat, auf die angeforderte Ressource zuzugreifen.',
+ cve: user.isHighValue ? 'Dies ist eine kritische Schwachstelle - Admin-/Hochwertkonto aufgerufen!' : null
+ } : null
+ };
+ }
+
+ /**
+ * Get interactive data for IDOR demo step
+ * @param {string} stepId - Step identifier
+ * @returns {Object} Interactive component data
+ */
+ async getInteractiveData(stepId) {
+ if (stepId === 'idor-demo') {
+ return {
+ baseUrl: 'https://securebank.example/profile',
+ currentUserId: 55,
+ vulnerableParameter: 'userId',
+ easterEggs: [
+ { id: 1, type: 'admin', found: false },
+ { id: 42, type: 'millionaire', found: false },
+ { id: 67, type: 'shrug', found: false },
+ { id: 54, type: 'neighbor', found: false },
+ { id: 56, type: 'neighbor', found: false }
+ ],
+ secureApproach: {
+ title: 'Sichere Implementierung',
+ description: 'Anstelle von URL-Parametern, verwenden Sie sitzungsbasierte Authentifizierung',
+ example: 'GET /profile (gibt nur die Daten des authentifizierten Benutzers zurĂźck)',
+ code: `
+// Anfällig (IDOR):
+app.get('/profile', (req, res) => {
+ const userId = req.query.userId; // â Jeder kann dies ändern!
+ const user = db.getUserById(userId);
+ res.json(user);
+});
+
+// Sicher (Sitzungsbasiert):
+app.get('/profile', authenticate, (req, res) => {
+ const userId = req.session.userId; // â Aus verifizierter Sitzung
+ if (req.params.userId && req.params.userId !== userId) {
+ return res.status(403).json({ error: 'Forbidden' });
+ }
+ const user = db.getUserById(userId);
+ res.json(user);
+});
+ `.trim()
+ }
+ };
+ }
+
+ return await super.getInteractiveData(stepId);
+ }
+}
+
+module.exports = IDORDemoLesson;
diff --git a/backend/lessons/modules/script-injection-forum/index.js b/backend/lessons/modules/script-injection-forum/index.js
new file mode 100644
index 0000000..dd3ea1c
--- /dev/null
+++ b/backend/lessons/modules/script-injection-forum/index.js
@@ -0,0 +1,236 @@
+const LessonModule = require('../base/LessonModule');
+
+/**
+ * Forum Script Injection Lesson
+ * Demonstrates stored XSS vulnerabilities in comment systems
+ */
+class ForumScriptInjectionLesson extends LessonModule {
+ constructor(config) {
+ super(config);
+ }
+
+ /**
+ * Detect script injection in comment content
+ * @param {string} content - Comment content
+ * @returns {boolean} True if script detected
+ */
+ detectScriptInjection(content) {
+ const patterns = [
+ /',
+ description: 'Attempts to steal session cookies'
+ },
+ {
+ label: 'Redirect Attack',
+ author: 'Malicious User',
+ payload: '',
+ description: 'Redirects users to malicious site'
+ },
+ {
+ label: 'DOM Manipulation',
+ author: 'Hacker',
+ payload: '',
+ description: 'Defaces the website'
+ },
+ {
+ label: 'Image Onerror XSS',
+ author: 'Sneaky',
+ payload: '',
+ description: 'Executes code via image error handler'
+ },
+ {
+ label: 'Phishing Overlay',
+ author: 'Phisher',
+ payload: '',
+ description: 'Creates fake login overlay'
+ }
+ ]
+ };
+ }
+
+ return await super.getInteractiveData(stepId);
+ }
+}
+
+module.exports = ForumScriptInjectionLesson;
diff --git a/backend/lessons/modules/social-engineering-password/index.js b/backend/lessons/modules/social-engineering-password/index.js
new file mode 100644
index 0000000..880d626
--- /dev/null
+++ b/backend/lessons/modules/social-engineering-password/index.js
@@ -0,0 +1,194 @@
+const LessonModule = require('../base/LessonModule');
+
+/**
+ * Social Engineering Password Demo Lesson
+ * Demonstrates how personal information from social media leads to weak passwords
+ */
+class SocialEngineeringPasswordLesson extends LessonModule {
+ constructor(config) {
+ super(config);
+ this.correctPassword = 'bella2018';
+ this.attempts = new Map(); // Track attempts per participant
+ }
+
+ /**
+ * Validate password guess
+ * Called via executeLessonAction endpoint
+ * @param {string} participantId - Participant identifier
+ * @param {string} password - Password guess
+ * @param {number} eventLessonId - Event lesson ID for point awards
+ * @returns {Object} Validation result with German feedback
+ */
+ async testPassword(participantId, password, eventLessonId) {
+ // Initialize attempt counter for this participant
+ if (!this.attempts.has(participantId)) {
+ this.attempts.set(participantId, 0);
+ }
+
+ const attemptCount = this.attempts.get(participantId) + 1;
+ this.attempts.set(participantId, attemptCount);
+
+ // Normalize input (case-insensitive, trim whitespace)
+ const normalizedInput = (password || '').toLowerCase().trim();
+ const isCorrect = normalizedInput === this.correctPassword;
+
+ // Award points for cracking the password
+ let pointsAwarded = 0;
+ if (isCorrect && participantId && eventLessonId) {
+ // Award bonus points based on attempts (fewer attempts = more points)
+ if (attemptCount <= 3) {
+ pointsAwarded = 60; // Expert: found quickly
+ } else if (attemptCount <= 5) {
+ pointsAwarded = 50; // Good: found with minimal hints
+ } else if (attemptCount <= 8) {
+ pointsAwarded = 40; // Average: needed some hints
+ } else {
+ pointsAwarded = 30; // Struggled: needed all hints
+ }
+
+ try {
+ await this.awardPoints(participantId, eventLessonId, pointsAwarded,
+ `Password cracked in ${attemptCount} attempts`);
+ } catch (error) {
+ console.error('Failed to award password points:', error);
+ }
+ }
+
+ // Progressive hints based on attempt count
+ let hint = null;
+ if (!isCorrect) {
+ if (attemptCount >= 8) {
+ hint = 'Tipp: Manche nutzer fĂźgennoch ein Sonderzeichen an ihr schwaches Passwort (.,?,!,_)';
+ } else if (attemptCount >= 5) {
+ hint = 'Tipp: Kombinieren Sie den Namen des Hundes mit der Jahreszahl aus den Posts';
+ } else if (attemptCount >= 3) {
+ hint = 'Tipp: Achten Sie auf persĂśnliche Details in den Social-Media-Posts';
+ }
+ }
+
+ return {
+ success: isCorrect,
+ attemptCount,
+ pointsAwarded,
+ message: isCorrect
+ ? 'Passwort korrekt! Sie haben die Schwachstelle erfolgreich identifiziert.'
+ : 'Passwort falsch. Versuchen Sie es erneut.',
+ hint,
+ explanation: isCorrect
+ ? 'Das Passwort "bella2018!" kombiniert den Hundenamen (Bella) mit dem Geburtsjahr der Zwillinge (2018). Dies ist ein häufiges und unsicheres Passwort-Muster, da diese Informationen leicht aus Social-Media-Profilen zu finden sind.'
+ : null,
+ securityTip: isCorrect
+ ? 'Verwenden Sie niemals persĂśnliche Informationen wie Haustiernamen, Geburtsdaten oder Namen von Familienmitgliedern in PasswĂśrtern. Nutzen Sie stattdessen einen Passwort-Manager mit generierten ZufallspasswĂśrtern.'
+ : null
+ };
+ }
+
+ /**
+ * Reset attempts for a participant (when using hint system)
+ * @param {string} participantId - Participant identifier
+ */
+ resetAttempts(participantId) {
+ this.attempts.delete(participantId);
+ }
+
+ /**
+ * Get interactive data for social media demo step
+ * @param {string} stepId - Step identifier
+ * @returns {Object} Interactive component data
+ */
+ async getInteractiveData(stepId) {
+ if (stepId === 'social-media-demo') {
+ return {
+ profile: {
+ name: 'Sophia MĂźller',
+ username: '@sophia.mueller',
+ bio: 'Mutter von Zwillingen đśđś | Hundeliebhaberin đ | Fotografin đ¸',
+ location: 'MĂźnchen, Deutschland',
+ joined: 'März 2016',
+ profileImage: 'đ¤', // Placeholder emoji
+ followers: 342,
+ following: 198,
+ posts: [
+ {
+ id: 1,
+ type: 'photo',
+ caption: 'Unsere Zwillinge sind heute 6 Jahre alt geworden! đđ Die Zeit vergeht so schnell! #2018Babies #Zwillinge #Geburtstag #StolzeMama',
+ imageDescription: '[Foto: Zwei Kinder vor einem Geburtstagskuchen mit "6" Kerzen, Dekoration zeigt "2018"]',
+ date: '2024-09-15',
+ likes: 89,
+ comments: 24,
+ timestamp: 'vor 5 Monaten'
+ },
+ {
+ id: 2,
+ type: 'photo',
+ caption: 'Bella liebt den Herbst! đđ Unser Golden Retriever hat so viel SpaĂ beim Spielen in den Blättern. #BellaTheDog #GoldenRetriever #HerbstspaĂ #Hundeliebe',
+ imageDescription: '[Foto: Golden Retriever namens Bella spielt in Herbstlaub]',
+ date: '2024-10-12',
+ likes: 156,
+ comments: 31,
+ timestamp: 'vor 4 Monaten'
+ },
+ {
+ id: 3,
+ type: 'text',
+ content: 'Bella ist jetzt seit 8 Jahren meine beste Freundin â¤ď¸đž Kann mir ein Leben ohne sie nicht mehr vorstellen!',
+ date: '2023-11-20',
+ likes: 203,
+ comments: 45,
+ timestamp: 'vor 1 Jahr'
+ },
+ {
+ id: 4,
+ type: 'photo',
+ caption: 'Familienausflug zum Starnberger See! âľď¸ Die Zwillinge lieben es hier. Bella auch! đ #FamilyTime #Bayern #Wochenende',
+ imageDescription: '[Foto: Familie am See, zwei Kinder und ein Hund]',
+ date: '2024-07-22',
+ likes: 124,
+ comments: 18,
+ timestamp: 'vor 7 Monaten'
+ },
+ {
+ id: 5,
+ type: 'photo',
+ caption: 'Erster Schultag fĂźr Emma und Liam! đâď¸ Meine Babys werden so groĂ! #Einschulung #Zwillinge #ProudMom',
+ imageDescription: '[Foto: Zwei Kinder mit SchultĂźten vor einer Schule]',
+ date: '2024-09-10',
+ likes: 267,
+ comments: 52,
+ timestamp: 'vor 5 Monaten'
+ }
+ ]
+ },
+ loginForm: {
+ username: 'sophia.mueller@email.de',
+ correctPassword: 'bella2018!',
+ passwordHint: 'Versuchen Sie, das Passwort aus den Informationen im Profil zu erraten...',
+ hints: [
+ 'Achten Sie auf Namen und Jahreszahlen in den Posts',
+ 'Viele Menschen verwenden Namen von Haustieren in PasswĂśrtern',
+ 'Kombinationen aus Namen und Jahreszahlen sind häufig'
+ ]
+ },
+ securityLessons: [
+ {
+ title: 'Offensichtliche Informationen',
+ description: 'Hundename (Bella) und Geburtsjahr der Kinder (2018) sind Ăśffentlich sichtbar'
+ },
+ {
+ title: 'Vorhersagbares Muster',
+ description: 'Name + Jahreszahl ist ein sehr häufiges Passwort-Muster'
+ },
+ {
+ title: 'OSINT Risiko',
+ description: 'Open Source Intelligence (OSINT) ermĂśglicht das Sammeln solcher Informationen'
+ }
+ ]
+ };
+ }
+
+ return await super.getInteractiveData(stepId);
+ }
+}
+
+module.exports = SocialEngineeringPasswordLesson;
diff --git a/backend/lessons/modules/sql-injection-shop/index.js b/backend/lessons/modules/sql-injection-shop/index.js
index 48a69e5..a5b1b72 100644
--- a/backend/lessons/modules/sql-injection-shop/index.js
+++ b/backend/lessons/modules/sql-injection-shop/index.js
@@ -1,10 +1,95 @@
const LessonModule = require('../base/LessonModule');
+const progressQueries = require('../../../src/models/queries/progress.queries');
+/**
+ * Beginner-Friendly SQL Injection Shop Lesson
+ * Simplified to 3 progressive challenges with helpful hints
+ *
+ * Activity data structure:
+ * {
+ * discoveries: ['GENERIC', 'BYPASS_FILTER', 'UNION_SELECT'],
+ * timerStart: timestamp,
+ * unionHintShown: boolean
+ * }
+ */
class SQLInjectionShopLesson extends LessonModule {
constructor(config) {
super(config);
}
+ /**
+ * Get activity data from database
+ */
+ async _getActivityData(participantId, eventLessonId) {
+ try {
+ const data = await progressQueries.getActivityData(participantId, eventLessonId);
+ console.log(`[SQL Injection] Loading activity data for participant ${participantId}, event ${eventLessonId}:`, data);
+ return {
+ discoveries: data.discoveries || [],
+ timerStart: data.timerStart || null,
+ unionHintShown: data.unionHintShown || false
+ };
+ } catch (error) {
+ console.error('[SQL Injection] Error loading activity data:', error);
+ return {
+ discoveries: [],
+ timerStart: null,
+ unionHintShown: false
+ };
+ }
+ }
+
+ /**
+ * Save activity data to database
+ */
+ async _saveActivityData(participantId, eventLessonId, activityData) {
+ try {
+ console.log(`[SQL Injection] Saving activity data for participant ${participantId}, event ${eventLessonId}:`, activityData);
+ await progressQueries.updateActivityData(participantId, eventLessonId, activityData);
+ console.log('[SQL Injection] Activity data saved successfully');
+ } catch (error) {
+ console.error('[SQL Injection] Error saving activity data:', error);
+ throw error; // Re-throw to see the error in the main flow
+ }
+ }
+
+ /**
+ * Start challenge timer
+ */
+ async startTimer(participantId, eventLessonId) {
+ const activityData = await this._getActivityData(participantId, eventLessonId);
+
+ if (!activityData.timerStart) {
+ activityData.timerStart = Date.now();
+ await this._saveActivityData(participantId, eventLessonId, activityData);
+ }
+
+ const discoveries = new Set(activityData.discoveries);
+ const totalDiscoveries = 3;
+
+ return {
+ started: true,
+ duration: 600, // 10 minutes in seconds
+ message: 'Timer gestartet! Du hast 10 Minuten Zeit.',
+ discoveries: {
+ found: discoveries.size,
+ total: totalDiscoveries,
+ types: Array.from(discoveries)
+ },
+ unionHintShown: activityData.unionHintShown
+ };
+ }
+
+ /**
+ * Get elapsed time for participant
+ */
+ async _getElapsedTime(participantId, eventLessonId) {
+ const activityData = await this._getActivityData(participantId, eventLessonId);
+ const start = activityData.timerStart;
+ if (!start) return 0;
+ return Math.floor((Date.now() - start) / 1000);
+ }
+
// Mock database with products
getMockDatabase() {
return {
@@ -13,25 +98,18 @@ class SQLInjectionShopLesson extends LessonModule {
{ id: 2, name: 'Wireless Mouse', price: 29.99, category: 'Accessories', stock: 50 },
{ id: 3, name: 'USB-C Cable', price: 12.99, category: 'Accessories', stock: 100 },
{ id: 4, name: 'Gaming Keyboard', price: 89.99, category: 'Electronics', stock: 25 },
- { id: 5, name: 'Monitor 27"', price: 349.99, category: 'Electronics', stock: 20 },
- { id: 6, name: 'Webcam HD', price: 79.99, category: 'Electronics', stock: 30 },
- { id: 7, name: 'Desk Lamp', price: 34.99, category: 'Office', stock: 40 },
- { id: 8, name: 'Notebook Set', price: 15.99, category: 'Office', stock: 60 }
+ { id: 5, name: 'Monitor 27"', price: 349.99, category: 'Electronics', stock: 20 }
],
users: [
{ id: 1, username: 'admin', password: 'hashed_admin_password', role: 'admin' },
{ id: 2, username: 'john_doe', password: 'hashed_user_password', role: 'customer' },
{ id: 3, username: 'jane_smith', password: 'hashed_user_password', role: 'customer' }
- ],
- orders: [
- { id: 1, user_id: 2, total: 1329.98, status: 'shipped' },
- { id: 2, user_id: 3, total: 89.99, status: 'processing' }
]
};
}
// Simulate vulnerable SQL query
- executeVulnerableQuery(searchTerm) {
+ async executeVulnerableQuery(searchTerm, participantId, eventLessonId) {
const db = this.getMockDatabase();
// Build the "vulnerable" query string for educational display
@@ -43,29 +121,84 @@ class SQLInjectionShopLesson extends LessonModule {
let results = [];
let injectionType = null;
let explanation = '';
+ let pointsAwarded = 0;
+ let isNewDiscovery = false;
+ let unionHintMessage = null;
+
+ // Load activity data from database
+ const activityData = await this._getActivityData(participantId, eventLessonId);
+ const discoveries = new Set(activityData.discoveries);
+ console.log(`[SQL Injection] Current discoveries:`, Array.from(discoveries));
if (injectionDetected) {
const injectionInfo = this.analyzeInjection(searchTerm);
injectionType = injectionInfo.type;
explanation = injectionInfo.explanation;
+ console.log(`[SQL Injection] Injection detected: ${injectionType}`);
+
+ // Check if this is a new discovery
+ isNewDiscovery = !discoveries.has(injectionType);
+ console.log(`[SQL Injection] Is new discovery: ${isNewDiscovery}`);
+
+ // Award points only for NEW discoveries
+ if (isNewDiscovery && participantId && eventLessonId) {
+ console.log(`[SQL Injection] Awarding points for new discovery: ${injectionType}`);
+ const pointsMap = {
+ 'GENERIC': 30, // Challenge 1: Discovering injection is possible
+ 'BYPASS_FILTER': 40, // Challenge 2: Showing all products
+ 'UNION_SELECT': 80 // Challenge 3: Extracting user data (Easter egg!)
+ };
+
+ pointsAwarded = pointsMap[injectionType] || 0;
+
+ // Time bonus
+ const elapsedTime = await this._getElapsedTime(participantId, eventLessonId);
+ if (elapsedTime > 0 && elapsedTime < 600) {
+ const timeBonus = Math.max(0, Math.floor((600 - elapsedTime) / 60));
+ if (timeBonus > 0) {
+ pointsAwarded += timeBonus;
+ explanation += ` đŻ Zeit-Bonus: +${timeBonus} Punkte!`;
+ }
+ }
+
+ try {
+ await this.awardPoints(participantId, eventLessonId, pointsAwarded,
+ `SQL Injection discovered: ${injectionType}`);
+
+ // Mark as discovered and save to database
+ discoveries.add(injectionType);
+ activityData.discoveries = Array.from(discoveries);
+ await this._saveActivityData(participantId, eventLessonId, activityData);
+
+ // Show UNION hint after completing challenge 2
+ if (injectionType === 'BYPASS_FILTER' && !activityData.unionHintShown) {
+ activityData.unionHintShown = true;
+ await this._saveActivityData(participantId, eventLessonId, activityData);
+
+ unionHintMessage = {
+ title: 'đŻ Neue Herausforderung freigeschaltet!',
+ content: 'Du kannst jetzt versuchen, Daten aus anderen Tabellen zu extrahieren! Die Datenbank hat eine "users" Tabelle mit den Spalten: id, username, password, role. Verwende UNION SELECT um diese Daten zu kombinieren. Die Anzahl der Spalten muss Ăźbereinstimmen (5 Spalten).',
+ hint: "Versuche: ' UNION SELECT id, username, password, role, 'X' FROM users--"
+ };
+ }
+ } catch (error) {
+ console.error('Failed to award SQL injection points:', error);
+ }
+ }
// Simulate different injection results
- if (injectionInfo.type === 'OR_ALWAYS_TRUE') {
- // Return all products (simulating OR '1'='1')
+ if (injectionInfo.type === 'BYPASS_FILTER') {
+ // Return all products
results = db.products;
} else if (injectionInfo.type === 'UNION_SELECT') {
// Simulate UNION attack showing user data
results = [
- { id: 'INJECTED', name: 'admin', price: 'hashed_admin_password', category: 'LEAKED DATA', stock: 'admin' },
- { id: 'INJECTED', name: 'john_doe', price: 'hashed_user_password', category: 'LEAKED DATA', stock: 'customer' },
- { id: 'INJECTED', name: 'jane_smith', price: 'hashed_user_password', category: 'LEAKED DATA', stock: 'customer' }
+ { id: 'USER', name: 'admin', price: 'hashed_admin_password', category: 'admin', stock: 'LEAKED!' },
+ { id: 'USER', name: 'john_doe', price: 'hashed_user_password', category: 'customer', stock: 'LEAKED!' },
+ { id: 'USER', name: 'jane_smith', price: 'hashed_user_password', category: 'customer', stock: 'LEAKED!' }
];
- } else if (injectionInfo.type === 'DROP_TABLE') {
- // Simulate destructive command
- results = [];
- explanation += ' In a real scenario, this could delete the entire products table!';
- } else if (injectionInfo.type === 'COMMENT_INJECTION') {
- // Bypass rest of query
+ } else if (injectionInfo.type === 'GENERIC') {
+ // Generic injection - show it affects the query
results = db.products;
}
} else {
@@ -75,13 +208,25 @@ class SQLInjectionShopLesson extends LessonModule {
);
}
+ const totalDiscoveries = 3; // Only 3 challenges now
+ const elapsedTime = await this._getElapsedTime(participantId, eventLessonId);
+
return {
query: vulnerableQuery,
results,
injectionDetected,
injectionType,
explanation,
- recordCount: results.length
+ recordCount: results.length,
+ pointsAwarded: isNewDiscovery ? pointsAwarded : 0,
+ isNewDiscovery,
+ unionHintMessage,
+ discoveries: {
+ found: discoveries.size,
+ total: totalDiscoveries,
+ types: Array.from(discoveries)
+ },
+ elapsedTime
};
}
@@ -89,14 +234,8 @@ class SQLInjectionShopLesson extends LessonModule {
detectInjection(input) {
const injectionPatterns = [
/'/, // Single quote
- /--/, // SQL comment
- /;/, // Statement separator
/union/i, // UNION keyword
/select/i, // SELECT keyword
- /drop/i, // DROP keyword
- /insert/i, // INSERT keyword
- /update/i, // UPDATE keyword
- /delete/i, // DELETE keyword
/or\s+['"]?\d+['"]?\s*=\s*['"]?\d+['"]?/i // OR 1=1 pattern
];
@@ -107,47 +246,37 @@ class SQLInjectionShopLesson extends LessonModule {
analyzeInjection(input) {
const lowerInput = input.toLowerCase();
- if (lowerInput.includes('union') && lowerInput.includes('select')) {
+ // Challenge 3: UNION SELECT (most advanced)
+ // Must include UNION SELECT FROM users/user to be valid
+ if (lowerInput.includes('union') && lowerInput.includes('select') &&
+ lowerInput.includes('from') && (lowerInput.includes('users') || lowerInput.includes('user'))) {
return {
type: 'UNION_SELECT',
- explanation: 'â ď¸ UNION SELECT injection detected! This technique combines results from multiple tables, potentially exposing sensitive data like usernames and passwords.'
- };
- }
-
- if (lowerInput.includes('drop')) {
- return {
- type: 'DROP_TABLE',
- explanation: 'đ¨ DROP TABLE injection detected! This is a destructive attack that could delete entire database tables. Critical data loss would occur!'
+ explanation: 'đ Perfekt! UNION SELECT Injection erfolgreich! Du hast Daten aus der users-Tabelle extrahiert. **Challenge 3 abgeschlossen!** â'
};
}
+ // Challenge 2: Bypass filter to show all products
if (lowerInput.includes("'") && (lowerInput.includes('or') || lowerInput.includes('||'))) {
if (lowerInput.match(/or\s+['"]?\d+['"]?\s*=\s*['"]?\d+['"]?/)) {
return {
- type: 'OR_ALWAYS_TRUE',
- explanation: "â ď¸ OR injection detected! The condition '1'='1' is always true, bypassing the intended filter and returning ALL records."
+ type: 'BYPASS_FILTER',
+ explanation: "â Super! Die Bedingung '1'='1' ist immer wahr und umgeht den Filter. Jetzt werden ALLE Produkte angezeigt. **Challenge 2 abgeschlossen!**"
};
}
}
- if (lowerInput.includes('--') || lowerInput.includes('#')) {
+ // Challenge 1: Generic injection - just discovered manipulation is possible
+ if (lowerInput.includes("'")) {
return {
- type: 'COMMENT_INJECTION',
- explanation: 'â ď¸ Comment injection detected! The -- sequence comments out the rest of the SQL query, potentially bypassing security checks.'
+ type: 'GENERIC',
+ explanation: "đ Gut gemacht! Das AnfĂźhrungszeichen (') zeigt, dass die Abfrage manipuliert werden kann. Du hast entdeckt, dass SQL Injection mĂśglich ist! **Challenge 1 abgeschlossen!**"
};
}
- if (lowerInput.includes(';')) {
- return {
- type: 'MULTIPLE_STATEMENTS',
- explanation: 'â ď¸ Multiple statement injection detected! The semicolon allows execution of additional SQL commands, enabling complex attacks.'
- };
- }
-
- // Generic injection
return {
- type: 'GENERIC',
- explanation: 'â ď¸ SQL injection attempt detected! Special characters in the input could manipulate the query structure.'
+ type: 'NONE',
+ explanation: 'Keine SQL Injection erkannt.'
};
}
@@ -155,11 +284,9 @@ class SQLInjectionShopLesson extends LessonModule {
executeSafeQuery(searchTerm) {
const db = this.getMockDatabase();
- // Show the safe query with placeholder
const safeQuery = `SELECT * FROM products WHERE name LIKE ?`;
const parameter = `%${searchTerm}%`;
- // Execute safe search (treats all input as literal data)
const results = db.products.filter(p =>
p.name.toLowerCase().includes(searchTerm.toLowerCase())
);
@@ -168,41 +295,79 @@ class SQLInjectionShopLesson extends LessonModule {
query: safeQuery,
parameter,
results,
- explanation: 'â Parameterized query used! User input is treated as data only, never as SQL code. Injection is impossible.',
+ explanation: 'â Parameterized query verwendet! Benutzereingaben werden als Daten behandelt, nie als SQL-Code. Injection ist unmĂśglich.',
recordCount: results.length
};
}
// Get interactive data for the SQL shop demo
- getInteractiveData(stepId) {
+ async getInteractiveData(stepId) {
if (stepId === 'shop-demo') {
return {
+ timerDuration: 600, // 10 minutes
+ totalChallenges: 3, // Simplified to 3 challenges
database: this.getMockDatabase(),
- examples: [
+ challenges: [
{
- label: 'Normal Search',
- input: 'laptop',
- description: 'Search for products containing "laptop"'
+ id: 'GENERIC',
+ difficulty: 'Anfänger',
+ points: 30,
+ title: 'SQL Injection entdecken',
+ hint: "Versuche ein ' (AnfĂźhrungszeichen) einzugeben"
},
{
- label: 'View All Products (OR injection)',
- input: "' OR '1'='1",
- description: 'Exploit: Returns all products by making condition always true'
+ id: 'BYPASS_FILTER',
+ difficulty: 'Anfänger',
+ points: 40,
+ title: 'Filter umgehen (alle Produkte zeigen)',
+ hint: "Verwende: ' OR '1'='1"
},
{
- label: 'Extract User Data (UNION)',
- input: "' UNION SELECT id, username, password, role, 'LEAKED' FROM users--",
- description: 'Exploit: Combines product results with user table data'
- },
- {
- label: 'Destructive Attack (DROP)',
- input: "'; DROP TABLE products--",
- description: 'Exploit: Attempts to delete the products table'
+ id: 'UNION_SELECT',
+ difficulty: 'Fortgeschritten',
+ points: 80,
+ title: 'Benutzerdaten extrahieren',
+ hint: 'Wird nach Challenge 2 freigeschaltet',
+ isEasterEgg: true
}
- ]
+ ],
+ externalResources: [
+ {
+ title: 'OWASP SQL Injection',
+ url: 'https://owasp.org/www-community/attacks/SQL_Injection',
+ type: 'documentation',
+ description: 'Grundlagen zu SQL Injection-Angriffen'
+ },
+ {
+ title: 'SQL Tutorial (W3Schools)',
+ url: 'https://www.w3schools.com/sql/',
+ type: 'tutorial',
+ description: 'SQL Grundlagen lernen'
+ },
+ {
+ title: 'SQL Injection Cheat Sheet',
+ url: 'https://portswigger.net/web-security/sql-injection/cheat-sheet',
+ type: 'reference',
+ description: 'Schnellreferenz fĂźr SQL Injection'
+ }
+ ],
+ schemaInfo: {
+ tables: ['products', 'users'],
+ productsColumns: ['id', 'name', 'price', 'category', 'stock'],
+ usersColumns: ['id', 'username', 'password', 'role']
+ },
+ initialHint: {
+ title: 'đĄ Einstiegshilfe',
+ content: 'Du hast erfahren, dass dieser Shop anfällig fßr SQL Injection ist. Beginne mit einem einfachen Test: Gib ein Anfßhrungszeichen (\') ein und beobachte was passiert. Dann versuche den Filter zu umgehen.',
+ examples: [
+ { label: "Challenge 1", payload: "'", description: "Entdecke die Schwachstelle" },
+ { label: "Challenge 2", payload: "' OR '1'='1", description: "Zeige alle Produkte (Filter umgehen)" }
+ ]
+ }
};
}
- return null;
+
+ return await super.getInteractiveData(stepId);
}
}
diff --git a/backend/lessons/modules/xss-comprehensive/index.js b/backend/lessons/modules/xss-comprehensive/index.js
new file mode 100644
index 0000000..2e90195
--- /dev/null
+++ b/backend/lessons/modules/xss-comprehensive/index.js
@@ -0,0 +1,462 @@
+const LessonModule = require('../base/LessonModule');
+
+/**
+ * Comprehensive XSS Lesson
+ * Demonstrates both reflected XSS (URL parameters) and stored XSS (forum comments)
+ * Features: Variant discovery tracking, hint system, time limits
+ */
+class XSSComprehensiveLesson extends LessonModule {
+ constructor(config) {
+ super(config);
+
+ // Track discovered variants per participant
+ this.discoveredVariants = new Map(); // participantId -> Set of variant types
+
+ // Track step start times per participant
+ this.stepStartTimes = new Map(); // participantId -> timestamp
+
+ // Track hints used per participant
+ this.hintsUsed = new Map(); // participantId -> { stepId: count }
+
+ // Maximum time to earn points (15 minutes)
+ this.MAX_TIME_FOR_POINTS = 15 * 60 * 1000;
+
+ // Point deduction per hint
+ this.HINT_PENALTY = 5;
+
+ // Total XSS variants to discover
+ this.TOTAL_VARIANTS = 9;
+ }
+
+ /**
+ * XSS variant patterns to discover
+ */
+ getVariantPatterns() {
+ return [
+ { regex: / oder ',
+ 'Tipp 4: Andere Varianten: