Ankündigung

Einklappen
Keine Ankündigung bisher.

Sicherheitslücke

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Sicherheitslücke

    Hallo, ich wollte mal fragen ob Ihr mal auf mein Script schauen könnt und mir sagt, ob ich noch irgendwo eine gravierende Sicherheitslücke habe:
    PHP-Code:
    //**********************************************
    // Abhängigkeiten einbinden
    //**********************************************

        // escape
        function e($s) { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); }

        // abhängige Dateien
        include('../Connections/astro_error_report.php'); 
        include('../Connections/astro_dbconnect.php'); 


    //**********************************************
    // Initialisierung
    //**********************************************

        mysqli_select_db($verbindung, $datenbank) or die ("Die Datenbank existiert nicht");

    //**********************************************
    // Standardwerte für Templatevariablen
    //**********************************************

        $id = '';
        $errors = array();
        $formSent = false;

    // Verarbeitungslogik

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $formSent = true;

            $id = (isset($_POST['id']))
                ? $_POST['id']
                //? (int) $_POST['id'] 
                : $id;
        }
            if (!ctype_digit($id)){ 
                $errors[] = 'Keine bzw. ungültige ID angegeben';
            }
            if (count($errors) === 0) {
                $sql = "
                        DELETE FROM
                            benutzer
                        WHERE intID = $id 
                        ";      
                $abfrage = mysqli_query($verbindung, $sql);     
            }
        }

    ?>

    <?php if (count($errors) > 0): ?>
        <h2>Fehler</h2>
        <ol>
        <?php foreach ($errors as $message) : ?>
            <li><?php echo e($message?></li>
        <?php endforeach; ?>
        </ol>
        <p>Bitte überprüfen Sie Ihre Eingaben.</p>
    <?php endif; ?>



    <?php if (count($errors) === && $formSent) : ?>
        <p>Daten gelöscht.</p>
        <pre><?php echo e(print_r($_POSTtrue)) ?></pre>
    <?php else : ?>
        <form method="post" action="<?php echo e($_SERVER['SCRIPT_NAME']) ?>">
        <table>
        <tbody>
        <tr>
        <td>intID</td>
        <td><input type="text" name="id" value="<?php echo e($id?>" /></td>
        </tr>
        </tbody>
        </table>
        <br />
        <input type="submit" name="loeschen" value="Löschen" />
        </form>
        <?php 
                $selectsql 
    "SELECT * FROM benutzer";

                
    $abfrage mysqli_query($verbindung$selectsql);
                            
                echo 
    '<h3>Es gibt ' mysqli_num_rows($abfrage) . ' User</h3>';

                 echo 
    "<table class='daten' >";
                echo 
    "<thead>";
                echo 
    "<th class='daten'>"'ID' "</th>"
                echo 
    "<th class='daten'>"'Vorname' "</th>"
                echo 
    "<th class='daten'>"'Nachname' "</th>"
                echo 
    "<th class='daten'>"'Anlagedatum' "</th>"
                echo 
    "</thead>";
                while(
    $userdaten mysqli_fetch_assoc($abfrage))
                {
                echo 
    "<tr>";
                echo 
    "<td class='daten'>"$userdaten['intID'] . "</td>"
                echo 
    "<td class='daten'>"$userdaten['strVorname'] . "</td>"
                echo 
    "<td class='daten'>"$userdaten['strNachname']  . "</td>";
                echo 
    "<td class='daten'>"$userdaten['dtmAnlage'] . "</td>"
                echo 
    "</tr>"
                 }
                 echo 
    "</table>";
         
    ?>
    <?php 
    endif; ?>

  • #2
    Sicherheitslücke oder nicht .. wenn du sowieso das gleiche Script mit der Formularverarbeitung aufrufst, dann lass deine form action="" gleich ganz LEER (nicht weglassen) ...

    und du müsstest dich noch um den Fall id=0 kümmern - wenn die id ein auto_increment -Wert ist, dann fängt die normal bei 1 an .. genau wie du auch prüfen solltest, ob überhaupt eine vergebene id gelöscht werden soll ....

    wenn du sowieso die User tabellarisch darstellst, warum listest du sie nicht stattdessen in einer <select-Liste auf ... dann kann man gleich einen der bestehenden User auswählen .. Eintippen vergrößert die Möglichkeit von Fehleingaben ungemein
    [Quote=nikosch]
    So glatt kann doch wirklich keiner sein.[/quote] :roll:

    Kommentar


    • #3
      Danke für die wertvollen Tips. Das mit der Select-Geschichte ist eine super Idee, da hab ich eine schöne Knobelaufgabe. Ich werde aber vorher noch versuchen, das mit der Überprüfung hinzubekommen ob die zu löschende ID überhaupt existiert.

      Ich übe ja noch kräftig, sowas bekomm ich noch nicht so schnell hin.

      Kommentar


      • #4
        Zitat von beliar284
        Sicherheitslücke oder nicht .. wenn du sowieso das gleiche Script mit der Formularverarbeitung aufrufst, dann lass deine form action="" gleich ganz LEER (nicht weglassen) ...
        Weißt du sicher, dass das in HTML5 erlaubt ist? (Keine rhetorische Frage.)

        - http://phpforum.de/forum/showthread.php?t=267795
        - http://xhtmlforum.de/67503-haltet-ihr-von-php-self.html
        - http://www.php-resource.de/forum/php...nem-order.html

        Kommentar


        • #5
          Ich habe jetzt den Block mit den if Bedingungen wie folgt geändert:
          PHP-Code:
                  if (!ctype_digit($id) OR $id == 0){ 
                      
          $errors[] = 'Keine bzw. ungültige ID angegeben';
                  }
                  
          $vorhanden mysqli_query($verbindung"SELECT intID FROM benutzer WHERE intID = $id");
                  if (
          mysqli_num_rows($vorhanden) == 0) {
                      
          $errors[] = 'Diese ID ist nicht vorhanden';
                  }
                  if (
          count($errors) === 0) {
                      
          $sql "
                              DELETE FROM
                                  benutzer
                              WHERE intID = 
          $id 
                              "
          ;      
                      
          $abfrage mysqli_query($verbindung$sql);     
                  } 
          Funktionieren tut dies, es gibt also eine Fehlermeldung wenn ich eine id löschen will, welche nicht in der DB existiert. Ist daran etwas verbesserungswürdig? Also dass
          PHP-Code:
          $vorhanden mysqli_query($verbindung"SELECT intID FROM benutzer WHERE intID = $id");
                  if (
          mysqli_num_rows($vorhanden) == 0) {
                      
          $errors[] = 'Diese ID ist nicht vorhanden';
                  } 
          habe ich hinzugefügt.

          Kommentar


          • #6
            PHP-Code:
            $vorhanden mysqli_query($verbindung"SELECT intID FROM benutzer WHERE intID = $id"); 
            Diese Zeile wird auch erreicht, wenn in $id keine Zahl > 0 steht. Eine Angabe für $_POST['id'] von "1 OR 1" dürfte dir die Tabelle leerräumen.

            Edit: Ne, doch nicht. Der DELETE-Befehl steht ja in der „Wenn kein Fehler“-Bedingung. Haarscharf.

            Kommentar


            • #7
              Wäre trotzdem empfehlenswert die id zu casten!

              Kommentar


              • #8
                Oder die ID in Anführungszeichen (also als String) in die Query einzufügen und zu escapen.

                Kommentar


                • #9
                  Hallo,

                  Alternativ kannst du dir mal PDO (http://de2.php.net/pdo) anschauen - da wird bei prepared Statements die Sicherheit von Parametern (soweit ich weiß) automaisch gewährleistet.

                  Beispiel (ungetestet):
                  PHP-Code:
                  <?php

                  // Konfiguration - setzten des Datenbank-Hosts sowie des Datenbank-Namens und die Zugangsdaten
                  $dsn 'mysql:dbname=testdb;host=127.0.0.1';
                  $user 'dbuser';
                  $password 'dbpass';

                  // PDO wirft im Fehlerfall Expetions (per default) - daher sollte der Verbindungsaufbau in einem "try"-Block sein
                  try {
                      
                  // PDO ist eine PHP-Interne Klasse und für alle gängigen Datenbanktreiber im jeweiligen Paket enthalten
                      // Doku: http://de2.php.net/manual/de/pdo.construct.php
                      
                  $dbh = new PDO($dsn$user$password);
                  } catch (
                  PDOException $e) {
                      
                  // Zeige eine Fehlermeldung an falls die Verbindung fehlschläft
                      // Doku zur PDOException und verfügbaren Methoden: http://de2.php.net/manual/de/class.pdoexception.php
                      
                  echo 'Connection failed: ' $e->getMessage();
                  }

                  // PDO den SQL-Query mit Platzhaltern für die Werte vorbereiten lassen
                  // Doku: http://de2.php.net/manual/de/pdo.prepare.php
                  $sth $dbh->prepare(
                      
                  'SELECT 
                          name, 
                          colour, 
                          calories 
                      FROM 
                          fruit 
                      WHERE 
                          calories < :calories AND 
                          colour = :colour'
                  );

                  // Execute führt den SQL-Query aus, hier werden die Parameter als Array (Platzhalter => Wert) übergeben
                  // Normalerweise sind die Werte natürlich nicht Hardcoded sondern z.B. User-Inputs!
                  // Doku: http://de2.php.net/manual/de/pdostatement.execute.php
                  $sth->execute(array(
                    
                  ':calories' => 150,
                    
                  ':colour' => 'red'
                  ));

                  /* Damit erhalten wir die nächste Zeile des Result-Sets 
                   * (wird meistens genutzt wenn nur eine Zeile angefordert wird z.B. wenn die Abfrage im WHERE-Teil durch eine eindeutige ID 
                   * z.B. mit Primary-Key oder UNIQUE versehen ist.
                   * Wichtig: Als erster Parameter kann der Fetch-Style übergeben werden d.h. was für ein Result-Typ man bekommen will z.B. Num oder Assoc
                   * Doku: http://de2.php.net/manual/de/pdostatement.fetch.php
                  */
                  $data $sth->fetch();

                  // Gibt alle Zeilen die auf das Statement passen als Array zurück
                  // Wichtig: Als erster Parameter kann der Fetch-Style übergeben werden d.h. was für ein Result-Typ man bekommen will z.B. Num oder Assoc
                  // Doku: http://de2.php.net/manual/de/pdostatement.fetchall.php
                  $dataAll $sth->fetchAll();

                  ?>
                  Ist jetzt relativ schnell aus den Beispielen zusammenkopiert und kommentiert - hoffe das passt so

                  Kommentar


                  • #10
                    Die Unsitte, in irgend nem Include die DB-Connection aufzumachen werde ich nie verstehen…
                    [COLOR="#F5F5FF"]--[/COLOR]
                    [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
                    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                    [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
                    [COLOR="#F5F5FF"]
                    --[/COLOR]

                    Kommentar


                    • #11
                      Hallo,

                      so aus Interesse - wieso findest du es Unsinnig den Code z.B. den Aufbau der Datenbankverbindung in eine andere Datei auszulagern?
                      Im Grunde fand ich das immer förderlich - da es die Dateien kleiner und übersichtlicher macht und man ein bisschen nach Aufgaben trennt?

                      Kommentar


                      • #12
                        übersichtlicher macht und man ein bisschen nach Aufgaben trennt
                        dann am besten doch gleich OOP.
                        Eine if-else-Abfrage nimmt, ordentlich geschrieben eine Menge Platz weg. Platzsparend geht es mit einem ternären Operator.

                        Kommentar


                        • #13
                          wieso findest du es Unsinnig den Code z.B. den Aufbau der Datenbankverbindung in eine andere Datei auszulagern?
                          Im Grunde fand ich das immer förderlich - da es die Dateien kleiner und übersichtlicher macht und man ein bisschen nach Aufgaben trennt?
                          Tust Du aber nicht. DB-Verbindungsaufbau und Auswahl der Datenbank und Query sind keine getrennten Aufgaben. Zudem gibt es auch Anwendungen, die nicht in jedem Request eine aktive DB benötigen.
                          [COLOR="#F5F5FF"]--[/COLOR]
                          [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
                          „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                          [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
                          [COLOR="#F5F5FF"]
                          --[/COLOR]

                          Kommentar

                          Lädt...
                          X