web-dev-qa-db-fra.com

La conversion indésirable d'un numéro scientifique est-elle une vulnérabilité?

J'ai remarqué dans plusieurs tests de pénétration que PHP convertit des valeurs comme 1e9 à 1000000000 tandis que la longueur de chaîne maximale acceptée de ce nombre est 3 (dans le stockage de la base de données et en tant que propriété maxlength sur les formulaires HTML).

Néanmoins, lors de la saisie de 1e9 (3), PHP renverra 1000000000 (10) comme sortie. C'est un nombre supérieur à ce que l'application attend et peut gérer correctement. Par conséquent, je considérerais une meilleure validation des entrées utilisateur pour éviter cela.

Premièrement, je suppose que ce comportement n'est pas dangereux mais simplement indésirable, est-il légitime de supposer cela? Deuxièmement, puis-je considérer cela comme une vulnérabilité réelle (de faible gravité)?

L'entrée 9e9 entraînera la valeur maximale de 32 bits 2147483647 (10) au lieu de 9000000000 (dix). Est-ce seul (système ou configuration 32 bits) considéré comme une fuite d'informations système ou dangereux de toute façon?

29
Bob Ortiz

À proprement parler? Non, en soi, ce n'est pas une vulnérabilité. Mais cela suggère qu'il y a potentiellement un problème qui nécessite une enquête plus approfondie.

C'est l'un des problèmes inhérents aux tests au stylet. Vous trouvez quelque chose d'ambigu comme celui-ci et vous ne savez pas s'il est exploitable. Pour même commencer à découvrir s'il s'agit d'une vulnérabilité, vous devez comprendre ce que fait la limitation d'entrée.

Par exemple, si le programme a été conçu pour limiter les virements bancaires à moins de 1000 $ et que le champ de saisie est le montant, et qu'il n'y a plus de contrôle nulle part, vous venez de découvrir une énorme vulnérabilité.

D'un autre côté, si le champ n'est que les 3 premiers chiffres d'un numéro de téléphone qui crée une base de données de numéros de téléphone pour que les parents entrent les numéros de contact d'une école, et la validation consiste simplement à s'assurer que l'utilisateur n'entre que les 3 premiers chiffres , vous n'avez probablement rien trouvé d'autre qu'un cas de coin où un parent très ringard peut bousiller son propre numéro de téléphone dans la base de données.

18
Steve Sether

Pourquoi cela arrive-t-il?

C'est parce que PHP has typage lâche . Jetez un œil à cet exemple:

$x = "1e6";
echo strlen($x); // 3
echo $x * 1;     // 1 000 000

Sur la deuxième ligne, $x Est supposé être une chaîne et, en tant que tel, comporte évidemment trois caractères. Sur la troisième ligne, $x Est interprété comme un entier, ou 1 000 000 dans ce cas.

C'est un problème?

Cela peut certainement provoquer des bogues, et chaque bogue est une vulnérabilité de sécurité potentielle. Mais en soi, cela ne rend pas votre application vulnérable par défaut. Mais essayons d'imaginer un scénario où cela causerait un problème.

Disons qu'un forum a des groupes numérotés que les utilisateurs peuvent rejoindre librement, mais les 10 premiers groupes (0 à 9) sont réservés aux administrateurs. Le code de joingroup.php Ressemble à ceci:

$group = $_POST['group'];
if(strlen($group) > 1 || $isadmin) {
    join_group($group, $uid);
}
else {
    // Fail.
}

Vous pouvez vous faufiler dans un groupe d'administrateurs sans être réellement administrateur en publiant par exemple 0.3e1, Qui a une longueur de chaîne de 5 mais correspond à 3. Je sais, c'est un exemple stupide. Le point que je veux faire valoir est que si vous comptez sur strlen() (ou toute autre chose qui traite l'entrée comme une chaîne) pour valider les données numériques, vous pourriez être vulnérable.

La simple publication de 3.0 Ou  3 Contournerait également cette vérification. Pour en savoir plus sur la façon dont PHP convertit implicitement les chaînes en nombres, consultez le manuel .

Comment dois-je gérer cela en PHP?

Validez l'entrée utilisateur. Vérifiez que vous obtenez réellement un entier lorsque vous vous attendez à obtenir un entier:

if(!ctype_digit($group)) {
    // Fail.
}

C'est aussi une bonne idée de toujours traiter quelque chose qui devrait être un entier comme un entier et non une chaîne:

$group = (int) $_POST['group']
if($group > 9 || $isadmin) {
    // ...

S'agit-il d'une fuite d'informations système?

Apparemment, cela peut révéler la valeur entière maximale. Peut-être que quelqu'un pourrait déduire que vous utilisez PHP à partir de cela, mais il existe probablement de nombreuses autres façons de le faire déjà. La valeur maximale dépend de la plate-forme, donc elle pourrait être utilisée pour les empreintes digitales. Mais dans 32 bits sont probablement utilisés sur un système 32 bits et 64 bits sur un système 64 bits. C'est donc la seule information que vous divulguez.

26
Anders