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 (14 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)

Traditioneller SDLC:
  Requirements → Design → Coding → Testing → Deployment → Maintenance

                                          Security-Test erst hier!

Secure SDLC (Microsoft SDL / OWASP SDLC):
  Requirements  → Sicherheitsanforderungen definieren
  Design        → Threat Modeling (STRIDE/PASTA)
  Coding        → Secure Coding Guidelines, SAST im IDE
  Testing       → DAST, Penetrationstest, SCA
  Deployment    → Security-Review, Secure Config
  Maintenance   → Patch-Management, Vulnerability Monitoring

Grundprinzipien Secure Coding

Die zehn wichtigsten Secure-Coding-Prinzipien:

1. Input Validation (Alle Eingaben sind verdächtig):
   → Validiere ALLES: HTTP-Parameter, Headers, Cookies, Dateiinhalte
   → Whitelist-basiert: was ERLAUBT ist, nicht was verboten
   → Validierung: so früh wie möglich, so nah an der Eingabe wie möglich

2. Output Encoding (Kontext-abhängig):
   → HTML-Context: HTML-Entity-Encoding (< → &lt;)
   → JavaScript-Context: JavaScript-Encoding (\x3C)
   → SQL-Context: Parameterized Queries (nie String-Konkatenation!)
   → URL-Context: URL-Encoding (%3C)
   → Falscher Kontext = XSS, Injection!

3. Authentication (Identität verifizieren):
   → Starke Passwort-Hashing-Algorithmen (bcrypt, Argon2, PBKDF2)
   → MFA für privilegierte Aktionen
   → Session-Management: zufällige Session-IDs, kurze Lifetime

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

5. Fail Secure (Bei Fehler: Zugang verweigern):
   → Exception = Zugang verwehren, nicht gewähren
   → 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

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

OWASP Application Security Verification Standard (ASVS):
  Level 1: Grundlegende Sicherheit (alle Anwendungen)
  Level 2: Standard-Sicherheit (business-critical)
  Level 3: Höchste Sicherheit (kritische Infrastruktur)

  Wichtigste ASVS-Anforderungen (Level 1):
  V1:  Architektur, Design und Bedrohungsmodell
  V2:  Authentifizierung (MFA, Session Management)
  V3:  Session Management (sichere Tokens, Timeout)
  V5:  Input Validation und Encoding (XSS, SQLi verhindern)
  V6:  Kryptographie (AES-256, TLS 1.2+, kein MD5!)
  V8:  Datenschutz (Logging, Fehlerbehandlung ohne Datenleck)
  V9:  Kommunikationssicherheit (TLS, Certificate Pinning)
  V14: Konfigurationssicherheit (Secrets, Dependencies)

Threat Modeling mit STRIDE

STRIDE-Bedrohungsmodell - pro Komponente analysieren:

Datenflussdiagramm (DFD):
Externe Nutzer


[Browser] ──HTTPS──► [Web-App-Server] ──► [DB-Server]

                           └──► [Auth-Service]

Vertrauensgrenzen (Trust Boundaries):
  Internet → DMZ → Intranet → Datenbank

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

Security Story Template:
  "Als [Angreifer] will ich [Angriffsaktion] um [Ziel] zu erreichen."
  Beispiel: "Als Angreifer will ich durch SQL-Injection die Kundendatenbank
  auslesen, um Kreditkartendaten zu stehlen."
  → Jede Security Story: entsprechende Test Case definieren

Input Validation Patterns

Richtige Input-Validierung (mehrere Sprachen):

Python (allgemein):
  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)  # HTML-Ausgabe sicher escapen

  try:
    valid = validate_email(email, check_deliverability=False)
    safe_email = valid.email
  except EmailNotValidError:
    raise ValueError("Ungültige E-Mail")

Java (Spring Bean Validation - JSR-380):
  public class UserRequest {
    @NotBlank @Size(min=3, max=50)
    @Pattern(regexp = "^[a-zA-Z0-9_-]+$",
             message = "Nur erlaubte Zeichen")
    private String username;

    @Email @NotBlank
    private String email;

    @Min(0) @Max(150)
    private Integer age;
  }

Node.js (Zod):
  import { z } from 'zod';

  const UserSchema = z.object({
    username: z.string()
      .min(3).max(50)
      .regex(/^[a-zA-Z0-9_-]+$/),
    email: z.string().email(),
    age: z.number().int().min(0).max(150).optional()
  });

  const result = UserSchema.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json(result.error.flatten());
  }

Datei-Upload-Validierung:
  ALLOWED_MIME_TYPES = {'image/jpeg', 'image/png', 'image/webp'}
  MAX_SIZE_BYTES = 5 * 1024 * 1024  # 5MB

  import magic  # python-magic liest MagicBytes, nicht nur Extension!
  mime = magic.from_buffer(file.read(1024), mime=True)
  if mime not in ALLOWED_MIME_TYPES:
    raise ValueError(f"Unerlaubter Dateityp: {mime}")
  # MagicBytes prüfen, NICHT den Dateinamen!
  # upload.jpg.php → MagicBytes = PHP → geblockt!

  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

SQL Injection Prevention

Sichere Datenbankabfragen - das Grundprinzip:

Python (sqlite3/psycopg2):
  # FALSCH - SQL Injection möglich:
  query = f"SELECT * FROM users WHERE username='{username}'"
  cursor.execute(query)

  # 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()

Java (PreparedStatement):
  // FALSCH:
  Statement stmt = conn.createStatement();
  ResultSet rs = stmt.executeQuery(
    "SELECT * FROM users WHERE id=" + userId);

  // RICHTIG:
  PreparedStatement ps = conn.prepareStatement(
    "SELECT * FROM users WHERE id = ?");
  ps.setInt(1, userId);
  ResultSet rs = ps.executeQuery();

Node.js (pg):
  // FALSCH:
  const result = await pool.query(
    `SELECT * FROM orders WHERE user_id='${userId}'`);

  // RICHTIG:
  const result = await pool.query(
    'SELECT * FROM orders WHERE user_id = $1',
    [userId]
  );

  // Prisma ORM (sicher by design):
  const user = await prisma.user.findUnique({
    where: { id: userId }
  });

NoSQL Injection (MongoDB):
  // FALSCH:
  db.users.find({ username: req.body.username })
  // Wenn username = { $gt: "" } → alle User!

  // RICHTIG - Type-Check:
  if (typeof req.body.username !== 'string') {
    return res.status(400).send('Invalid input');
  }
  // NIEMALS: db.users.find({ $where: "this.field..." })

Authentifizierung und Session Management

Sichere Passwort-Verwaltung:

Algorithmen:
  RICHTIG:   bcrypt (weit verbreitet, solide), Argon2id (aktuellster Standard)
             scrypt (memory-hard), PBKDF2 (FIPS-Konformität)
  FALSCH:    MD5, SHA-1, SHA-256 allein!
             Ohne Salt: Rainbow-Table-Angriffe möglich!
             Zu schnell: Brute-Force in Sekunden!

Python (Argon2id):
  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")  # Upgrade bei neuen Params
  except VerifyMismatchError:
    raise ValueError("Falsches Passwort")

Node.js (bcrypt):
  const bcrypt = require('bcrypt');
  const ROUNDS = 12;
  const hash = await bcrypt.hash(password, ROUNDS);
  const valid = await bcrypt.compare(password, hash);

Java (BCryptPasswordEncoder):
  PasswordEncoder encoder = new BCryptPasswordEncoder(12);
  String hashed = encoder.encode(rawPassword);
  boolean valid = encoder.matches(rawPassword, hashed);

Session-Management:
  # Session-ID: kryptografisch zufällig, mind. 128 Bit:
  import secrets
  session_id = secrets.token_hex(32)  # 256 Bit

  # Session-Cookie-Attribute:
  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!):
  old_session_data = get_session(old_id)
  new_id = secrets.token_hex(32)
  create_session(new_id, old_session_data)
  delete_session(old_id)

JWT (korrekt verwenden):
  const token = jwt.sign(
    { userId: user.id, role: user.role },
    process.env.JWT_SECRET,  # stark, aus Env!
    { expiresIn: '1h', algorithm: 'RS256' }  # asymmetrisch!
  );
  # NIEMALS: algorithms=["none"] oder ohne Algorithmus-Angabe!

Secrets Management

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

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

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

  # Azure Key Vault:
  from azure.keyvault.secrets import SecretClient
  # AWS Secrets Manager, GCP Secret Manager analog

.gitignore: immer .env hinzufügen!
  echo ".env" >> .gitignore

Pre-commit Hooks für Secret Detection:
  pip install detect-secrets
  detect-secrets scan > .secrets.baseline
  # Gitleaks: pre-commit hook in .pre-commit-config.yaml

Kryptographie-Patterns in der Entwicklung

Sichere Kryptographie in Applikationen:

Symmetrische Verschlüsselung (AES-GCM):
  from cryptography.hazmat.primitives.ciphers.aead import AESGCM
  import os

  key = AESGCM.generate_key(bit_length=256)
  aesgcm = AESGCM(key)

  nonce = os.urandom(12)   # 96 Bit Nonce, EINMALIG!
  ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)
  stored = nonce + ciphertext  # Nonce mit gespeichert

  nonce = stored[:12]
  ciphertext = stored[12:]
  plaintext = aesgcm.decrypt(nonce, ciphertext, associated_data)
  # WICHTIG: Nonce niemals wiederverwenden! (GCM-Nonce-Misuse-Angriff)

Asymmetrische Signaturen (Ed25519):
  from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
  private_key = Ed25519PrivateKey.generate()
  public_key = private_key.public_key()
  signature = private_key.sign(message)
  public_key.verify(signature, message)  # Exception wenn ungültig

Zufallszahlen für Sicherheitszwecke:
  Python:   secrets.token_bytes(32)    # kryptografisch sicher!
  Java:     SecureRandom.getInstanceStrong()
  Node.js:  crypto.randomBytes(32)
  Go:       crypto/rand.Read()

  NIEMALS für Security:
  Python: random.random()  → NICHT kryptografisch sicher!
  Java:   Math.random()    → NICHT kryptografisch sicher!
  JS:     Math.random()    → NICHT kryptografisch sicher!

Fehlerbehandlung und sicheres Logging

Keine internen Details ans Frontend:

FALSCH:
  try:
    result = database_query(user_id)
  except Exception as e:
    return {"error": str(e)}  # DB-Struktur, Tabellennamen, SQL-Details!

RICHTIG:
  import uuid
  try:
    result = database_query(user_id)
  except DatabaseError as e:
    error_id = str(uuid.uuid4())
    logger.error(f"[{error_id}] DB error for user {user_id}: {e}", exc_info=True)
    return {"error": "Interner Fehler", "reference": error_id}, 500

Sicheres Logging:
  NIEMALS loggen:
  □ Passwörter (auch falsche Logins!)
  □ Session-IDs / Tokens
  □ Kreditkartennummern (PCI-DSS!)
  □ Private Keys
  □ Vollständige PII (DSGVO!)

  Maskierung sensibler Daten:
  def mask_sensitive(data: dict) -> dict:
    SENSITIVE_KEYS = {'password', 'token', 'credit_card', 'secret'}
    return {
      k: '***' if k.lower() in SENSITIVE_KEYS else v
      for k, v in data.items()
    }

  Structured Logging (für SIEM-Integration):
  import structlog
  log = structlog.get_logger()
  log.warning(
    "failed_login",
    username=username,
    ip=request.remote_addr,
    user_agent=request.headers.get('User-Agent'),
    timestamp=datetime.utcnow().isoformat()
  )
  # JSON-Format → einfach in SIEM importierbar

Security Testing in CI/CD

Automatisierte Sicherheitsprüfungen:

SAST (Static Application Security Testing):
  Semgrep (Open Source):
  - name: Run Semgrep
    uses: returntocorp/semgrep-action@v1
    with:
      config: >-
        p/owasp-top-ten
        p/python
        p/javascript
        p/docker

  CodeQL (GitHub Actions, kostenlos für Open Source):
  - name: Initialize CodeQL
    uses: github/codeql-action/init@v3
    with:
      languages: python, javascript

  Was SAST findet:
  → SQL Injection-Muster
  → Hardcoded Secrets (Passwort in Code)
  → Unsichere Zufallszahlen (Math.random statt crypto.randomBytes)
  → Fehlende Input-Validierung
  → Unsichere Konfigurationen (CORS: *)

SCA (Software Composition Analysis):
  Trivy (Alle-in-einem-Scanner):
  trivy image myapp:latest              # Container scannen
  trivy fs --scanners vuln,secret,misconfig ./  # Filesystem
  trivy image --format cyclonedx --output sbom.json myapp:latest  # SBOM

  Python SCA:
  pip install pip-audit
  pip-audit --vulnerability-service pypi

  Node.js:
  npm audit --audit-level=high

  Dependabot (.github/dependabot.yml):
  version: 2
  updates:
    - package-ecosystem: "npm"
      directory: "/"
      schedule:
        interval: "weekly"
      open-pull-requests-limit: 10

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

  # Trufflehog (tieferer Scan inkl. Commit-History):
  - name: TruffleHog OSS
    uses: trufflesecurity/trufflehog@main
    with:
      extra_args: --only-verified

DAST (Dynamic Application Security Testing):
  OWASP ZAP Baseline Scan in CI/CD:
  - name: ZAP Baseline Scan
    uses: zaproxy/action-baseline@v0.10.0
    with:
      target: 'https://staging.meineapp.de'
      cmd_options: '-T 120'

  Nuclei (Template-basiert):
  nuclei -u https://staging.meinapp.de -t cves/ -t misconfigurations/

Container Security

Dockerfile Best Practices:

FALSCH:
FROM ubuntu:latest
RUN apt-get install -y python3 && pip install -r requirements.txt
USER root  # niemals!

RICHTIG:
FROM python:3.12-slim  # minimal image
WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Non-root user:
RUN useradd --create-home appuser
USER appuser

# Health check:
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/health || exit 1

EXPOSE 8080
CMD ["python", "app.py"]

Dependency Pinning:
  → package-lock.json / yarn.lock / poetry.lock immer committen! (reproduzierbare Builds)
  → Regelmäßig aktualisieren (Dependabot/Renovate)
  → pip: requirements.txt mit exakten Versionen:
    flask==3.0.1  # nicht flask>=3.0.0!
  → Docker: nie "latest" in Produktion:
    FROM python:3.12.1-slim  # spezifische Version!

Security Release Gates

Pflichtprüfungen vor Deployment:

Definition of Done (Security):
  → SAST: 0 kritische Findings (Semgrep/SonarQube)
  → SCA: 0 kritische CVEs in Dependencies (Trivy/Snyk)
  → Secrets Scan: 0 Secrets im Code (GitLeaks/detect-secrets)
  → DAST Baseline: 0 High/Critical in Staging (ZAP)
  → Security Code Review: abgenommen

GitHub Actions Security Gate:
  security-gate:
    runs-on: ubuntu-latest
    needs: [sast, sca, secrets-scan]
    steps:
      - name: Check security scan results
        run: |
          if [ -f sast-findings.json ]; then
            CRITICAL=$(jq '[.[] | select(.severity == "CRITICAL")] | length' sast-findings.json)
            if [ "$CRITICAL" -gt 0 ]; then
              echo "FAIL: $CRITICAL critical SAST findings!"
              exit 1
            fi
          fi

SBOM (Software Bill of Materials):
  → ISO/IEC 5962, SPDX oder CycloneDX Format
  → Pflicht für: US-Regierungsaufträge (Executive Order 2021)
  → Empfohlen: KRITIS-Betreiber, kritische Anwendungen
  → Syft: syft myapp:latest -o cyclonedx-json > sbom.json

Security Code Review Checkliste

Quick-Reference für Code-Reviews:

Injection-Prüfung:
  □ SQL: Parameterized Queries überall? (grep nach String-Konkatenation mit SQL)
  □ Command Injection: Shell-Aufrufe → nur execFile mit Array-Args
  □ SSTI: Template-Strings mit User-Input? (nur Variables, nie inline!)
  □ XXE: XML-Parser konfiguriert? (external entities disabled)
  □ LDAP-Injection: LDAP-Queries escaped?
  □ NoSQL Injection: Type-Check vor MongoDB-Queries?

Authentifizierung & Session:
  □ Passwort-Hashing: bcrypt/Argon2? (kein MD5, SHA-1, SHA-256 allein!)
  □ Session-IDs: kryptografisch zufällig (crypto.randomBytes)?
  □ Session-Rotation nach Login?
  □ CSRF-Schutz auf state-changing Endpoints?
  □ Session-Timeout implementiert?
  □ Logout: Session serverseitig invalidiert?

Autorisierung:
  □ Alle Endpoints: Authentifizierung erzwungen?
  □ Jede Ressource: Ownership-Check (nicht nur Auth-Check! IDOR!)
  □ RBAC/ABAC korrekt implementiert?
  □ Admin-Funktionen: doppelte Prüfung?
  □ Versteckte Felder/Parameter: serverseitig validiert (nicht vertrauen!)?

Kryptografie:
  □ Keine selbst implementierte Krypto?
  □ Starke Algorithmen: AES-256-GCM, RSA-4096/Ed25519, bcrypt/Argon2?
  □ Nonce-Wiederverwendung vermieden?
  □ Secrets nicht im Code (Env-Vars oder Secrets Manager)?
  □ TLS: Version 1.2+ erzwungen?

Input & Output:
  □ Alle User-Inputs: validiert und sanitisiert?
  □ SQL: ausschließlich Parameterized Queries?
  □ HTML Output: escaped (XSS-Schutz)?
  □ File Uploads: Typ/Größe/Name validiert?
  □ Error Messages: keine Stack Traces, keine interne Info!

Logging:
  □ Keine sensiblen Daten in Logs (Passwörter, Tokens, Kreditkarten!)?
  □ Sicherheitsereignisse geloggt (Login, Fehler, Rechte-Zugriff)?
  □ Logs nicht manipulierbar durch User-Input (Log Injection)?

Dependencies:
  □ npm audit / pip audit / mvn dependency-check ausgeführt?
  □ Bekannte CVEs in Dependencies?
  □ Keine veralteten Kryptobibliotheken?
  □ Neue Dependencies: Sicherheits-Review durchgeführt?

Reifegrad-Modell: OWASP SAMM

OWASP SAMM (Software Assurance Maturity Model) - Reifegrade:

Level 1 (Basis):
  ✓ OWASP Top 10 Schulung für Entwickler
  ✓ Manueller Security-Review vor Release
  ✓ Grundlegendes SAST in IDE
  ✓ Security User Stories

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

Level 3 (Führend):
  ✓ Kontinuierlicher Pentest (Bug Bounty)
  ✓ Automatisierte 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 Penetrationstest jährlich
deckt auf, was CI/CD-Tools übersehen.

Quellen & Referenzen

  1. [1] OWASP Secure Coding Practices Quick Reference Guide - OWASP
  2. [2] OWASP Secure Development Lifecycle - OWASP
  3. [3] Microsoft Security Development Lifecycle - Microsoft
  4. [4] NIST Secure Software Development Framework (SSDF) - NIST
  5. [5] 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

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

Cookielose Analyse via Matomo (selbst gehostet, kein Tracking-Cookie). Datenschutzerklärung