Description:
------------
var_dump([0 => 0] === [0x100000000 => 0]); // bool(true)
# Challenge
$users = array(
"0:9b5c3d2b64b8f74e56edec71462bd97a" ,
"1:4eb5fb1501102508a86971773849d266",
"2:facabd94d57fc9f1e655ef9ce891e86e",
"3:ce3924f011fe323df3a6a95222b0c909",
"4:7f6618422e6a7ca2e939bd83abde402c",
"5:06e2b745f3124f7d670f78eabaa94809",
"6:8e39a6e40900bb0824a8e150c0d0d59f",
"7:d035e1a80bbb377ce1edce42728849f2",
"8:0927d64a71a9d0078c274fc5f4f10821",
"9:e2e23d64a642ee82c7a270c6c76df142",
"10:70298593dd7ada576aff61b6750b9118"
);
$valid_user = false;
$input = $_COOKIE['user'];
$input[1] = md5($input[1]);
foreach ($users as $user)
{
$user = explode(":", $user);
if ($input === $user) {
$uid = $input[0] + 0;
$valid_user = true;
}
}
if (!$valid_user) {
die("not a valid user\n");
}
if ($uid == 0) {
echo "Hello Admin How can I serve you today?\n";
echo "SECRETS ....\n";
} else {
echo "Welcome back user\n";
}
$users = array(
"0:9b5c3d2b64b8f74e56edec71462bd97a" ,
······
);
$valid_user = false;
有一个users数组,这是一个定义了MD5哈希值的用户密码列表,并将valid_user初始化为false
$input = $_COOKIE['user'];
$input[1] = md5($input[1]);
以cookie的方式接受一个输入,并将接受的输入转换为数组进行检查,将数组第二项也就是密码项转换为md5
foreach ($users as $user)
{
$user = explode(":", $user);
if ($input === $user) {
$uid = $input[0] + 0;
$valid_user = true;
}
}
在数组中遍历检查所用传入的用户和密码,如果匹配,把传入的账号赋值给uid,并添加值0以强制转换为数值数据类型,除此之外,标志$valid_user 设置为 true,这个部分就是一个验证登录的部分。
if (!$valid_user) {
die("not a valid user\n");
}
if ($uid == 0) {
echo "Hello Admin How can I serve you today?\n";
echo "SECRETS ....\n";
} else {
echo "Welcome back user\n";
}
这一部分的主要作用就是在根据uid来判断是否为管理员,如果uid为0,那么就是确认为管理员登录,否则就是user登录。
我习惯于第一步泛读代码理清思路后采用逆推的方法解决问题
首先以管理员身份登陆成功要使uid==0(注意此处为弱等于),uid如何才能变成0,要到代码第三部分uid账号等于实际传入的账号(只有验证通过的传入的账号才能赋值传递给uid),那么只要使用账号0登录并且验证通过就可以了,接下来解决如何才能验证通过。传入的账号密码要与users数组中相匹配,解密一下数组中的md5值,发现只有用户5可以解密。
06e2b745f3124f7d670f78eabaa94809解密后为hund。
现在虽然使用用户0无法登录,但是我们使用用户5可以登录。
cookie:user[0]=5;user[1]=hund;
接下来的问题就变成了如何把user[0]=5变成user[0]=0
这就用到了phpbug#69892
简单来说,就是漏洞的利用就是键名user[4294967296]效果上等于user[0],但是要注意user[0]=5,它的值是5,使用user[4294967296]=5,他的值其实已经变成了空的。但是在后边
$uid = $input[0] + 0;
本来此处input[0]的值是空的,后边+0强制转换为int类型,uid就变成了0。
在比较的时候,input和user这两个数组时用的"=="在比较,那么我们可以不设置input[0]的值,而是用input[4294967296]来代替,然后比较的时候时用的input[4294967296]和input[1]来和列表中的用户比较,而uid又是通过input[0]+0来得到的,这样就完美绕过了它的限制。
关于phpBug#69892详细的信息还是参考相关资料,这里只给出了一种利用方法。