Soll ich eine E-Mail-Adresse bereinigen, bevor ich sie an die Funktion is_email () weitergebe?

13

Ich is_email()überprüfe mit, ob eine vom Benutzer angegebene E-Mail-Adresse gültig ist. Beispielsweise:

$email = $_POST['email'];
if ( is_email( $email ) )
    // Do something.

Nach meinem besten Wissen schreibt nichts in dieser Funktion Informationen in die Datenbank. Sollte ich bereinigen, $emailbevor ich es an die Funktion weitergebe?

Henrywright
quelle
Kaiser, danke für die Bearbeitung. Eigentlich ist es Hygiene für mich, aber ich bin sicher, dass die meisten Leser hier ein z :) verwenden werden
henrywright

Antworten:

5

Wenn Sie sich die is_email()Funktionen von trac ansehen, müssen Sie anscheinend nicht sanieren, da es sich nur um Stringtests handelt. Ich würde sogar so weit gehen zu sagen, dass wenn diese Funktion true zurückgibt, Sie sie nicht bereinigen müssen, bevor Sie sie in die Datenbank senden.

Howdy_McGee
quelle
Meine Gedanken genau zum Saitentest. Ich denke , ich werde noch sanitize vor dem db zu senden, sind Sie wahrscheinlich richtig , dass es nicht notwendig ist, aber ich bin ein nervöses Wrack , wenn es um diese Dinge geht :)
henrywright
Sicher ist sicher, und der Aufwand für die Desinfektion wäre völlig unbemerkt.
Howdy_McGee
18

WordPress und PHP-Kern

Die is_email()Funktion Source ist eine typische WordPress-Implementierung und funktioniert nicht vollständig mit dem, was der RFC 6531 zulässt. Ein Grund könnte sein, dass die Standard-PHP- FILTER_VALIDATE_EMAILKonstante für filter_var()nicht viel besser ist, um etwas gemäß den Richtlinien der Internet Engineering Task Force (IETF®) zu validieren .

Standards

Punkt ist, dass der RFC 6531 "Unicode-Zeichen außerhalb des ASCII-Bereichs" zulässt . Das sind nämlich (für den lokalen Teil - vor dem @):

  • Englische Groß- und Kleinbuchstaben (AZ, AZ) (ASCII: 65-90, 97-122)
  • Ziffern 0bis 9(ASCII: 48–57)
  • Diese Sonderzeichen: ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • Zeichen .(Punkt, Punkt, Punkt) (ASCII: 46), sofern es sich nicht um das erste oder letzte Zeichen handelt, und sofern es nicht fortlaufend vorkommt (z. B. [email protected]nicht zulässig).
  • Sonderzeichen sind mit Einschränkungen erlaubt. Sie sind:
    • Leerzeichen und "(),:;<>@[\](ASCII: 32, 34, 40, 41, 44, 58, 59, 60, 62, 64, 91–93)
    • Die Einschränkungen für Sonderzeichen bestehen darin, dass sie nur zwischen Anführungszeichen verwendet werden dürfen und dass 2 von ihnen (der Backslash \ und das Anführungszeichen "(ASCII: 92, 34)) ebenfalls mit einem Backslash \(zB "\\"und "\"") versehen werden müssen. .
  • Kommentare sind mit runden Klammern an beiden Enden des lokalen Teils zulässig. zB john.smith(comment)@example.comund (comment)[email protected]sind beide äquivalent "[email protected]", john.(comment)[email protected]wären aber ungültig.
  • Die obigen internationalen Zeichen U+007F, die als UTF-8 codiert sind, sind nach RFC 6531 zulässig, obwohl Mailsysteme möglicherweise die Verwendung der Zeichen für die Zuweisung lokaler Teile einschränken.

und für den globalen / Domain-Teil:

Der Domainnamen-Teil einer E-Mail-Adresse muss strengen Richtlinien entsprechen: Er muss den Anforderungen für einen Hostnamen entsprechen, der aus Buchstaben, Ziffern, Bindestrichen und Punkten besteht. Darüber hinaus kann der Domänenteil ein IP-Adressliteral sein, das von eckigen Klammern wie jsmith@[192.168.2.1]oder jsmith@[IPv6:2001:db8::1][…] umgeben ist.

Quelle: Wikipedia

Was ist gültig?

Dies kann zu seltsamen, aber gültigen E-Mail-Adressen wie den folgenden führen:

  • [email protected]
  • (comment)[email protected]
  • "this is v@lid!"@example.com
  • "much.more unusual"@example.com
  • postbox@com
  • admin@mailserver1
  • "()<>[]:,;\\@\"\\\\!#$%&\'*+-/=?^_`{}| ~.a"@example.org
  • " "@example.org

Quelle: php.net / author [email protected] - Beispiel vom Autor dieses Beitrags behoben

Grenzen

Es gibt auch lokale und Domain-Längenbeschränkungen:

Im Format der E-Mail-Adressen darflocal-part@domain der lokale Teil bis zu 64 Zeichen lang sein und der Domain-Name darf maximal 253 Zeichen lang sein. Die maximale Länge eines Vorwärts- oder Rückwärtspfads von 256 Zeichen beschränkt die gesamte E-Mail-Adresse jedoch auf darf nicht länger als 254 Zeichen sein . [2] Die formalen Definitionen sind in RFC 5322 (Abschnitte 3.2.3 und 3.4.1) und RFC 5321 enthalten. Eine besser lesbare Form finden Sie im informativen RFC 3696 [3] und den zugehörigen Errata .

Quelle: Wikipedia

WordPress-Einschränkungen

Und darauf prüft WordPress:

  • Testen Sie die Mindestlänge der E-Mail: strlen( $email ) < 3
  • Test auf ein @ -Zeichen nach der ersten Position: strpos( $email, '@', 1 ) === false
  • Auf ungültige Zeichen prüfen: !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local )
  • Test für Abfolgen von Perioden: preg_match( '/\.{2,}/', $domain )
  • Test für führende und nachfolgende Perioden und Leerzeichen: trim( $domain, " \t\n\r\0\x0B." ) !== $domain
  • Angenommen, die Domain hat mindestens zwei Subs: $subs = explode( '.', $domain );und dann
    • 2 > count( $subs )
    • trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
    • !preg_match('/^[a-z0-9-]+$/i', $sub )

Quelle: WP Core v4.0

Filter & benutzerdefinierte Validierung

Alle oben genannten Fälle lösen is_email()den Rückgabewert false aus. Das Ergebnis ist filterfähig (ein Rückruf kann angehängt werden) und der Filter hat drei Argumente, wobei das letzte Argument der Grund ist. Beispiel:

return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );

Dies bedeutet, dass Sie die von bestimmten Prüfungen zurückgegebenen Ergebnisse überschreiben können.

Auf diese Weise können Sie spezielle Prüfungen hinzufügen, um beispielsweise Umlaut-Domains, nur TLD-Domain-Teile usw. zuzulassen.

Fazit

WordPress ist in den meisten Fällen sicher, aber restriktiver, da Mailserver RFC-konform sein müssen. Beachten Sie, dass nicht jeder Mailserver den RF 6531-Richtlinien entspricht.

Bearbeiten

Lustiger Nebeneffekt: Es gibt zwei verwandte Funktionen ~/wp-includes/formatting: is_email()und sanitize_email(). Sie haben praktisch die gleiche Funktion. Ich habe keine Ahnung, warum jemand entschieden hat, dass es eine gute Idee ist, den Funktionsinhalt von einem zum anderen zu kopieren, anstatt nur den einen als Rückruf zu den Filtern hinzuzufügen, die der andere bereitstellt. Da v0.71 und v1.5 gleich sind, würde ich das später verwenden, da man einen gereinigten String bekommt. Beachten Sie, dass sogar angegeben wird, dass es nicht RFC-konform ist.is_email() sanitize_email() is_email()

Kaiser
quelle
Sie sagen also, dass es theoretisch E-Mail-Adressen gibt, die gemäß RFC 6531 vollständig gültig sind, aber von WordPress als ungültig eingestuft werden?
Henrywright
Einige ja. Zum Beispiel TLD-only-Domains, Umlaut-Domains usw., wie Sie im letzten Absatz vor dem Abschluss in der Antwort nachlesen können. Bitte lesen Sie die Antwort noch einmal. Ich weiß, es ist viel, den Kopf herumzukrempeln, aber es lohnt sich.
Kaiser
1
Ich habe es tatsächlich schon zweimal gelesen, da es sich lohnt, es zu verstehen! Vielen Dank für eine so ausführliche Antwort :)
Henrywright
2

Sanitize all die Dinge!

Eine der wichtigsten Sicherheitsregeln besteht darin, den Eingaben des Benutzers niemals zu vertrauen. Im Allgemeinen interessiert mich die Implementierung von is_email () oder einer anderen spezifischen Funktion nicht, oder ob diese Funktion mit dem, was ich gebe, etwas Gefährliches anstellt. Vielleicht wird sich die Implementierung eines Tages ändern. Wer weiß. Ich muss davon ausgehen, dass es kompromittiert werden kann. Die Annahme sollte immer sein, dass Benutzereingaben aktiv feindselig sind, doppelt für alles, was irgendwann für eine Datenbank bestimmt ist, und dass jede Benutzereingabe bereinigt werden muss, bevor sie an eine Funktion übergeben wird. Dies ist nur eine gute allgemeine Sicherheitshygiene.

JesseM
quelle
Ich denke, Sie haben den Nagel auf den Kopf getroffen, als Sie sagten, Sie wissen nie, ob sich die Implementierung ändern wird. Es mag in Ordnung sein, jetzt nicht zu sanieren, aber wer weiß, ob sich das zu einem späteren Zeitpunkt ändern wird?
Henrywright