Dois-je purifier une adresse e-mail avant de la transmettre à la fonction is_email ()?


13

J'utilise is_email()pour vérifier si une adresse e-mail fournie par l'utilisateur est valide. Par exemple:

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

À ma connaissance, rien dans cette fonction n'écrit d'informations dans la base de données. Dois-je désinfecter $emailavant de le passer à la fonction?


Kaiser, merci pour le montage. C'est en fait de la désinfection pour moi, mais je suis sûr que la plupart des lecteurs ici utiliseront un z :)
henrywright

Réponses:


5

En regardant les is_email()fonctionnalités de trac, il semble que vous n'ayez pas besoin de sanatizie car il s'agit simplement de tests de chaînes. J'irais même jusqu'à dire que si cette fonction retourne true, vous n'auriez pas besoin de la nettoyer avant de l'envoyer dans la base de données.


Mes pensées exactement sur les tests de chaînes. Je pense que je vais encore désinfecter avant d'envoyer à la base de données, vous avez probablement raison que ce n'est pas nécessaire, mais je suis une épave nerveuse quand il s'agit de ces choses :)
henrywright

Certes, mieux vaut prévenir que guérir et les frais généraux de désinfection seraient totalement imperceptibles.
Howdy_McGee

18

Cœur WordPress et PHP

La is_email()fonction Source est une implémentation WordPress typique et ne fonctionne pas complètement avec ce que permet le RFC 6531 . Une des raisons pourrait être que la FILTER_VALIDATE_EMAILconstante PHP par défaut filter_var()n'est pas beaucoup plus efficace pour valider quelque chose selon les directives de l' IETF® (Internet Engineering Task Force) .

Normes

Le fait est que le RFC 6531 autorise "les caractères Unicode au-delà de la plage ASCII" . À savoir ce sont (pour la partie locale - avant le @):

  • Lettres anglaises majuscules et minuscules (a – z, A – Z) (ASCII: 65–90, 97–122)
  • Chiffres 0vers 9(ASCII: 48-57)
  • Ces caractères spéciaux: ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • Caractère .(point, point, point final) (ASCII: 46) à condition qu'il ne soit pas le premier ou le dernier caractère, et à condition également qu'il n'apparaisse pas consécutivement (par exemple John..Doe@example.comn'est pas autorisé).
  • Les caractères spéciaux sont autorisés avec des restrictions. Elles sont:
    • Espace et "(),:;<>@[\](ASCII: 32, 34, 40, 41, 44, 58, 59, 60, 62, 64, 91–93)
    • Les restrictions pour les caractères spéciaux sont qu'ils ne doivent être utilisés que lorsqu'ils sont contenus entre guillemets, et que 2 d'entre eux (la barre oblique inversée \ et le guillemet "(ASCII: 92, 34)) doivent également être précédés d'une barre oblique inverse \(par exemple "\\"et "\"") .
  • Les commentaires sont autorisés avec des parenthèses à chaque extrémité de la partie locale; par exemple, john.smith(comment)@example.comet (comment)john.smith@example.comsont tous deux équivalents "john.smith@example.com", mais john.(comment)smith@example.comne seraient pas valides.
  • Les caractères internationaux ci U+007F- dessus , codés en UTF-8, sont autorisés par la RFC 6531, bien que les systèmes de messagerie puissent restreindre les caractères à utiliser lors de l'attribution de parties locales.

et pour la partie globale / domaine:

La partie nom de domaine d'une adresse e-mail doit être conforme à des directives strictes: elle doit correspondre aux exigences d'un nom d'hôte, composé de lettres, chiffres, tirets et points. De plus, la partie de domaine peut être un littéral d'adresse IP, entouré d'accolades carrées, comme jsmith@[192.168.2.1]ou jsmith@[IPv6:2001:db8::1][…]

Source: Wikipedia

Qu'est-ce qui est valable?

Cela peut conduire à des adresses e-mail étranges mais valides comme les suivantes:

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

Source: php.net / author gt@kani.hu - exemple corrigé par l'auteur de ce post

Limites

Il existe également des limites de longueur locales et de domaine:

Le format des adresses e-mail est celui local-part@domainoù la partie locale peut comporter jusqu'à 64 caractères et le nom de domaine peut avoir un maximum de 253 caractères - mais la longueur maximale de 256 caractères d'un chemin direct ou inverse restreint l'adresse e-mail entière à ne doit pas dépasser 254 caractères . [2] Les définitions formelles se trouvent dans la RFC 5322 (sections 3.2.3 et 3.4.1) et la RFC 5321 - avec une forme plus lisible donnée dans la RFC 3696 [3] et les errata associés .

Source: Wikipedia

Restrictions WordPress

Et c'est ce que WordPress vérifie:

  • Testez la longueur minimale de l'e-mail peut être: strlen( $email ) < 3
  • Testez un caractère @ après la première position: strpos( $email, '@', 1 ) === false
  • Testez les caractères non valides: !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local )
  • Testez les séquences de périodes: preg_match( '/\.{2,}/', $domain )
  • Test des périodes de début et de fin et des espaces: trim( $domain, " \t\n\r\0\x0B." ) !== $domain
  • Supposons que le domaine aura au moins deux sous-marins: $subs = explode( '.', $domain );puis
    • 2 > count( $subs )
    • trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
    • !preg_match('/^[a-z0-9-]+$/i', $sub )

Source: WP Core v4.0

Filtres et validation personnalisée

Tous les cas mentionnés ci-dessus déclencheront un is_email()retour faux. Le résultat est filtrable (un rappel peut être attaché) et le filtre aura trois arguments, où le dernier argument est la raison. Exemple:

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

ce qui signifie que vous pouvez remplacer les résultats renvoyés par des vérifications spécifiques.

Cela vous permet d'ajouter des vérifications spéciales, par exemple pour autoriser les domaines Umlaut, les parties de domaine TLD uniquement, etc.

Conclusion

WordPress est sûr dans la plupart des cas, mais plus restrictif car les serveurs de messagerie doivent être conformes à RFC. Gardez à l'esprit que tous les serveurs de messagerie ne seront pas alignés sur les directives RF 6531.

Éditer

Sidefact drôle: Il y a deux fonctions liées à l'intérieur ~/wp-includes/formatting: is_email()et sanitize_email(). Ils ont pratiquement la même fonction. Je n'ai aucune idée pourquoi quelqu'un a décidé que ce serait une bonne idée de copier le contenu de la fonction de l'un à l'autre au lieu d'ajouter simplement l'un comme rappel aux filtres que l'autre fournit. Comme depuis la v0.71 et depuis la v1.5 sont les mêmes, j'utiliserais personnellement la dernière que vous obtenez une chaîne nettoyée. Notez que même indique qu'il n'est pas compatible RFC.is_email() sanitize_email() is_email()


Donc, vous dites qu'en théorie, il y aura des adresses e-mail qui sont complètement valides selon la RFC 6531, mais celles-ci seront jugées invalides par WordPress?
henrywright

Certains oui. Par exemple, les domaines TLD uniquement, les domaines de trémas, etc., comme vous pouvez le lire dans le dernier paragraphe avant la conclusion de la réponse. Veuillez relire la réponse. Je sais que c'est beaucoup de choses à envelopper, mais ça vaut le coup.
kaiser

1
En fait, je l'ai déjà lu deux fois car c'est quelque chose qui mérite d'être compris! Merci pour cette réponse détaillée :)
henrywright

2

Désinfectez toutes les choses!

L'une des règles cardinales de sécurité est de ne jamais faire confiance à l'entrée de l'utilisateur. En général, je ne me soucie pas de l'implémentation de is_email () ou de toute autre fonction spécifique, ou si cette fonction fait quelque chose de dangereux avec ce que je lui donne. Peut-être que la mise en œuvre changera un jour. Qui sait. Je dois supposer que cela peut être compromis. L'hypothèse devrait toujours être que l'entrée utilisateur est activement hostile, doublement pour tout ce qui est éventuellement destiné à une base de données, et pour nettoyer chaque bit d'entrée utilisateur avant de le transmettre à une fonction. C'est juste une bonne hygiène de sécurité générale.


Je pense que vous avez mis le doigt sur la tête lorsque vous avez dit que vous ne savez jamais si la mise en œuvre changera. Il est peut-être OK de ne pas désinfecter maintenant, mais qui sait si cela changera à une date ultérieure?
henrywright
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.