in_array函数缺陷

in_array

in_array介绍

先来看一下in_array函数的介绍:
在这里插入图片描述

从上图的介绍可以看出:

  1. 这个函数的漏洞点就是如果第三个参数没有被设置或者设置为false时,那么从 h a y s t a c k 比较 haystack比较 haystack比较needle时,采用的就是弱类型比较。
  2. 如果第三个参数设置为了true,那么就会同时再检查类型

弱类型比较tips

弱类型比较时,如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行。
"0e"开头的字符串参与弱类型比较时,会将0e这类字符串识别为科学技术法的数字,0的无论多少次方都是零,所以会将它转换成0。
纯字符串与数值进行弱类型比较时,会先将字符串强制转换成数值,也就是0。

看一个例子:

var_dump('1a' == 1);          //truevar_dump('1a' === 1);         //falsevar_dump('0e' == 0);          //truevar_dump('0e' === 0);         //falsevar_dump('1234abc' == 1234);  //truevar_dump('1234abc' === 1234); //falsevar_dump('0e12344abc' == 0);  //truevar_dump('0e12344abc' === 0); //falsevar_dump('abcdefghik' == 0);  //truevar_dump('abcdefghik' === 0); //false
?>

弱类型比较总结

1. md5碰撞

if (isset($_GET['username']) && isset($_GET['password'])) {$logined = true;$Username = $_GET['username'];$password = $_GET['password'];if (!ctype_alpha($Username)) {$logined = false;}if (!is_numeric($password) ) {$logined = false;}if (md5($Username) != md5($password)) {$logined = false;}if ($logined){echo "successful";}else{echo "login failed!";}
}
?>

从上面代码看出,如果想认证成功,那就需要满足:

  • username和password都不为空
  • username需要是纯字符串
  • password需要是数字
  • username和password的md5值需要相等

这里就用到了md5碰撞。0e在比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方还是0。
所以只需要username和password进行md5之后分别是两个以0e开头的就满足条件了。

payload:

?username=QNKCDZO&password=240610708

一些以md5后0e开头的值:

QNKCDZO
0e830400451993494058024219903391s878926199a
0e545993274517709034328855841020s155964671a
0e342768416822451524974117254469s214587387a
0e848240448830537924465865611904s214587387a
0e848240448830537924465865611904s878926199a
0e545993274517709034328855841020s1091221200a
0e940624217856561557816327384675s1885207154a
0e509367213418206700842008763514240610708
0e462097431906509019562988736854
2. 十六进制与数字比较

error_reporting(0);function noother_says_correct($temp)
{$flag = 'flag{test}';$one = ord('1');    //ord — 返回字符的 ASCII 码值$nine = ord('9');    //ord — 返回字符的 ASCII 码值$number = '3735929054';// Check all the input characters!for ($i = 0; $i < strlen($number); $i++){// Disallow all the digits!$digit = ord($temp{$i});if ( ($digit >= $one) && ($digit <= $nine) ){// Aha, digit not allowed!return "flase";}}if($number == $temp)return $flag;
}$temp = $_GET['password'];
echo noother_says_correct($temp);
?>

想让这段代码成功输出flag,需要满足:

  • 传入的password的前十位的ascii值不能在ord(1)和ord(9)之间,左闭右闭
  • $password值与$number的值进行弱类型比较后需要相等

这段代码冲突的地方就是$number的值的所有数字都是在1~9之间,但是又要让$password的前十位中每一位的值不能在1-9之间,又要让password与number相等。
这里就用到了进制之间的弱类型比较,这里将$number的值转换成十六进制即可。注意十六进制前面要加上0x。

payload:

?password=0xdeadc0de
3. json绕过

if (isset($_POST['message'])) {$message = json_decode($_POST['message']);$key ="*********";if ($message->key == $key) {echo "flag";}else {echo "fail";}
}
else{echo "~~~~";
}
?>

想让这段代码成功打印flag需要满足post一个json数据,并且json中key字段的值与$key的值进行弱类型比较时相等。

由于我们不知道$key的值,但是题意来讲,它是个纯字符串,所以我们可以通过"abcd" == 0这一点来实现打印出flag。

payload:

message={"key":0}
4. array_search和is_array绕过

if(!is_array($_GET['test'])){exit();}
$test=$_GET['test'];
for($i=0;$i<count($test);$i++){if($test[$i]==="admin"){echo "error";exit();}$test[$i]=intval($test[$i]);
}
if(array_search("admin",$test)===0){echo "flag";
}
else{echo "false";
}
?>

先来看一下这两个函数的介绍:
在这里插入图片描述

想让上面的代码成功输出flag,需要满足:

  • test参数接收的值是一个数组类型
  • test数组中的值不能有admin
  • test数组中的值被强制转换成int类型后,数组内的第一个值与"admin"进行弱类型比较时需要相等。

通过这三个条件来看,只需要传入一个数组,并且第一个值是0就可以了。

payload:

?test[]=0
5. strcmp漏洞绕过

php版本 < 5.3


$password="***************";if(isset($_POST['password'])) {if (strcmp($_POST['password'], $password) == 0) {echo "Right!!!login success";exit();} else {echo "Wrong password..";}}
?>

先来看一下strcmp函数的介绍:

在这里插入图片描述

当一个字符串是另一个字符串的一部分时,strcmp 返回 strlen($str1)-strlen($str2)。 否则,如果两个字符串不相同则返回 -1 或 1,否则返回 0。
strcmp的比较为弱类型比较。
所以上面的代码,想要登录成功就需要POST上去的password值与$password的值弱类型比较后相等就行,需要注意的是strcmp的两个参数的类型都是字符串类型。
这个函数用数组来绕过,原因是函数接收到了不符合的类型,会产生错误,但是还是会判断为相等。

payload:

?password[]=1
6. in_array绕过
$ostype = intval($_GET['os']);$os = array("Mac", "NT", "Irix", "Linux");if (in_array($ostype, $os)) {echo "flag";}else{echo "error";}

想让上面的代码输出flag,就需要:

  • GET方式传入os参数
  • 并且强制转换成int类型后的os值需要经过in_array在os数组中查过,结果为true

这里就是用到了in_array没有设置第三个strict参数为true的漏洞,in_array采用了弱比较。
这里可以用到"admin" == 0的原理,传入os的值为0,经过intval转换后,ostype是一个整型的0,那么与os数组中的字符串进行比较时,会将字符串换成为数值,这里的数组转换成数值后均为0,所以就通过的in_array函数,输出了flag。

payload:

?os=0


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部