web-dev-qa-db-fra.com

L'entrée utilisateur doit-elle être validée pour sa longueur en PHP (côté serveur) par mesure de sécurité?

Il est important de noter que cette entrée utilisateur fera l'objet d'une validation et d'un nettoyage à l'aide d'expressions rationnelles (côté serveur en PHP), puis sera insérée dans une base de données. Plus tard, il serait montré à d'autres utilisateurs sur le même site Web (par exemple: sur un forum).

Je fais référence à la fois à un cas où je sais à l'avance quelle longueur je dois attendre de l'utilisateur et à un cas dans lequel je ne le fais pas, mais je peux supposer qu'il ne dépasse pas 100 caractères.

J'essaie de déterminer s'il existe des avantages de sécurité pour la vérification de la longueur d'entrée utilisateur.

Je sais que cela diffère d'une langue à l'autre, j'utilise PHP. Les informations concernant tout autre langage comme Java, .NET, Python etc. seraient bien.

14
rami300

En règle générale, vous devez restreindre la saisie utilisateur autant que possible, mais pas plus. Un champ conçu pour contenir le nom des villes n'a pas besoin d'une longueur illimitée. Mais si vous limitez la longueur à 25 en pensant qu'aucun nom ne peut être plus long, vous bouleverserez le gallois .

Des longueurs d'entrée plus courtes signifient moins d'espace pour les charges utiles si vous êtes inquiet, par exemple SQLi ou XSS. Il pourrait donc être considéré comme une défense en profondeur contre ces attaques. Mais s'il s'agit de votre première ligne de défense, vous avez de gros ennuis ...

Enfin, vous avez raison de dire que toutes les restrictions que vous décidez d'utiliser doivent être appliquées côté serveur, et pas uniquement sur le client.

26
Anders

Cela dépend de ce contre quoi vous voulez vous protéger.

Vous avez mentionné que vous avez une expression régulière utilisée pour valider l'entrée. Cela peut être bien, mais dépend en fin de compte de la façon dont votre expression régulière est formée. Si votre RegEx ressemble à ceci, vous irez probablement bien:

{\"name\":\"(.+?)\",\ ?\"age\":(\d+?)}

Si votre RegEx ressemble à ceci d'autre part ...

({.+})

Il ne suffit pas de dire que vous utilisez des expressions régulières pour affirmer à quel point celles-ci peuvent être sécurisées contre diverses attaques telles que l'injection SQL ou les scripts intersites.

Ce que la validation de longueur fait protège contre certaines formes d'attaques par déni de service. Par exemple, une requête HTTP POST peut avoir plusieurs mégaoctets. Si vous copiez simplement ce que vous recevez dans une base de données, un attaquant peut rapidement remplir votre base de données avec des ordures et affecter votre disponibilité.

9
MechMK1

Toute validation du côté client de l'application Web peut être facilement contournée et ne doit pas être invoquée du point de vue de la sécurité.

Les outils de développement du navigateur incluent de très bons débogueurs Html/JavaScript qui permettent au code côté client d'être exécuté étape par étape, d'avoir des attributs et des scripts modifiés pour contourner les vérifications et validations de sécurité.

Même les pirates informatiques médiocres savent comment exploiter cela. Du point de vue de la sécurité, il est nécessaire de revérifier les validations côté serveur.

Dans mes applications, je fais la plupart du front-end côté serveur. Je soumets la plupart des formulaires en utilisant un IFRAME ou XmlHttpClient qui renvoie les messages de validation ou l'URL de la page de confirmation. C'est beaucoup plus facile à développer et très réactif pour la plupart des formulaires. Même dans ce cas, je code beaucoup de code JavaScript côté client, mais uniquement lorsque cela a plus d'impact sur les performances ou l'expérience utilisateur. C'est une stratégie à 80/20.

1
Lucas

Par mesure de sécurité? Non.

Les attaques via l'entrée utilisateur se produisent lorsqu'un utilisateur est capable de saisir des commandes, généralement sous la forme de requêtes de base de données, dans des variables que vous n'avez pas correctement échappées. Bien qu'une entrée tronquée puisse empêcher par inadvertance une attaque, elle ne résout pas vraiment le problème.

En termes de sécurité, vous devez valider toutes les entrées utilisateur et vérifier que l'entrée n'est utilisée que de manière protégée, dans certains cas:

  1. Si la valeur doit être sortie en HTML, vous voudrez vous assurer qu'elle ne contient pas de balises HTML (strip_tags) ou uniquement celles que vous autorisez (utilisez une bibliothèque ou DOMDocument pour cela).
  2. Si la valeur doit être utilisée dans un calcul, assurez-vous qu'il s'agit d'un nombre valide. Le moyen le plus simple consiste à caster en tant que (int)$foo ou (float)$foo mais vos besoins peuvent varier.
  3. Si la valeur doit être stockée dans une base de données, assurez-vous de ne pas créer votre requête de manière non sécurisée. La meilleure façon de sécuriser les requêtes consiste à utiliser des instructions préparées, PDO est bon pour cela. Sinon, vous devez vous assurer d'échapper à l'entrée utilisateur avant de créer votre requête.

Si vous demandez à un utilisateur de saisir uniquement des lettres et des chiffres pour une valeur, vous ne devez accepter que des lettres et des chiffres sur votre serveur. Vous pouvez ajouter la même condition côté client, pour éviter des surprises à vos utilisateurs (en leur donnant une erreur avant d'envoyer un formulaire), mais le serveur est l'endroit où vous vous protégez réellement, car la validation côté client est informative, elle n'est pas protectrice ( il est facilement contourné).

Sur cette base, si vous ne pouvez stocker qu'un nombre limité de caractères dans un champ, vous pouvez également le signaler à l'utilisateur si un champ est trop long.

Disons que vous voulez une adresse e-mail ne dépassant pas 128 caractères, vous pouvez gérer cela à tous les niveaux comme ceci:

Base de données (modèle)

CREATE TABLE Emails `email` VARCHAR(128) NOT NULL

PHP (contrôleur)

$email = $_POST['email'];
if ((strlen($email) > 128) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
    // Produce error that input was invalid
    die('ERROR: Invalid e-mail');
}

// Input is valid, store in database (e.g- with PDO)
$stmt = $pdo->prepare('INSERT INTO Emails (email) VALUES (?)');
$stmt->execute([$email]);

HTML (Afficher)

<input name="email" type="email" maxlength="128" placeholder="E-mail" />

Cela vous donne un bon mélange d'efficacité de stockage, d'exactitude, de sécurité et de rétroaction à l'utilisateur; s'ils ont un navigateur qui prend en charge HTML5, ils obtiendront des erreurs précoces s'ils tentent d'envoyer une valeur non valide, mais nous vérifions quand même la sécurité du serveur (navigateur non compatible HTML5 ou utilisateur malveillant).

1
Haravikk

Vous devez toujours vous assurer que vous comprenez quelle entrée utilisateur vous attendez et assurez-vous que l'entrée réelle est aussi proche de ce que vous attendez que possible.

Des données plus longues que prévu peuvent entraîner de nombreux types de problèmes de sécurité:

  • Attaques DOS/surutilisation des ressources: 1 Go gaspillé pour un nom factice dans une base de données, ou puissance CPU gaspillée pour valider regex un nom de 1 Go qui ne devrait pas dépasser 100 caractères
  • buffer/champ de données/débordements d'entiers
  • exploits de logique métier: quelqu'un a implémenté une logique métier qui suppose une certaine entrée d'une certaine longueur et des données de plus grandes longueurs la cassent de manière exploitable

Une vérification d'expression régulière est bonne et potentiellement plus stricte que la vérification de la longueur en elle-même. S'il inclut le contrôle de longueur implicitement, cela couvre déjà beaucoup de problèmes potentiels. Certains restent cependant: votre regex pourrait toujours être attaqué lui-même, par exemple en utilisant plus de CPU que nécessaire pour valider l'entrée, ou en ciblant les bogues dans le moteur d'expression régulière. Les regex sont également compliqués, il y a toujours une chance que vous ou quelqu'un qui le modifiez plus tard, casse l'expression et soudain, il ne vérifie plus correctement la longueur. Un contrôle de longueur explicite et léger peut vous protéger contre cela. Que cela en vaille la peine, cela dépend toujours de la sécurité que vous souhaitez et de l'effort nécessaire pour ajouter le chèque (à maintenir), etc.

Veiller à ce que l'entrée utilisateur soit aussi proche de ce que vous attendez d'elle a toujours des impacts sur la sécurité, mais augmente également les efforts de mise en œuvre/maintenance. Les humains font des erreurs et ne prennent pas en compte tous les cas Edge, donc moins de cas Edge signifie plus de sécurité pratique. La nécessité de telles vérifications dans votre scénario concret dépend toujours des autres mesures de sécurité que vous avez mises en place, du scénario d'attaque attendu, de ce que vous surveillez, de la gravité d'une effraction, etc. pp.

1
Frank Hopkins