decocode decocode deco    

Skripte gegen SQL-Injection absichern #

► PHP-Dokumentation: mysqli_escape_string()

SQL-Injection ist ein häufiges Mittel, das es Angreifern ermöglicht, eine Webseite zu hacken. Daher sollte bei der Verwendung von MySQL besonders darauf geachtet werden, dass die PHP-Skripte keine Sicherheitslücken dieser Art enthalten.

Folgendes Skript soll das veranschaulichen:

Quelltext auswählen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php
  $thisfile = basename(__FILE__);
  $db_user     = "web007";        # Benutzername
  $db_password = "g5Rd3dfCvf";    # Benutzerpasswort
  $db_name     = "usr_web007_1";  # Name der Datenbank
  
  # Verbindung zum Datenbank-Server herstellen
  $my = mysqli_connect("localhost", $db_user, $db_password, $db_name)
  or die("Keine Verbindung zur Datenbank: ".mysqli_connect_error()); 
  mysqli_set_charset($my, "utf8");
  
  # Datenbanktabelle erzeugen
  $sql = "CREATE TABLE IF NOT EXISTS `injection` (
    `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `name` VARCHAR(30),
    `private` SMALLINT UNSIGNED,
    `phone` VARCHAR(5)
  ) CHARSET=utf8";
  if (!mysqli_query($my, $sql)) die(mysqli_error($my));
  
  # Datenbanktabelle befüllen
  if (!mysqli_num_rows(mysqli_query($my, "SELECT `id` FROM `injection`"))) {
    $data = array(
      array("Hans", 0, "71123"),
      array("Tine", 0, "74532"),
      array("Hugo", 0, "90872"),
      array("Ines", 0, "00453"),
      array("Olaf", 0, "16539"),
      array("Vera", 1, "44633"),
      array("Toni", 1, "95562"),
      array("Mona", 1, "78786"),
      array("Otto", 1, "24322"),
      array("Nora", 1, "08773")
    );
    foreach ($data as $d) {
      $sql = "INSERT INTO `injection` (`name`, `private`, `phone`) VALUES (
        '".mysqli_escape_string($my, $d[0])."',
        ".$d[1].",
        '".mysqli_escape_string($my, $d[2])."'
      )";
      if (!mysqli_query($my, $sql)) die(mysqli_error($my));
    }
  }
  
  # Ausgabe
  header("Content-Type: text/html; charset=utf-8");
  echo "<!DOCTYPE html>
<html lang='de'>
  <head>
    <title>SQL-Injection</title>
    <meta charset='UTF-8'>
    <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
  </head>
  <body>
    <h3>Öffentliche Einträge:</h3>
    <p>\r\n";
  $res = mysqli_query($my, "SELECT * FROM `injection` WHERE `private` = '0'");
  if ($res) {
    while ($ds = mysqli_fetch_array($res)) {
      echo "      <a href='".$thisfile."?show=".$ds['id']."'>".$ds['name']."</a></br>\r\n";
    }
  } else die(mysqli_error());
  echo "    </p>\r\n";
  
  # Individuellen Eintrag anzeigen
  if (isset($_GET['show'])) {
    $id = $_GET['show'];
    //$id = mysqli_escape_string($my, $_GET['show']);
    $sql = "SELECT * FROM `injection` WHERE `private` = '0' AND id = '".$id."'";
    $res = mysqli_query($my, $sql);
    if ($res && $ds = mysqli_fetch_array($res)) echo "    <p><b>".$ds['name'].": Telefon ".$ds['phone']."</b></p>\r\n";
    else echo "    <p><mark>Der Eintrag ist nicht verfügbar!</mark></p>\r\n";
  }
  
  echo "<p>Die privaten Einträge 6-10 können sichtbar gemacht werden, in dem man den Wert von <samp>show</samp> durch <samp>x</samp> ersetzt und an die URL folgenden SQL-Code anhängt:<br><samp>'+OR+id+=+'x</samp><br>wobei <samp>x</samp> die ID des gewünschten Eintrags ist.</p>";
  echo"  </body>
</html>";
?>

Die privaten Einträge 6-10 können sichtbar gemacht werden, indem man den Wert von show durch x ersetzt und an die URL folgenden SQL-Code anhängt:

'+OR+id+=+'x

wobei x die ID des gewünschten Eintrags ist.

Durch Entfernen des Kommentarzeichens // in Zeile 69 wird der SQL-Befehl mit der Funktion mysql_escape_string() vor SQL-Injection geschützt.

Ebenso sollte man alle alphanumerische Werte in SQL-Befehlen mit dieser Funktion vorbereiten, da damit bestimmte Sonderzeichen escapet werden, um Syntaxfehler zu vermeiden (s. Zeilen 38 und 40).