SQL Injection verhindern: Sichere Datenbank-Abfragen | Enjyn Gruppe
Hallo Welt
Hallo Welt
Original Lingva Deutsch
Übersetzung wird vorbereitet...
Dieser Vorgang kann bis zu 60 Sekunden dauern.
Diese Seite wird erstmalig übersetzt und dann für alle Besucher gespeichert.
0%
DE Zurück zu Deutsch
Übersetzung durch Lingva Translate

235 Dokumentationen verfügbar

Wissensdatenbank

SQL Injection Verhindern

Zuletzt aktualisiert: 20.01.2026 um 10:05 Uhr

SQL Injection verhindern: Sichere Datenbank-Abfragen

SQL Injection ist eine der gefährlichsten Sicherheitslücken. Angreifer können damit Daten stehlen, ändern oder löschen. So schützen Sie Ihre Anwendung.

Was ist SQL Injection?

Bei SQL Injection schleust ein Angreifer schädlichen SQL-Code über Benutzereingaben ein:

// GEFÄHRLICH: Benutzereingabe direkt im Query
$username = $_POST['username'];
$query = "SELECT * FROM users WHERE username = '$username'";

// Angreifer gibt ein:
// ' OR '1'='1

// Ergebnis:
SELECT * FROM users WHERE username = '' OR '1'='1'
// → Gibt ALLE User zurück!

Mögliche Angriffe

  • Daten auslesen: UNION-basierte Angriffe
  • Authentication Bypass: Login umgehen
  • Daten löschen: DROP TABLE, DELETE
  • Daten ändern: UPDATE, INSERT
  • Kommandos ausführen: xp_cmdshell (MSSQL)

Lösung: Prepared Statements

Prepared Statements trennen SQL-Code von Daten. Der sicherste Schutz!

PHP mit PDO

<?php
// ✅ SICHER: Prepared Statement
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->execute(['username' => $username]);
$user = $stmt->fetch();

// Auch für INSERT, UPDATE, DELETE
$stmt = $pdo->prepare("INSERT INTO users (username, email) VALUES (?, ?)");
$stmt->execute([$username, $email]);

// Mit mehreren Parametern
$stmt = $pdo->prepare("
    SELECT * FROM products
    WHERE category = :category
    AND price < :maxPrice
    ORDER BY name
");
$stmt->execute([
    'category' => $category,
    'maxPrice' => $maxPrice
]);

PHP mit MySQLi

<?php
// Prepared Statement mit MySQLi
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $username);  // "s" = string
$stmt->execute();
$result = $stmt->get_result();

// Typ-Spezifikationen:
// s = string
// i = integer
// d = double
// b = blob

$stmt = $mysqli->prepare("INSERT INTO users (name, age, score) VALUES (?, ?, ?)");
$stmt->bind_param("sid", $name, $age, $score);
$stmt->execute();

Node.js mit mysql2

// ✅ SICHER: Parametrisierte Query
const [rows] = await connection.execute(
  'SELECT * FROM users WHERE username = ?',
  [username]
);

// Mehrere Parameter
const [results] = await connection.execute(
  'SELECT * FROM products WHERE category = ? AND price < ?',
  [category, maxPrice]
);

// Mit Named Parameters
const [rows] = await connection.execute(
  'SELECT * FROM users WHERE username = :username',
  { username: username }
);

Python mit psycopg2 (PostgreSQL)

import psycopg2

# ✅ SICHER: Parametrisierte Query
cursor.execute(
    "SELECT * FROM users WHERE username = %s",
    (username,)
)

# Mehrere Parameter
cursor.execute(
    """
    INSERT INTO users (username, email, age)
    VALUES (%s, %s, %s)
    """,
    (username, email, age)
)

# Mit Named Parameters
cursor.execute(
    "SELECT * FROM users WHERE username = %(user)s",
    {'user': username}
)

Dynamische Queries sicher bauen

Whitelist für Spaltennamen

<?php
// Spaltennamen können NICHT als Parameter übergeben werden!
// Lösung: Whitelist

$allowedColumns = ['name', 'email', 'created_at'];
$orderBy = in_array($orderBy, $allowedColumns) ? $orderBy : 'name';

$stmt = $pdo->prepare("SELECT * FROM users ORDER BY $orderBy");
$stmt->execute();

Whitelist für Sortierrichtung

<?php
$direction = strtoupper($direction) === 'DESC' ? 'DESC' : 'ASC';
$stmt = $pdo->prepare("SELECT * FROM users ORDER BY name $direction");

IN-Clause mit variabler Anzahl

<?php
$ids = [1, 2, 3, 4, 5];
$placeholders = str_repeat('?,', count($ids) - 1) . '?';

$stmt = $pdo->prepare("SELECT * FROM users WHERE id IN ($placeholders)");
$stmt->execute($ids);

Was NICHT funktioniert

❌ Unsichere Methoden:
  • Escaping allein: mysql_real_escape_string ist unzureichend
  • Blacklists: Gefährliche Zeichen filtern (umgehbar)
  • addslashes(): Nicht sicher für SQL
  • Typ-Casting allein: Nur für Integers hilfreich
// ❌ UNSICHER: Escaping
$username = mysqli_real_escape_string($conn, $username);
$query = "SELECT * FROM users WHERE username = '$username'";
// Kann bei bestimmten Zeichensätzen umgangen werden!

// ❌ UNSICHER: Blacklist
$username = str_replace("'", "", $username);
// Kann durch Encoding umgangen werden!

Zusätzliche Schutzmaßnahmen

1. Minimale Datenbankrechte

-- Eigener User für die Anwendung
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'password';

-- Nur notwendige Rechte
GRANT SELECT, INSERT, UPDATE ON myapp.* TO 'app_user'@'localhost';
-- KEIN DROP, DELETE, ALTER etc.

2. Input-Validierung

<?php
// Zusätzlich zu Prepared Statements!
$email = filter_var($email, FILTER_VALIDATE_EMAIL);
if (!$email) {
    throw new InvalidArgumentException('Invalid email');
}

$age = filter_var($age, FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 0, 'max_range' => 150]
]);

3. Web Application Firewall (WAF)

ModSecurity oder Cloud-WAFs wie Cloudflare erkennen SQLi-Versuche.

Testen auf SQL Injection

  • sqlmap: Automatisiertes SQLi-Testing
  • Burp Suite: Manuelles Testing
  • OWASP ZAP: Kostenloser Scanner
# sqlmap Beispiel
sqlmap -u "https://example.com/page?id=1" --dbs
💡 Zusammenfassung: IMMER Prepared Statements verwenden. Keine Ausnahmen. Das ist die einzig sichere Methode gegen SQL Injection.

Weitere Informationen

Enjix Beta

Enjyn AI Agent

Hallo 👋 Ich bin Enjix — wie kann ich dir helfen?
120