Sicherheitskompetenz-Assessment und -Tracking
Man kann nicht verbessern, was man nicht misst. Bevor Sie Sicherheitsschulungen starten, müssen Sie den aktuellen Kenntnisstand Ihres Teams verstehen. Nach der Schulung müssen Sie verifizieren, dass sie gewirkt hat. Regelmäßige Assessments stellen sicher, dass Kenntnisse nicht abbauen.
Dieser Artikel beschreibt praktische Methoden zur Bewertung von Entwickler-Sicherheitswissen: Quizze, Code-Review-Übungen, CTF-Wettbewerbe und der Aufbau von Kompetenz-Maps, die Teamstärken und -lücken visualisieren.
Dies ist Teil 2 der Entwickler-Sicherheitsschulungs-Serie:
- Lehrplan und Ressourcen — was zu lehren ist
- Assessment und Kompetenz-Mapping (dieser Artikel) — wie man Kenntnisse bewertet
- Implementierungsleitfaden — wie man das Programm einführt
Warum Assessment wichtig ist
Lücken vor der Schulung identifizieren. Generische Schulungen verschwenden Zeit mit Themen, die Leute bereits kennen. Assessments zeigen, was jeder Entwickler tatsächlich braucht.
Schulungseffektivität messen. Hat die Schulung gewirkt? Vergleichen Sie Vor- und Nach-Schulungs-Scores, um es sicher zu wissen.
Verbesserung im Zeitverlauf verfolgen. Sicherheitswissen baut ohne Praxis ab. Regelmäßige Assessments erkennen Kenntnisrückgang früh.
Die Investition rechtfertigen. Die Unternehmensführung möchte wissen, ob die Schulung funktioniert. Assessments liefern konkrete Metriken.
Entwickler motivieren. Klare Kompetenzstufen geben Entwicklern Ziele, auf die sie hinarbeiten können. Verbesserungen sind sichtbar und lohnend.
Assessment-Methoden
Methode 1: Sicherheitswissen-Quiz
Der einfachste Ansatz. Erstellen Sie Multiple-Choice- und Kurzantwort-Fragen zu wichtigen Sicherheitsthemen.
Grundsätze für das Quiz-Design:
| Grundsatz | Warum es wichtig ist |
|---|---|
| Rollenrelevant | Backend-Entwickler nicht über iOS-Sicherheit befragen |
| Schwierigkeitsprogression | L1 (grundlegend) → L2 (mittel) → L3 (fortgeschritten) |
| Praktischer Fokus | Code-Beispiele statt Definitionen |
| Keine Fangfragen | Wissen testen, nicht Leseverständnis |
| Antworten erklären | Lernmöglichkeit auch während des Assessments |
Assessment-Struktur:
Dauer: 45–60 Minuten. Format: Online, beaufsichtigt oder auf Vertrauensbasis.
Abschnitte:
- Grundlegende Sicherheitskonzepte (10 Fragen) — alle Rollen
- OWASP Top 10 (10 Fragen) — alle Rollen
- Sprachspezifisch (10 Fragen) — je nach Rolle
- Authentifizierung/Autorisierung (5 Fragen) — Backend/Fullstack
- Sicherheitstests (5 Fragen) — alle Rollen
Bewertung: 90 %+ = L3 (Experte) · 70–89 % = L2 (Praktiker) · 50–69 % = L1 (Bewusst) · Unter 50 % = Schulung erforderlich
Methode 2: Sicherer Code-Review-Übung
Praktischer als Quizze. Geben Sie Entwicklern Code mit absichtlichen Schwachstellen und bitten Sie sie, Probleme zu finden.
Funktionsweise:
- Code-Beispiele mit 5–10 Schwachstellen vorbereiten
- Zeitlimit setzen (30–45 Minuten)
- Entwickler bitten, Probleme zu identifizieren und zu erklären
- Bewertung basierend auf gefundenen Schwachstellen und Erklärungsqualität
Beispielübung:
# Code Review Exercise: Find the security issues
# Time limit: 30 minutes
# Identify all security vulnerabilities and suggest fixes
from flask import Flask, request, render_template_string
import sqlite3
import pickle
import os
app = Flask(__name__)
SECRET_KEY = "super_secret_key_12345" # Issue #1
@app.route('/login', methods=['POST'])
def login():
username = request.form['username']
password = request.form['password']
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
# Issue #2
query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
cursor.execute(query)
user = cursor.fetchone()
if user:
return f"Welcome {username}!" # Issue #3
return "Invalid credentials"
@app.route('/profile/<user_id>')
def profile(user_id):
# Issue #4
user_data = open(f'profiles/{user_id}.json').read()
return user_data
@app.route('/search')
def search():
query = request.args.get('q', '')
# Issue #5
template = f"<h1>Results for: {query}</h1>"
return render_template_string(template)
@app.route('/load-session')
def load_session():
data = request.cookies.get('session_data')
# Issue #6
session = pickle.loads(bytes.fromhex(data))
return str(session)
@app.route('/execute')
def execute():
cmd = request.args.get('cmd')
# Issue #7
result = os.popen(cmd).read()
return result
if __name__ == '__main__':
app.run(debug=True) # Issue #8
Antwortschlüssel:
| # | Schwachstelle | Ort | Schweregrad |
|---|---|---|---|
| 1 | Hartcodiertes Geheimnis | Zeile 8 | Hoch |
| 2 | SQL-Injection | Zeile 18 | Kritisch |
| 3 | Potenzielles XSS | Zeile 21 | Mittel |
| 4 | Path Traversal | Zeile 26 | Hoch |
| 5 | Server-Side Template Injection | Zeile 32 | Kritisch |
| 6 | Unsichere Deserialisierung | Zeile 38 | Kritisch |
| 7 | Command-Injection | Zeile 43 | Kritisch |
| 8 | Debug-Modus in Produktion | Zeile 47 | Mittel |
Bewertung:
- Schwachstelle gefunden: 1 Punkt
- Auswirkung korrekt erklärt: +1 Punkt
- Gültige Lösung vorgeschlagen: +1 Punkt
- Maximale Punktzahl: 24 Punkte
Methode 3: Capture The Flag (CTF)
Gamifiziertes Assessment, bei dem Entwickler verwundbare Anwendungen ausnutzen, um „Flags" (versteckte Strings) zu finden.
Vorteile:
- Ansprechend und unterhaltsam
- Testet praktische Fähigkeiten
- Fördert Lernen durch Erkundung
- Kann teambasiert für Zusammenarbeit sein
CTF-Plattformen:
| Plattform | Geeignet für | Kosten | Link |
|---|---|---|---|
| CTFd | Self-hosted benutzerdefinierter CTF | Kostenlos | ctfd.io |
| OWASP Juice Shop | Vorgefertigte Challenges | Kostenlos | owasp.org/www-project-juice-shop |
| HackTheBox | Realistische Maschinen | Kostenpflichtig | hackthebox.com |
| PicoCTF | Einsteiger-freundlich | Kostenlos | picoctf.org |
Internes CTF durchführen:
Dauer: 2–4 Stunden (kann über Tage verteilt werden).
Setup: OWASP Juice Shop oder benutzerdefinierte Challenges bereitstellen. Teams von 2–3 Personen erstellen, Erfahrungsstufen mischen, Hinweise für feststeckende Teams vorbereiten.
Challenges nach Schwierigkeit:
- Einfach (1 Stern): 5 Challenges — grundlegendes XSS, robots.txt
- Mittel (2–3 Sterne): 5 Challenges — SQLi, Auth-Bypass
- Schwer (4–5 Sterne): 3 Challenges — Deserialisierung, SSRF
Bewertung: Punkte basierend auf Schwierigkeit. Bonus für frühe Lösungen. Keine Strafe für Hinweise — fördert Lernen statt Wettbewerb.
Nach dem Event: Lösungsdurchgang für alle Challenges. Anerkennung für Top-Teams. Individuelle Skill-Notizen basierend auf der Teilnahme.
Methode 4: Schwachstellen-Injektions-Übung
Realistisches Assessment — Sie fügen absichtlich Schwachstellen in einen PR ein und prüfen, ob Entwickler sie beim Review finden.
Funktionsweise:
- Einen Branch mit absichtlichen Schwachstellen erstellen
- Entwickler bitten, den PR zu reviewen
- Verfolgen, welche Schwachstellen sie finden
- Feedback zu übersehenen Problemen geben
Beispiel-Schwachstellen zum Injizieren:
# Intentional vulnerabilities for testing
# 1. SQL Injection (obvious)
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
# 2. Command injection (less obvious)
os.system(f"convert {filename} output.pdf")
# 3. SSRF (requires understanding)
requests.get(user_provided_url)
# 4. Hardcoded secret
API_KEY = "sk_live_123456789"
# 5. Insecure deserialization
data = pickle.loads(user_input)
# 6. Path traversal
file_path = f"uploads/{user_filename}"
with open(file_path, 'r') as f:
content = f.read()
Quiz-Fragen erstellen
KI zur Fragenerstellung nutzen
Sie können KI-Assistenten nutzen, um Assessment-Fragen zu erstellen. Hier ist eine Prompt-Vorlage:
Create 5 multiple-choice security questions for [ROLE] developers
working with [TECHNOLOGY STACK].
Requirements:
- Include code examples where applicable
- Vary difficulty (2 L1, 2 L2, 1 L3)
- Focus on [SPECIFIC TOPIC: e.g., SQL injection, authentication]
- Provide correct answer and explanation
- Make wrong answers plausible but clearly incorrect
Format each question as:
**Q[N] ([Level]):** Question text
[Code if applicable]
a) Option A
b) Option B
c) Option C
d) Option D
**Answer:** [Letter]
**Explanation:** [Why this is correct and others are wrong]
Beispiel-Fragen nach Thema
SQL-Injection (Backend, Daten)
F1 (L1): Welche der folgenden Optionen ist anfällig für SQL-Injection?
# Option A
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
# Option B
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
# Option C
User.objects.get(id=user_id)
a) Nur A b) Nur B c) A und B d) Alle
Antwort: b Erklärung: Option B verwendet f-String-Interpolation und bettet Nutzereingaben direkt in die Query ein. Option A verwendet parametrisierte Queries (sicher). Option C verwendet das Django-ORM (sicher).
F2 (L2): Ist dieser Code sicher vor SQL-Injection?
if user_id.isdigit():
User.objects.raw(f"SELECT * FROM users WHERE id = {user_id}")[0]
a) Ja, immer noch anfällig für SQL-Injection b) Nein, isdigit()-Validierung macht es sicher c) Nein, Django ORM verhindert SQL-Injection d) Hängt vom Datenbanktyp ab
Antwort: b (aber Randfälle besprechen) Erklärung: isdigit() stellt sicher, dass nur Ziffern verwendet werden, wodurch eine Injection unmöglich wird. Dieses Muster ist jedoch fragil — besser parametrisierte Queries für Defense in Depth verwenden. raw() mit f-Strings ist ein Code-Smell.
F3 (L3): Prüfen Sie diese parametrisierte Query. Ist sie sicher?
table_name = request.args.get('table')
cursor.execute(f"SELECT * FROM {table_name} WHERE id = %s", (user_id,))
a) Ja, parametrisierte Queries verhindern SQL-Injection b) Nein, der Tabellenname ist weiterhin injizierbar c) Ja, der Platzhalter schützt alle Eingaben d) Hängt vom Datenbanktreiber ab
Antwort: b Erklärung: Parametrisierung funktioniert nur für Werte, nicht für Bezeichner (Tabellen-/Spaltennamen). Der table_name ist weiterhin verwundbar. Lösung: Erlaubte Tabellennamen auf eine Whitelist setzen.
XSS (Frontend, Backend)
F1 (L1): Wofür steht XSS? a) Cross-Site Scripting b) Cross-Server Security c) Client-Side Scripting d) Cross-Site Security
Antwort: a
F2 (L2): In React, welche Option ist anfällig für XSS?
// Option A
<div>{userInput}</div>
// Option B
<div dangerouslySetInnerHTML={{__html: userInput}} />
// Option C
<input value={userInput} />
a) Nur A b) Nur B c) A und B d) Alle
Antwort: b Erklärung: React escaped Inhalte in JSX standardmäßig (A und C sind sicher). dangerouslySetInnerHTML umgeht diesen Schutz und ist anfällig, wenn userInput bösartiges HTML/JavaScript enthält.
F3 (L2): Welcher Content-Security-Policy-Header verhindert XSS am besten? a) Content-Security-Policy: default-src * b) Content-Security-Policy: default-src 'self' c) Content-Security-Policy: default-src 'self'; script-src 'unsafe-inline' d) Content-Security-Policy: script-src 'none'
Antwort: b Erklärung: 'self' erlaubt nur Ressourcen gleichen Ursprungs. Option a erlaubt alles (kein Schutz). Option c erlaubt Inline-Skripte (XSS-Risiko). Option d blockiert alle Skripte, auch die eigenen.
Authentifizierung (alle Rollen)
F1 (L1): Wo sollten Sie JWT-Tokens im Browser speichern? a) localStorage b) sessionStorage c) HttpOnly-Cookie d) URL-Parameter
Antwort: c Erklärung: HttpOnly-Cookies sind nicht über JavaScript zugänglich, was vor XSS-Token-Diebstahl schützt. localStorage/sessionStorage sind über JavaScript zugänglich. URL-Parameter werden protokolliert und gecacht.
F2 (L2): Was ist falsch an dieser Passwort-Speicherung?
import hashlib
password_hash = hashlib.md5(password.encode()).hexdigest()
a) MD5 ist zu langsam b) MD5 ist kryptografisch gebrochen und es wird kein Salt verwendet c) Sollte base64 statt hexdigest verwenden d) Nichts, das ist korrekt
Antwort: b Erklärung: MD5 ist schnell und hat Kollisionsschwachstellen — ungeeignet für Passwörter. Passwörter sollten bcrypt, Argon2 oder scrypt mit automatischem Salting verwenden.
F3 (L3): Prüfen Sie diese JWT-Validierung. Was ist das Sicherheitsproblem?
const decoded = jwt.verify(token, secret);
if (decoded.userId) {
// Grant access
}
a) Kein Problem — jwt.verify prüft alles b) Fehlende Algorithmusspezifikation — anfällig für Algorithm-Confusion c) Sollte jwt.decode statt jwt.verify verwenden d) Fehlende Audience-Prüfung
Antwort: b
Erklärung: Ohne Algorithmusspezifikation könnte ein Angreifer ein Token mit „alg": „none" erstellen oder von RS256 zu HS256 mit dem öffentlichen Schlüssel als Secret wechseln. Immer angeben: jwt.verify(token, secret, { algorithms: ['HS256'] })
Autorisierung (Backend)
F1 (L1): Was ist IDOR?
a) Insecure Direct Object Reference — Zugriff auf Ressourcen durch Erraten von IDs b) Internal Data Object Routing — internes API-Muster c) Integrated Development Object Repository — Versionskontrollbegriff d) Indirect Object Reference Design — sicheres Coding-Muster
Antwort: a
F2 (L2): Dieser Endpunkt ruft Nutzerdaten ab. Was fehlt?
@app.route('/api/users/<user_id>/profile')
def get_profile(user_id):
user = User.query.get(user_id)
return jsonify(user.to_dict())
a) Eingabevalidierung für user_id b) Autorisierungsprüfung — verifizieren, dass der Anforderer auf die Daten dieses Nutzers zugreifen darf c) Rate Limiting d) HTTPS-Anforderung
Antwort: b
Erklärung: Jeder authentifizierte Nutzer könnte auf das Profil eines anderen Nutzers zugreifen, indem er die user_id ändert. Verifizierung erforderlich: if current_user.id != user_id and not current_user.is_admin: abort(403)
F3 (L3): Welches ist das sicherste Autorisierungsmuster?
a) Autorisierung im Controller nach dem Abrufen von Daten prüfen b) Daten in der Repository/ORM-Schicht basierend auf dem aktuellen Nutzer filtern c) Middleware verwenden, die Autorisierung auf alle Endpunkte anwendet d) Autorisierung in der Service-Schicht vor dem Datenzugriff prüfen
Antwort: b Erklärung: Filterung auf Repository-Ebene stellt sicher, dass nicht autorisierte Daten die Datenbank nie verlassen. Andere Ansätze riskieren Datenoffenlegung, wenn eine Prüfung fehlt. Defense in Depth: mehrere Schichten verwenden.
Entwickler-Sicherheitskompetenz-Maps aufbauen
Kompetenz-Maps visualisieren Fähigkeiten im Team und identifizieren Lücken.
Individuelle Kompetenz-Map
Entwickler: Jane Smith | Rolle: Senior Developer | Level: L2
| Bereich | Score | Status |
|---|---|---|
| Sicheres Coding | 80 % | ✓ |
| Authentifizierung | 90 % | ✓ |
| Eingabevalidierung | 100 % | ✓ |
| Kryptografie | 40 % | ⚠ Lücke |
| Threat Modeling | 50 % | — |
| Sicherheitstests | 70 % | ✓ |
| Abhängigkeitsverwaltung | 80 % | ✓ |
| Vorfallreaktion | 40 % | ⚠ Lücke |
Empfohlen: Kryptografie-Kurs, IR-Schulung
Team-Kompetenz-Heatmap
| Name | Sicheres Coding | Auth | Eingabevalid. | Krypto | Threat Model | Tests | Abhäng. |
|---|---|---|---|---|---|---|---|
| Jane S. | ✓✓ | ✓✓ | ✓✓ | ✗ | ✓ | ✓✓ | ✓✓ |
| John D. | ✓✓ | ✓✓ | ✓✓ | ✓✓ | ✓✓ | ✓ | ✓ |
| Alice K. | ✓ | ✓ | ✓✓ | ✗ | ✗ | ✓ | ✓ |
| Bob M. | ✓✓ | ✓✓ | ✓✓ | ✓✓ | ✓✓ | ✓✓ | ✓✓ |
| Carol L. | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ |
| Team-Durchschn. | 80 % | 75 % | 90 % | 45 % LÜCKE | 40 % LÜCKE | 60 % | 70 % |
✓✓ = Stark (70 %+) · ✓ = In Entwicklung (40–70 %) · ✗ = Lücke (unter 40 %)
Kompetenz im Zeitverlauf verfolgen
Q1 2024 Assessment
| Bereich | Score | Ziel | Status |
|---|---|---|---|
| Sicheres Coding | 80 % | 80 % | Erreicht |
| Authentifizierung | 75 % | 80 % | In Bearbeitung |
| Kryptografie | 45 % | 60 % | Lücke |
| Threat Modeling | 40 % | 60 % | Lücke |
| Sicherheitstests | 60 % | 70 % | In Bearbeitung |
Maßnahmen:
- Authentifizierungs-Modul abgeschlossen
- Threat-Modeling-Workshop (geplant Februar)
- Kryptografie-Schulung für Team (geplant März)
Q2-Ziele: Kryptografie über 60 % · Threat Modeling über 60 % · Alle Entwickler bestehen das mittlere Assessment
Tools für das Kompetenz-Tracking
| Ansatz | Geeignet für | Aufwand |
|---|---|---|
| Tabellenkalkulation | Kleine Teams (unter 10) | Gering |
| Notion/Confluence | Dokumentationsstarke Organisationen | Gering |
| Skills-Management-Plattform | Große Teams | Mittel |
| Benutzerdefiniertes Dashboard | Spezifische Anforderungen | Hoch |
Einfache Tabellen-Vorlage:
| Entwickler | Rolle | OWASP Top 10 | Auth/AuthZ | Krypto | Tests | Threat Model | Letztes Assessment |
|---|---|---|---|---|---|---|---|
| Jane S. | Senior | 4/5 | 5/5 | 2/5 | 3/5 | 3/5 | 2024-01-15 |
| John D. | Mid | 3/5 | 3/5 | 4/5 | 2/5 | 4/5 | 2024-01-15 |
| ... | ... | ... | ... | ... | ... | ... | ... |
Vergleich von Assessment-Plattformen
Kostenlose Plattformen
| Plattform | Stärken | Einschränkungen |
|---|---|---|
| Google Forms | Einfache Einrichtung, kostenlos | Keine Code-Ausführung, grundlegende Analysen |
| Microsoft Forms | Office-365-Integration | Ähnlich wie Google Forms |
| Typeform | Bessere UX | Begrenzter kostenloser Tarif |
| Self-hosted CTFd | Vollständige Kontrolle, gamifiziert | Erfordert Setup und Wartung |
Kostenpflichtige Plattformen
| Plattform | Geeignet für | Ungefähre Kosten |
|---|---|---|
| Secure Code Warrior | Enterprise-Sicherheitsschulung | $$$$ |
| HackEDU | Entwicklerorientierte Schulung | $$$ |
| Avatao | Praxisorientierte Challenges | $$$ |
| AppSec Engineer | Cloud-native Schulung | $$ |
| Kontra | Interaktive Lektionen | $$ |
DIY-Assessment
Für kleine Teams mit begrenztem Budget:
- Fragen in Markdown erstellen — Versionskontrolle, einfache Updates
- Google Forms für die Durchführung verwenden — kostenlos, einfaches Teilen
- Ergebnisse in Tabellenkalkulation verfolgen — einfaches Kompetenz-Mapping
- CTF mit Juice Shop durchführen — kostenlos, umfassend
Verbesserung messen
Zu verfolgende Metriken
| Metrik | Wie zu messen | Ziel |
|---|---|---|
| Durchschnittlicher Assessment-Score | Quiz-Ergebnisse | Verbesserung jedes Quartal |
| Schwachstellendichte | SAST-Funde pro KLOC | Abnahme im Zeitverlauf |
| Behebungszeit | JIRA-Tracking | Abnahme bei Sicherheits-Bugs |
| Sicherheits-Bugs in Produktion | Bug-Tracker | Weniger pro Release |
| Fangrate bei Code-Reviews | Review-Kommentare verfolgen | Mehr Sicherheitsprobleme entdeckt |
| Schulungsabschluss | LMS oder Tabelle | 100 % für Pflichtschulungen |
Vorher/Nachher-Analyse
Schulungsauswirkungsbericht: Q2 2024
Assessment-Scores vor und nach der Schulung:
| Bereich | Vor Schulung | Nach Schulung | Änderung |
|---|---|---|---|
| SQLi-Prävention | 65 % | 88 % | +23 % |
| Auth-Best-Practices | 70 % | 85 % | +15 % |
| Eingabevalidierung | 60 % | 82 % | +22 % |
Reale Auswirkungen im gleichen Zeitraum:
| Metrik | Q1 | Q2 | Änderung |
|---|---|---|---|
| SAST-Funde | 145 | 89 | −39 % |
| Sicherheits-Bugs in Produktion | 12 | 5 | −58 % |
| Durchschnittliche Behebungszeit (Tage) | 8 | 4 | −50 % |
Die Schulung zeigt messbaren ROI. Vierteljährliche Assessments fortsetzen und Schulungen auf aktuelle Lücken fokussieren.
Häufige Fehler
- Wissen statt Fähigkeiten testen — Praktische Übungen einbeziehen, nicht nur Theorie
- Einheitliches Assessment für alle — An Rollen und Tech-Stacks anpassen
- Einmalig testen und vergessen — Regelmäßige Assessments erkennen Wissensrückgang
- Niedrige Scores bestrafen — Das entmutigt ehrliches Assessment
- Nicht auf Ergebnisse reagieren — Assessment ohne Schulung ist sinnlos
- Zu lang machen — Maximal 45–60 Minuten für Quizze
Selbstcheck-Fragen
- Was sind die vier Methoden zur Bewertung von Entwickler-Sicherheitskenntnissen?
- Warum ist eine Code-Review-Übung praktischer als ein Quiz?
- Wie berechnet man Kompetenzstufen aus Assessment-Scores?
- Welche Metriken sollten Sie verfolgen, um die Schulungseffektivität zu messen?
- Wie oft sollten Entwickler bewertet werden?
- Was ist der Vorteil von CTF-Style-Assessments?
Fazit
Assessment ist nur dann wichtig, wenn Sie auf die Ergebnisse reagieren. Eine Kompetenzlücke, die Sie gemessen und ignoriert haben, ist schlimmer als eine, die Sie nicht gemessen haben — Sie wussten es und haben nichts getan.
Führen Sie die Basis-Messung durch. Finden Sie die Lücken. Nutzen Sie sie, um zu priorisieren, was zuerst geschult wird.
Was kommt als nächstes
Weiter: Implementierungsleitfaden — schrittweiser Plan zur Einführung von Entwickler-Sicherheitsschulungen im gesamten Team.