Wie kann ich Benutzereingaben mit PHP bereinigen?

Lesezeit: 6 Minuten

Wie kann ich Benutzereingaben mit PHP bereinigen
Brent

Gibt es irgendwo eine Catchall-Funktion, die gut funktioniert, um Benutzereingaben für SQL-Injection und XSS-Angriffe zu bereinigen und gleichzeitig bestimmte Arten von HTML-Tags zulässt?

  • Verwenden Sie heutzutage PDO oder MySQLi, um eine SQL-Injektion zu vermeiden.

    – Francisco Presencia

    8. April 2013 um 16:00 Uhr


  • Die Verwendung von PDO oder MySQLi reicht nicht aus. Wenn Sie Ihre SQL-Anweisungen mit nicht vertrauenswürdigen Daten erstellen, wie z select * from users where name='$name', dann spielt es keine Rolle, ob Sie PDO oder MySQLi oder MySQL verwenden. Sie sind immer noch in Gefahr. Sie müssen parametrisierte Abfragen verwenden oder, falls erforderlich, Escape-Mechanismen für Ihre Daten verwenden, aber das ist viel weniger vorzuziehen.

    – Andy Lester

    20. Dezember 2013 um 17:01 Uhr

  • @AndyLester Implizieren Sie, dass jemand PDO ohne vorbereitete Anweisungen verwendet? 🙂

    Benutzer1537415

    30. März 2014 um 14:20 Uhr

  • Ich sage, dass “Verwenden Sie PDO oder MySQLi” nicht ausreichend Informationen sind, um Anfängern zu erklären, wie sie sicher verwendet werden können. Sie und ich wissen, dass vorbereitete Aussagen wichtig sind, aber ich gehe nicht davon aus, dass jeder, der diese Frage liest, dies wissen wird. Deshalb habe ich die expliziten Anweisungen hinzugefügt.

    – Andy Lester

    30. März 2014 um 22:10 Uhr

  • Andys Kommentar ist völlig gültig. Ich habe kürzlich meine MySQL-Website auf PDO umgestellt und dachte, dass ich jetzt irgendwie sicher vor Injektionsangriffen wäre. Erst während des Prozesses wurde mir klar, dass einige meiner SQL-Anweisungen immer noch mit Benutzereingaben erstellt wurden. Ich habe das dann mit vorbereiteten Anweisungen behoben. Für einen absoluten Neuling ist es nicht ganz klar, dass es einen Unterschied gibt, da viele Experten den Kommentar zur Verwendung von PDO verwerfen, aber nicht die Notwendigkeit vorbereiteter Anweisungen angeben. Die Annahme ist, dass dies offensichtlich ist. Aber nicht für einen Neuling.

    – Geisterfahrer

    25. Mai 2014 um 8:15 Uhr


Wie kann ich Benutzereingaben mit PHP bereinigen
troelskn

Es ist ein weit verbreiteter Irrglaube, dass Benutzereingaben gefiltert werden können. PHP hat sogar ein (jetzt veraltetes) “Feature”, genannt Zauberzitate, die auf dieser Idee aufbaut. Das ist Unsinn. Vergessen Sie das Filtern (oder Reinigen oder wie auch immer die Leute es nennen).

Was Sie tun sollten, um Probleme zu vermeiden, ist ganz einfach: Wenn Sie ein Datenelement in einen fremden Code einbetten, müssen Sie es gemäß den Formatierungsregeln dieses Codes behandeln. Aber Sie müssen verstehen, dass solche Regeln zu kompliziert sein könnten, um zu versuchen, sie alle manuell zu befolgen. Beispielsweise sind in SQL die Regeln für Zeichenfolgen, Zahlen und Bezeichner alle unterschiedlich. Zu Ihrer Bequemlichkeit gibt es in den meisten Fällen ein spezielles Tool für eine solche Einbettung. Wenn Sie beispielsweise eine PHP-Variable in der SQL-Abfrage verwenden müssen, müssen Sie eine vorbereitete Anweisung verwenden, die sich um die gesamte richtige Formatierung/Behandlung kümmert.

Ein weiteres Beispiel ist HTML: Wenn Sie Zeichenfolgen in HTML-Markup einbetten, müssen Sie diese mit maskieren htmlspecialchars. Das bedeutet, dass jeder einzelne echo oder print Aussage verwenden sollte htmlspecialchars.

Ein drittes Beispiel könnten Shell-Befehle sein: Wenn Sie Zeichenfolgen (z. B. Argumente) in externe Befehle einbetten und sie mit aufrufen execdann müssen Sie verwenden escapeshellcmd und escapeshellarg.

Ein sehr überzeugendes Beispiel ist auch JSON. Die Regeln sind so zahlreich und kompliziert, dass Sie sie niemals alle manuell befolgen könnten. Deshalb sollten Sie niemals einen JSON-String manuell erstellen, sondern immer eine dedizierte Funktion verwenden, json_encode() Dadurch wird jedes Datenbit korrekt formatiert.

Und so weiter und so fort …

Die nur Der Fall, in dem Sie Daten aktiv filtern müssen, ist, wenn Sie vorformatierte Eingaben akzeptieren. Wenn Sie beispielsweise zulassen, dass Ihre Benutzer HTML-Markup posten, das Sie auf der Website anzeigen möchten. Sie sollten dies jedoch um jeden Preis vermeiden, denn egal wie gut Sie es filtern, es wird immer eine potenzielle Sicherheitslücke sein.

  • “Das bedeutet, dass jede einzelne echo- oder print-Anweisung htmlspecialchars verwenden sollte” – Sie meinen natürlich “jede … Anweisung, die Benutzereingaben ausgibt”; htmlspecialchars()-ifying “echo ‘Hallo Welt!’;” wäre verrückt 😉

    – Bobby Jack

    20. Oktober 2008 um 13:32 Uhr

  • Es gibt einen Fall, in dem ich denke, dass das Filtern die richtige Lösung ist: UTF-8. Sie möchten keine ungültigen UTF-8-Sequenzen in Ihrer gesamten Anwendung (je nach Codepfad erhalten Sie möglicherweise eine andere Fehlerbehebung), und UTF-8 kann einfach gefiltert (oder abgelehnt) werden.

    – Körnel

    9. September 2009 um 21:33 Uhr

  • @jbyrd – nein, LIKE verwendet eine spezialisierte Regexp-Sprache. Sie müssen Ihren Eingabe-String zweimal maskieren – einmal für die Regexp und einmal für die mysql-String-Codierung. Es ist Code im Code im Code.

    – troelskn

    29. Oktober 2011 um 20:02 Uhr


  • In diesem Moment mysql_real_escape_string ist veraltet. Es wird heutzutage als gute Praxis angesehen, es zu verwenden vorbereitete Erklärungen SQL-Injection zu verhindern. Wechseln Sie also entweder zu MySQLi oder PDO.

    – Marcel Korpel

    5. Juni 2013 um 12:46 Uhr

  • Denn Sie begrenzen die Angriffsfläche. Wenn Sie früh (bei der Eingabe) bereinigen, müssen Sie sicher sein, dass es keine anderen Löcher in der Anwendung gibt, durch die schlechte Daten eindringen könnten. Wenn Sie es spät tun, muss Ihre Ausgabefunktion nicht darauf “vertrauen”, dass ihr sichere Daten gegeben werden – sie geht einfach davon aus, dass alles unsicher ist.

    – troelskn

    15. Juli 2014 um 17:33 Uhr

1647092654 701 Wie kann ich Benutzereingaben mit PHP bereinigen
Andy Lester

Versuchen Sie nicht, die SQL-Injection zu verhindern, indem Sie Eingabedaten bereinigen.

Stattdessen, Lassen Sie nicht zu, dass Daten beim Erstellen Ihres SQL-Codes verwendet werden. Verwenden Sie vorbereitete Anweisungen (dh mit Parametern in einer Vorlagenabfrage), die gebundene Variablen verwenden. Dies ist die einzige Möglichkeit, um gegen SQL-Injection geschützt zu sein.

Bitte sehen Sie sich meine Website an http://bobby-tables.com/ Weitere Informationen zum Verhindern von SQL-Injection finden Sie hier.

  • Oder besuchen Sie die amtliche Dokumentation und lernen Sie PDO und vorbereitete Anweisungen. Winzige Lernkurve, aber wenn Sie SQL ziemlich gut kennen, werden Sie keine Probleme haben, sich anzupassen.

    – ein Codierer

    13. November 2014 um 2:49 Uhr

  • Für den speziellen Fall der SQL-Injection Das ist die richtige Antwort!

    – Scott Arciszewski

    30. Mai 2015 um 2:04 Uhr

  • Beachten Sie, dass vorbereitete Anweisungen keine Sicherheit hinzufügen, parametrisierte Abfragen tun dies. Sie sind einfach sehr einfach zusammen in PHP zu verwenden.

    – Basic

    16. August 2015 um 3:01 Uhr

  • Es ist nicht der einzige garantierte Weg. Hex die Eingabe und unhex in Abfrage wird auch verhindert. Auch Verhexungsangriffe sind nicht möglich, wenn Sie rechts verhexen.

    – Ramon Bakker

    22. Februar 2016 um 15:50 Uhr

  • Was ist, wenn Sie etwas Spezielles wie E-Mail-Adressen oder Benutzernamen eingeben?

    – Abraham Brookes

    9. Januar 2017 um 8:34 Uhr


1647092654 655 Wie kann ich Benutzereingaben mit PHP bereinigen
Daniel Papasian

Nein. Sie können Daten nicht generisch filtern, ohne dass sie im Zusammenhang mit dem Zweck stehen. Manchmal möchten Sie eine SQL-Abfrage als Eingabe verwenden, und manchmal möchten Sie HTML als Eingabe verwenden.

Sie müssen die Eingaben auf einer Whitelist filtern – stellen Sie sicher, dass die Daten mit einer Spezifikation Ihrer Erwartungen übereinstimmen. Dann müssen Sie es entkommen, bevor Sie es verwenden, je nach Kontext, in dem Sie es verwenden.

Der Prozess des Daten-Escapes für SQL – um eine SQL-Einschleusung zu verhindern – unterscheidet sich stark vom Prozess des Escapes von Daten für (X)HTML, um XSS zu verhindern.

1647092655 810 Wie kann ich Benutzereingaben mit PHP bereinigen
SchizoDuckie

PHP hat das neue nice filter_input Funktionen jetzt, die Sie zum Beispiel davon befreien, ‘die ultimative E-Mail-Regex’ zu finden, jetzt, wo es eine eingebaute gibt FILTER_VALIDATE_EMAIL Art


Meine eigene Filterklasse (verwendet JavaScript, um fehlerhafte Felder hervorzuheben) kann entweder durch eine Ajax-Anfrage oder einen normalen Formularpost initiiert werden. (siehe Beispiel unten)

/**
 *  Pork.FormValidator
 *  Validates arrays or properties by setting up simple arrays. 
 *  Note that some of the regexes are for dutch input!
 *  Example:
 * 
 *  $validations = array('name' => 'anything','email' => 'email','alias' => 'anything','pwd'=>'anything','gsm' => 'phone','birthdate' => 'date');
 *  $required = array('name', 'email', 'alias', 'pwd');
 *  $sanitize = array('alias');
 *
 *  $validator = new FormValidator($validations, $required, $sanitize);
 *                  
 *  if($validator->validate($_POST))
 *  {
 *      $_POST = $validator->sanitize($_POST);
 *      // now do your saving, $_POST has been sanitized.
 *      die($validator->getScript()."<script type="text/javascript">alert('saved changes');</script>");
 *  }
 *  else
 *  {
 *      die($validator->getScript());
 *  }   
 *  
 * To validate just one element:
 * $validated = new FormValidator()->validate('blah@bla.', 'email');
 * 
 * To sanitize just one element:
 * $sanitized = new FormValidator()->sanitize('<b>blah</b>', 'string');
 * 
 * @package pork
 * @author SchizoDuckie
 * @copyright SchizoDuckie 2008
 * @version 1.0
 * @access public
 */
class FormValidator
{
    public static $regexes = Array(
            'date' => "^[0-9]{1,2}[-/][0-9]{1,2}[-/][0-9]{4}\$",
            'amount' => "^[-]?[0-9]+\$",
            'number' => "^[-]?[0-9,]+\$",
            'alfanum' => "^[0-9a-zA-Z ,.-_\\s\?\!]+\$",
            'not_empty' => "[a-z0-9A-Z]+",
            'words' => "^[A-Za-z]+[A-Za-z \\s]*\$",
            'phone' => "^[0-9]{10,11}\$",
            'zipcode' => "^[1-9][0-9]{3}[a-zA-Z]{2}\$",
            'plate' => "^([0-9a-zA-Z]{2}[-]){2}[0-9a-zA-Z]{2}\$",
            'price' => "^[0-9.,]*(([.,][-])|([.,][0-9]{2}))?\$",
            '2digitopt' => "^\d+(\,\d{2})?\$",
            '2digitforce' => "^\d+\,\d\d\$",
            'anything' => "^[\d\D]{1,}\$"
    );
    private $validations, $sanatations, $mandatories, $errors, $corrects, $fields;
    

    public function __construct($validations=array(), $mandatories = array(), $sanatations = array())
    {
        $this->validations = $validations;
        $this->sanitations = $sanitations;
        $this->mandatories = $mandatories;
        $this->errors = array();
        $this->corrects = array();
    }

    /**
     * Validates an array of items (if needed) and returns true or false
     *
     */
    public function validate($items)
    {
        $this->fields = $items;
        $havefailures = false;
        foreach($items as $key=>$val)
        {
            if((strlen($val) == 0 || array_search($key, $this->validations) === false) && array_search($key, $this->mandatories) === false) 
            {
                $this->corrects[] = $key;
                continue;
            }
            $result = self::validateItem($val, $this->validations[$key]);
            if($result === false) {
                $havefailures = true;
                $this->addError($key, $this->validations[$key]);
            }
            else
            {
                $this->corrects[] = $key;
            }
        }
    
        return(!$havefailures);
    }

    /**
     *
     *  Adds unvalidated class to thos elements that are not validated. Removes them from classes that are.
     */
    public function getScript() {
        if(!empty($this->errors))
        {
            $errors = array();
            foreach($this->errors as $key=>$val) { $errors[] = "'INPUT[name={$key}]'"; }

            $output="$$(".implode(',', $errors).').addClass("unvalidated");'; 
            $output .= "new FormValidator().showMessage();";
        }
        if(!empty($this->corrects))
        {
            $corrects = array();
            foreach($this->corrects as $key) { $corrects[] = "'INPUT[name={$key}]'"; }
            $output .= '$$('.implode(',', $corrects).').removeClass("unvalidated");';   
        }
        $output = "<script type="text/javascript">{$output} </script>";
        return($output);
    }


    /**
     *
     * Sanitizes an array of items according to the $this->sanitations
     * sanitations will be standard of type string, but can also be specified.
     * For ease of use, this syntax is accepted:
     * $sanitations = array('fieldname', 'otherfieldname'=>'float');
     */
    public function sanitize($items)
    {
        foreach($items as $key=>$val)
        {
            if(array_search($key, $this->sanitations) === false && !array_key_exists($key, $this->sanitations)) continue;
            $items[$key] = self::sanitizeItem($val, $this->validations[$key]);
        }
        return($items);
    }


    /**
     *
     * Adds an error to the errors array.
     */ 
    private function addError($field, $type="string")
    {
        $this->errors[$field] = $type;
    }

    /**
     *
     * Sanitize a single var according to $type.
     * Allows for static calling to allow simple sanitization
     */
    public static function sanitizeItem($var, $type)
    {
        $flags = NULL;
        switch($type)
        {
            case 'url':
                $filter = FILTER_SANITIZE_URL;
            break;
            case 'int':
                $filter = FILTER_SANITIZE_NUMBER_INT;
            break;
            case 'float':
                $filter = FILTER_SANITIZE_NUMBER_FLOAT;
                $flags = FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND;
            break;
            case 'email':
                $var = substr($var, 0, 254);
                $filter = FILTER_SANITIZE_EMAIL;
            break;
            case 'string':
            default:
                $filter = FILTER_SANITIZE_STRING;
                $flags = FILTER_FLAG_NO_ENCODE_QUOTES;
            break;
             
        }
        $output = filter_var($var, $filter, $flags);        
        return($output);
    }
    
    /** 
     *
     * Validates a single var according to $type.
     * Allows for static calling to allow simple validation.
     *
     */
    public static function validateItem($var, $type)
    {
        if(array_key_exists($type, self::$regexes))
        {
            $returnval =  filter_var($var, FILTER_VALIDATE_REGEXP, array("options"=> array("regexp"=>'!'.self::$regexes[$type].'!i'))) !== false;
            return($returnval);
        }
        $filter = false;
        switch($type)
        {
            case 'email':
                $var = substr($var, 0, 254);
                $filter = FILTER_VALIDATE_EMAIL;    
            break;
            case 'int':
                $filter = FILTER_VALIDATE_INT;
            break;
            case 'boolean':
                $filter = FILTER_VALIDATE_BOOLEAN;
            break;
            case 'ip':
                $filter = FILTER_VALIDATE_IP;
            break;
            case 'url':
                $filter = FILTER_VALIDATE_URL;
            break;
        }
        return ($filter === false) ? false : filter_var($var, $filter) !== false ? true : false;
    }       
    


}

Denken Sie natürlich daran, dass Sie Ihre SQL-Abfrage auch entkommen müssen, je nachdem, welche Art von Datenbank Sie verwenden (mysql_real_escape_string() ist beispielsweise für einen SQL-Server nutzlos). Wahrscheinlich möchten Sie dies automatisch auf Ihrer entsprechenden Anwendungsebene wie einem ORM handhaben. Außerdem, wie oben erwähnt: Verwenden Sie für die Ausgabe in HTML die anderen dedizierten PHP-Funktionen wie htmlspecialchars 😉

Um HTML-Eingaben mit ähnlich entfernten Klassen und/oder Tags wirklich zuzulassen, hängen Sie von einem der dedizierten xss-Validierungspakete ab. SCHREIBEN SIE KEINE EIGENEN REGEXES, UM HTML ZU PARSEN!

1647092655 956 Wie kann ich Benutzereingaben mit PHP bereinigen
Peter Bailey

Nein, da ist kein.

Zunächst einmal ist die SQL-Einschleusung ein Eingabefilterungsproblem, und XSS ist ein Ausgabe-Escape-Problem – Sie würden diese beiden Operationen also nicht einmal gleichzeitig im Code-Lebenszyklus ausführen.

Grundlegende Faustregeln

  • Binden Sie für SQL-Abfragen Parameter (wie bei PDO) oder verwenden Sie eine treibernative Escape-Funktion für Abfragevariablen (wie z mysql_real_escape_string())
  • Verwenden strip_tags() um unerwünschtes HTML herauszufiltern
  • Escape alle anderen Ausgaben mit htmlspecialchars() und achten Sie hier auf den 2. und 3. Parameter.

  • Sie verwenden also nur strip_tags() oder htmlspecialchars(), wenn Sie wissen, dass die Eingabe HTML enthält, das Sie entfernen bzw. entkommen möchten – Sie verwenden es nicht für Sicherheitszwecke, oder? Außerdem, wenn Sie das Binden machen, was macht es für Dinge wie Bobby Tables? “Robert’); DROP TABLE Students;–” Entgeht es nur den Anführungszeichen?

    – Robert Mark Bram

    29. Oktober 2012 um 1:16 Uhr

  • Wenn Sie Benutzerdaten haben, die in eine Datenbank gehen und später auf Webseiten angezeigt werden, werden diese nicht normalerweise viel mehr gelesen als geschrieben? Für mich ist es sinnvoller, es einmal (als Eingabe) zu filtern, bevor Sie es speichern, anstatt es jedes Mal filtern zu müssen, wenn Sie es anzeigen. Vermisse ich etwas oder haben ein paar Leute in dieser und der akzeptierten Antwort für unnötigen Leistungsaufwand gestimmt?

    – jbo5112

    30. April 2014 um 14:07 Uhr

  • Beste Antwort für mich. Es ist kurz und spricht die Frage gut an, wenn Sie mich fragen. Ist es möglich, PHP irgendwie über $_POST oder $_GET mit einer Injektion anzugreifen, oder ist dies unmöglich?

    – Jo Smo

    14. Juli 2014 um 12:26 Uhr

  • oh ja, die Arrays $post und $get akzeptieren alle Zeichen, aber einige dieser Zeichen können gegen Sie verwendet werden, wenn das Zeichen auf der geposteten PHP-Seite aufgezählt werden darf. Wenn Sie also Kapselungszeichen (wie “, ‘ und ` ) nicht maskieren, könnte dies einen Angriffsvektor eröffnen. Das Zeichen ` wird oft übersehen und kann verwendet werden, um Befehlszeilenausführungs-Hacks zu bilden. Hygiene verhindert das Hacken von Benutzereingaben, hilft Ihnen aber nicht bei Firewall-Hacks für Webanwendungen.

    – drtechno

    18. September 2019 um 16:43 Uhr

Wie kann ich Benutzereingaben mit PHP bereinigen
jasonbar

Um das XSS-Problem zu lösen, werfen Sie einen Blick auf HTML-Reiniger. Es ist ziemlich konfigurierbar und hat eine anständige Erfolgsbilanz.

Stellen Sie bei den SQL-Injection-Angriffen sicher, dass Sie die Benutzereingabe überprüfen und sie dann durch mysql_real_escape_string() ausführen. Die Funktion wird jedoch nicht alle Injektionsangriffe abwehren, daher ist es wichtig, dass Sie die Daten überprüfen, bevor Sie sie in Ihre Abfragezeichenfolge einspeisen.

Eine bessere Lösung ist die Verwendung vorbereiteter Anweisungen. Die PDO-Bibliothek und mysqli-Erweiterung unterstützen diese.

  • Sie verwenden also nur strip_tags() oder htmlspecialchars(), wenn Sie wissen, dass die Eingabe HTML enthält, das Sie entfernen bzw. entkommen möchten – Sie verwenden es nicht für Sicherheitszwecke, oder? Außerdem, wenn Sie das Binden machen, was macht es für Dinge wie Bobby Tables? “Robert’); DROP TABLE Students;–” Entgeht es nur den Anführungszeichen?

    – Robert Mark Bram

    29. Oktober 2012 um 1:16 Uhr

  • Wenn Sie Benutzerdaten haben, die in eine Datenbank gehen und später auf Webseiten angezeigt werden, werden diese nicht normalerweise viel mehr gelesen als geschrieben? Für mich ist es sinnvoller, es einmal (als Eingabe) zu filtern, bevor Sie es speichern, anstatt es jedes Mal filtern zu müssen, wenn Sie es anzeigen. Vermisse ich etwas oder haben ein paar Leute in dieser und der akzeptierten Antwort für unnötigen Leistungsaufwand gestimmt?

    – jbo5112

    30. April 2014 um 14:07 Uhr

  • Beste Antwort für mich. Es ist kurz und spricht die Frage gut an, wenn Sie mich fragen. Ist es möglich, PHP irgendwie über $_POST oder $_GET mit einer Injektion anzugreifen, oder ist dies unmöglich?

    – Jo Smo

    14. Juli 2014 um 12:26 Uhr

  • oh ja, die Arrays $post und $get akzeptieren alle Zeichen, aber einige dieser Zeichen können gegen Sie verwendet werden, wenn das Zeichen auf der geposteten PHP-Seite aufgezählt werden darf. Wenn Sie also Kapselungszeichen (wie “, ‘ und ` ) nicht maskieren, könnte dies einen Angriffsvektor eröffnen. Das Zeichen ` wird oft übersehen und kann verwendet werden, um Befehlszeilenausführungs-Hacks zu bilden. Hygiene verhindert das Hacken von Benutzereingaben, hilft Ihnen aber nicht bei Firewall-Hacks für Webanwendungen.

    – drtechno

    18. September 2019 um 16:43 Uhr

1647092656 297 Wie kann ich Benutzereingaben mit PHP bereinigen
nik7

PHP 5.2 führte das ein filter_var Funktion.

Es unterstützt sehr viel SANITIZE, VALIDATE Filter.

993760cookie-checkWie kann ich Benutzereingaben mit PHP bereinigen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy