Zum Inhalt springen

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen

Secure Coding Practices: Sicherheit im Entwicklungsprozess verankern

Secure Coding und Secure SDLC: Von Threat Modeling und STRIDE über sprachspezifische Sicherheitsmuster (Python, Java, Node.js, Go) für Input Validation, SQL Injection, Authentifizierung und Kryptographie bis zu SAST/DAST/SCA in CI/CD, Security Code Reviews, Container Security, SBOM, Secrets Management und dem OWASP SAMM Reifegradmodell. Praxisleitfaden für Entwicklungsteams ohne eigene Security-Abteilung.

Inhaltsverzeichnis (11 Abschnitte)

Sicherheitslücken entstehen meist nicht durch fehlende Absicht, sondern durch fehlende Gewohnheiten. Secure Coding bedeutet, die richtigen Muster zu verinnerlichen bis sie zur Selbstverständlichkeit werden. Sicherheit im SDLC nachträglich einzubauen ist wie Sicherheitsgurte nach dem Unfall anzulegen: teuer, ineffektiv und zu spät. Ein Bug im Design kostet rund 100 EUR, im Code 1.000 EUR und in Produktion 100.000 EUR oder mehr.

Der Secure SDLC (Software Development Lifecycle)

Im traditionellen SDLC kommt der Security-Test erst am Ende, kurz vor dem Deployment. Im Secure SDLC (Microsoft SDL / OWASP SDLC) wird Sicherheit in jede Phase integriert: In der Requirements-Phase werden Sicherheitsanforderungen definiert, im Design wird Threat Modeling durchgeführt, im Coding gelten Secure Coding Guidelines mit SAST im IDE, im Testing kommen DAST, Penetrationstest und SCA zum Einsatz, das Deployment umfasst ein Security-Review und sichere Konfiguration, und in der Maintenance laufen Patch-Management und Vulnerability Monitoring kontinuierlich.

Grundprinzipien Secure Coding

1. Input Validation - alle Eingaben sind verdächtig. Validiere alles: HTTP-Parameter, Headers, Cookies, Dateiinhalte. Nutze Whitelist-basierte Validierung (was erlaubt ist, nicht was verboten). Validierung sollte so früh wie möglich, so nah an der Eingabe wie möglich stattfinden.

2. Output Encoding - kontextabhängig. Im HTML-Context: HTML-Entity-Encoding (< wird zu <). Im JavaScript-Context: JavaScript-Encoding (\x3C). Im SQL-Context: Parameterized Queries (niemals String-Konkatenation). Im URL-Context: URL-Encoding (%3C). Der falsche Kontext führt direkt zu XSS oder Injection.

3. Authentication - Identität verifizieren. Starke Passwort-Hashing-Algorithmen (bcrypt, Argon2, PBKDF2) verwenden, MFA für privilegierte Aktionen erzwingen, zufällige Session-IDs mit kurzer Lifetime nutzen.

4. Authorization - Zugriff kontrollieren. Object-Level Authorization für jede Ressource prüfen, Least Privilege (minimale Berechtigungen) durchsetzen, Deny-by-default: was nicht explizit erlaubt ist, ist verboten.

5. Fail Secure - bei Fehler Zugang verweigern. Exceptions führen zu verweigertem Zugang, nicht gewährtem. Keine Default-Credentials. Sichere Defaults überall.

6. Separation of Concerns. Daten und Code strikt trennen (SQL, HTML, Shell). Template-Engines: User-Input als Variablen, nie in Templates einfügen.

7. Defense in Depth. Mehrere unabhängige Sicherheitsschichten - eine Schwachstelle kompromittiert nicht alles.

8. Cryptography - nur geprüfte Bibliotheken. NIEMALS eigene Krypto implementieren. Sichere Defaults: AES-256-GCM, RSA-4096 oder Ed25519, bcrypt.

9. Error Handling - keine sensitiven Details. Interne Fehler loggen, aber nicht ans Frontend weitergeben. Generic error messages für Angreifer, Correlation-ID für Support.

10. Logging und Monitoring. Security-relevante Ereignisse loggen (Logins, Zugriffsversuche). Keine sensitiven Daten in Logs (Passwörter, Tokens, PII).

Phase 1: Security Requirements und Design

Der OWASP Application Security Verification Standard (ASVS) definiert drei Level: Level 1 für grundlegende Sicherheit aller Anwendungen, Level 2 als Standard für business-critical Anwendungen und Level 3 für kritische Infrastruktur. Die wichtigsten ASVS-Anforderungen auf Level 1 umfassen Architektur und Bedrohungsmodell (V1), Authentifizierung (V2), Session Management (V3), Input Validation und Encoding (V5), Kryptographie (V6), Datenschutz (V8), Kommunikationssicherheit (V9) und Konfigurationssicherheit (V14).

Threat Modeling mit STRIDE

STRIDE analysiert pro Komponente sechs Bedrohungskategorien anhand eines Datenflussdiagramms mit Vertrauensgrenzen (Internet → DMZ → Intranet → Datenbank):

  • S (Spoofing): Kann ein Angreifer als jemand anderes auftreten? Gegenmittel: MFA, starke Authentifizierung, JWT-Signierung.
  • T (Tampering): Kann ein Angreifer Daten ändern? Gegenmittel: Signaturen, MAC, Input Validation, HMAC.
  • R (Repudiation): Kann jemand Aktionen abstreiten? Gegenmittel: unveränderliche Audit-Logs, digitale Signaturen.
  • I (Information Disclosure): Werden sensible Daten unbeabsichtigt preisgegeben? Gegenmittel: Error Handling, Verschlüsselung, Minimal Disclosure.
  • D (Denial of Service): Kann der Dienst zum Absturz gebracht werden? Gegenmittel: Rate Limiting, Input Size Limits, Circuit Breaker.
  • E (Elevation of Privilege): Kann ein Nutzer mehr Rechte erlangen als erlaubt? Gegenmittel: Least Privilege, RBAC, IDOR-Schutz.

Für jede identifizierte Bedrohung wird eine Security Story formuliert: "Als Angreifer will ich durch SQL-Injection die Kundendatenbank auslesen, um Kreditkartendaten zu stehlen." Zu jeder Security Story gehört ein entsprechender Test Case.

Input Validation Patterns

# Python - Validierung und sicheres HTML-Escaping
import re, html
from email_validator import validate_email, EmailNotValidError

def validate_username(username: str) -> str:
    if not isinstance(username, str):
        raise ValueError("Username muss String sein")
    if not 3 <= len(username) <= 50:
        raise ValueError("Username: 3-50 Zeichen")
    if not re.match(r'^[a-zA-Z0-9_-]+$', username):
        raise ValueError("Nur Buchstaben, Zahlen, _ und -")
    return username

safe_output = html.escape(user_input)

# Datei-Upload: MagicBytes prüfen, NICHT den Dateinamen!
import magic
ALLOWED_MIME_TYPES = {'image/jpeg', 'image/png', 'image/webp'}
mime = magic.from_buffer(file.read(1024), mime=True)
if mime not in ALLOWED_MIME_TYPES:
    raise ValueError(f"Unerlaubter Dateityp: {mime}")

# Path Traversal verhindern
import os
def safe_join(base, user_path):
    path = os.path.realpath(os.path.join(base, user_path))
    if not path.startswith(base):
        raise ValueError("Path traversal attempt detected!")
    return path

Java und Node.js nutzen deklarative Validierung: In Java (Spring/JSR-380) werden Annotationen wie @NotBlank, @Size, @Pattern und @Email auf DTO-Feldern gesetzt. In Node.js bietet Zod eine typsichere Schema-Validierung mit z.object(), z.string().min().max().regex() und safeParse() für strukturierte Fehlermeldungen.

SQL Injection Prevention

# Python - RICHTIG: Parameterized Query
cursor.execute(
    "SELECT * FROM users WHERE username = %s",
    (username,)
)
# SQLAlchemy ORM (noch sicherer):
user = db.session.query(User).filter_by(username=username).first()

Dasselbe Prinzip gilt für alle Sprachen: Java verwendet PreparedStatement mit ps.setInt(1, userId), Node.js nutzt pool.query('SELECT ... WHERE id = $1', [userId]) oder Prisma ORM. Bei MongoDB muss vor Abfragen ein Type-Check auf string erfolgen und $where-Abfragen müssen vermieden werden, da {$gt: ""} sonst alle Dokumente liefert.

Authentifizierung und Session Management

# Python - Argon2id (aktuellster Standard)
from argon2 import PasswordHasher
ph = PasswordHasher(time_cost=3, memory_cost=65536, parallelism=2)
hash = ph.hash("user-password")
try:
    ph.verify(hash, "user-password")
    if ph.check_needs_rehash(hash):
        hash = ph.hash("user-password")
except VerifyMismatchError:
    raise ValueError("Falsches Passwort")

# Session-Cookie-Attribute:
import secrets
session_id = secrets.token_hex(32)  # 256 Bit
response.set_cookie(
    'session', session_id,
    httponly=True,     # Kein JS-Zugriff
    secure=True,       # Nur HTTPS
    samesite='Strict', # CSRF-Schutz
    max_age=3600       # 1h Lifetime
)
# Session-Rotation nach Login (Session-Fixation-Schutz!):
new_id = secrets.token_hex(32)
create_session(new_id, old_session_data)
delete_session(old_id)

Falsche Algorithmen sind MD5, SHA-1 und SHA-256 ohne Salt - diese sind zu schnell und anfällig für Rainbow-Table-Angriffe. Richtig sind bcrypt (weit verbreitet), Argon2id (aktuellster Standard), scrypt (memory-hard) und PBKDF2 (FIPS-konform). Node.js nutzt bcrypt.hash(password, 12), Java new BCryptPasswordEncoder(12).

Für JWTs gilt: algorithm: 'RS256' (asymmetrisch) verwenden und algorithms=["none"] niemals erlauben.

Secrets Management

# FALSCH: Hardcoded Secret (in Git!)
DATABASE_URL = "postgresql://admin:SuperSecret123@db.firma.de/prod"

# RICHTIG: Environment Variable
DB_PASSWORD = os.environ.get('DB_PASSWORD')

# BESSER: HashiCorp Vault
import hvac
client = hvac.Client()
secret = client.secrets.kv.read_secret_version(path='my-app/db')
DB_PASSWORD = secret['data']['data']['password']

.env muss immer in .gitignore eingetragen sein. Pre-commit Hooks mit detect-secrets oder Gitleaks verhindern das versehentliche Committen von Secrets.

Security Testing in CI/CD

# GitHub Actions - SAST mit Semgrep
- name: Run Semgrep
  uses: returntocorp/semgrep-action@v1
  with:
    config: >-
      p/owasp-top-ten
      p/python
      p/javascript

# SCA mit Trivy
# trivy image myapp:latest
# trivy fs --scanners vuln,secret,misconfig ./
# trivy image --format cyclonedx --output sbom.json myapp:latest

# Secrets Scanning mit Gitleaks
- name: Gitleaks Secret Scan
  uses: gitleaks/gitleaks-action@v2
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Security Gate
- name: Check security scan results
  run: |
    CRITICAL=$(jq '[.[] | select(.severity == "CRITICAL")] | length' sast-findings.json)
    if [ "$CRITICAL" -gt 0 ]; then
      echo "FAIL: $CRITICAL critical SAST findings!"
      exit 1
    fi

SAST findet SQL-Injection-Muster, Hardcoded Secrets, unsichere Zufallszahlen (Math.random statt crypto.randomBytes), fehlende Input-Validierung und unsichere Konfigurationen. DAST-Tools wie OWASP ZAP Baseline Scan und Nuclei prüfen die laufende Staging-Applikation.

Container Security

# RICHTIG - sichere Dockerfile-Struktur
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN useradd --create-home appuser
USER appuser
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/health || exit 1
EXPOSE 8080
CMD ["python", "app.py"]

Wichtig: Niemals USER root in Produktion. Immer spezifische Versionen pinnen (FROM python:3.12.1-slim, nie latest). Lock-Dateien (package-lock.json, poetry.lock) immer committen.

Security Code Review Checkliste

Injection: SQL mit Parameterized Queries, Command Injection über execFile mit Array-Args, SSTI (keine User-Inputs in Template-Strings), XXE (external entities disabled), LDAP-Escaped, MongoDB Type-Check.

Authentifizierung & Session: Passwort-Hashing mit bcrypt/Argon2, kryptografisch zufällige Session-IDs, Session-Rotation nach Login, CSRF-Schutz auf state-changing Endpoints, Session-Timeout, serverseitiger Logout.

Autorisierung: Alle Endpoints authentifiziert, Ownership-Check (nicht nur Auth-Check, IDOR!), RBAC/ABAC korrekt, Admin-Funktionen doppelt geprüft, versteckte Felder serverseitig validiert.

Kryptografie: Keine selbst implementierte Krypto, starke Algorithmen (AES-256-GCM, RSA-4096/Ed25519, bcrypt/Argon2), Nonce-Wiederverwendung vermieden, Secrets in Env-Vars oder Secrets Manager, TLS 1.2+ erzwungen.

Input & Output: Alle User-Inputs validiert und sanitisiert, ausschließlich Parameterized Queries, HTML-Output escaped, File-Uploads validiert (Typ/Größe/Name), keine Stack Traces in Error Messages.

Logging: Keine sensiblen Daten geloggt, sicherheitsrelevante Ereignisse geloggt, kein Log-Injection durch User-Input.

Dependencies: npm audit / pip audit ausgeführt, keine bekannten CVEs, keine veralteten Kryptobibliotheken, neue Dependencies reviewed.

Reifegrad-Modell: OWASP SAMM

OWASP SAMM (Software Assurance Maturity Model) definiert drei Reifegrade:

Level 1 (Basis): OWASP Top 10 Schulung für Entwickler, manueller Security-Review vor Release, grundlegendes SAST im IDE, Security User Stories.

Level 2 (Fortgeschritten): Threat Modeling für neue Features, SAST und SCA in CI/CD-Pipeline, DAST auf Staging-Umgebung, Security Champions in Entwicklungsteams, Security Release Gates.

Level 3 (Führend): Kontinuierlicher Pentest (Bug Bounty), automatisiertes DAST in Production, Security Architecture Reviews, Red Team Exercises, SBOM für alle Releases.

Für die meisten deutschen KMU ist Level 1-2 realistisch und schützt gegen 80% der häufigsten Schwachstellen. Ein jährlicher Penetrationstest deckt auf, was CI/CD-Tools übersehen.

Quellen & Referenzen

  1. [1] OWASP Secure Coding Practices Quick Reference Guide - OWASP
  2. [2] Microsoft Security Development Lifecycle - Microsoft
  3. [3] NIST Secure Software Development Framework (SSDF) - NIST
  4. [4] OWASP Application Security Verification Standard (ASVS) - OWASP

Fragen zu diesem Thema?

Unsere Experten beraten Sie kostenlos und unverbindlich.

Erstberatung

Über den Autor

Chris Wojzechowski
Chris Wojzechowski

Geschäftsführender Gesellschafter

E-Mail

Geschäftsführender Gesellschafter der AWARE7 GmbH mit langjähriger Expertise in Informationssicherheit, Penetrationstesting und IT-Risikomanagement. Absolvent des Masterstudiengangs Internet-Sicherheit an der Westfälischen Hochschule (if(is), Prof. Norbert Pohlmann). Bestseller-Autor im Wiley-VCH Verlag und Lehrbeauftragter der ASW-Akademie. Einschätzungen zu Cybersecurity und digitaler Souveränität erschienen u.a. in Welt am Sonntag, WDR, Deutschlandfunk und Handelsblatt.

10 Publikationen
  • Einsatz von elektronischer Verschlüsselung - Hemmnisse für die Wirtschaft (2018)
  • Kompass IT-Verschlüsselung - Orientierungshilfen für KMU (2018)
  • IT Security Day 2025 - Live Hacking: KI in der Cybersicherheit (2025)
  • Live Hacking - Credential Stuffing: Finanzrisiken jenseits Ransomware (2025)
  • Keynote: Live Hacking Show - Ein Blick in die Welt der Cyberkriminalität (2025)
  • Analyse von Angriffsflächen bei Shared-Hosting-Anbietern (2024)
  • Gänsehaut garantiert: Die schaurigsten Funde aus dem Leben eines Pentesters (2022)
  • IT Security Zertifizierungen - CISSP, T.I.S.P. & Co (Live-Webinar) (2023)
  • Sicherheitsforum Online-Banking - Live Hacking (2021)
  • Nipster im Netz und das Ende der Kreidezeit (2017)
IT-Grundschutz-Praktiker (TÜV) IT Risk Manager (DGI) § 8a BSIG Prüfverfahrenskompetenz Ausbilderprüfung (IHK)
Dieser Artikel wurde zuletzt am 08.03.2026 bearbeitet. Verantwortlich: Chris Wojzechowski, Geschäftsführender Gesellschafter bei AWARE7 GmbH. Lizenz: CC BY 4.0 - freie Nutzung mit Namensnennung: „AWARE7 GmbH, https://a7.de