弱类型比较
弱类型简介
通常语言有强类型和弱类型两种,弱类型可以随意转换变量的类型。类型转换最常见的就是 int 转 string、string 转 int 。
1 2 3 4 5 6
| <?php $num = 1; $str0 = (string)$num; $str1 = strval($num); var_dump($str0); var_dump($str1);
|
string 转 int 使用的 intval() (取整函数)导致很多漏洞
1 2 3 4 5
| <?php var_dump(intval(4)); var_dump(intval("1asd"));
var_dump(intval("asd1"));
|
md5(), json_encode(), array_search(), strcmp(), switch() ,in_array() 这几个容易涉及到 php 弱类型的函数
比较操作符
==
在进行比较的时候,会先将字符串类型转化成相同,再比较值
===
在进行比较的时候,会先判断两种字符串的类型是否相等,再比较值是否相等
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
类型0-直接弱类型比较
1 2 3 4 5 6 7 8 9
| <?php if (isset($_POST['password'])) { $password = $_POST['password']; if (is_numeric($password)) { echo "password can't be number</br>"; }elseif ($password == 404) { echo "Password Right!</br>"; } }
|
需要 password 不为数字,但需要 password 等于 404 ,传入 404a
弱类型比较时转换成 int 类型取整数:
1 2 3 4 5
| <?php var_dump(intval("404a")); if("404a" == 404){ echo "success"; }
|
比较时转换的用的是 intval() 转换。intval() 如果转换失败返回值是 0
特殊例子整数 0
与任何字符串弱类型比较都是 true
进制绕过
过滤 demo :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?php function noother_says_correct($number) { $one = ord('1'); $nine = ord('9'); for ($i = 0; $i < strlen($number); $i++) { $digit = ord($number{$i}); if ( ($digit >= $one) && ($digit <= $nine) ) { return false; } } return $number == '54975581388'; } $flag='*******'; if(noother_says_correct($_GET['key'])) echo $flag; else echo 'access denied'; ?>
|
十六进制绕过
1 2
| <?php var_dump("0xccccccccc" == 54975581388);
|
科学计数法绕过
1 2
| <?php var_dump("1e8" == 100000000);
|
类型1-switch弱类型比较
switch中同样存在弱类型比较问题,原理和上面类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php $i ="3name"; if(is_numeric($o)){ die("no hack!!"); } switch ($i) { case 0: case 1: case 2: echo "this is two"; break; case 3: echo "flag"; break; }
|
类型2-哈希比较绕过
函数函数:md5()、sha1()
不能加密数组
md5、sha1 不能加密数组,在加密数组的时候会返回 false
1 2 3 4 5 6 7 8 9
| <?php if (isset($_POST['a']) and isset($_POST['b'])) { if ($_POST['a'] != $_POST['b']) if (md5($_POST['a']) === md5($_POST['b'])) die('Flag: '.$flag); else print 'Wrong.'; } ?>
|
科学计数法绕过
在 hash 比较时,会出现这样问题:
1 2
| "0e132456789"=="0e7124511451155" //true "0e1abc"=="0" //true4219903
|
只需要输入一个数字和字符串进行 MD5 加密之后都为 0e
例子0:两个不同的值MD5相同
下面一个例子:大致意思是输入一个数字和一个字符串,并且让他们的 MD5 值相同,才可以得到 successful
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php 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;} var_dump(md5($Username) != md5($password)); if ($logined){ file_get_contents("/flag"); }else{ echo "login failed!"; } } ?>
|
上文提到过, 0e 在比较的时候会将其视作为科学计数法,所以无论 0e 后面是什么,0 的多少次方还是 0 。所以我们只需要输入一个数字和字符串进行 MD5 加密之后都为 0e 的即可得出答案。
1
| md5('240610708') == md5('QNKCDZO')
|
1
| ?username=QNKCDZO&password=240610708
|
不止这一组,写个脚本爆破就好了
例子1:一个值MD5等于本身
1 2 3 4 5 6 7 8 9
| if (isset($_GET['md5'])){ $md5=$_GET['md5']; if ($md5==md5($md5)) echo "鎯冲埌杩欎釜CTFer鎷垮埌flag鍚�, 鎰熸縺娑曢浂, 璺戝幓涓滄緶宀�, 鎵句竴瀹堕鍘�, 鎶婂帹甯堣桨鍑哄幓, 鑷繁鐐掍袱涓嬁鎵嬪皬鑿�, 鍊掍竴鏉暎瑁呯櫧閰�, 鑷村瘜鏈夐亾, 鍒灏忔毚.</br>"; else die("鎴戣刀绱у枈鏉ユ垜鐨勯厭鑲夋湅鍙�, 浠栨墦浜嗕釜鐢佃瘽, 鎶婁粬涓€瀹跺畨鎺掑埌浜嗛潪娲�"); }else{ die("鍘婚潪娲插惂"); }
|
输入值是以 0e 开头,加密后 MD5 也是要以 0e 开头。
1
| 0e215962017 == md5(0e215962017)
|
类型3-strcmp绕过
int strcmp ( string str1, string str2 )
:需要给 strcmp() 传递 2 个 string 类型的参数。strcmp 函数比较字符串的本质是将两个变量转换为ascii ,然后进行减法运算,然后根据运算结果来决定返回值。
- str1 小于 str2 ,返回 -1
- str1 小于 str2 ,相等返回 0
- str1 小于 str2 ,返回 1
- 报错返回 0
1 2 3 4 5 6 7 8 9 10
| <?php $password="*************** if(isset($_POST['password'])){ if (strcmp($_POST['password'], $password) == 0) { echo "Right!!!login success";n exit(); } else { echo "Wrong password.."; } ?>
|
传入password[]=xxx ,绕过成功,因为函数接受到了不符合的类型,将发生错误,函数返回值为0,所以判断相等。
未总结,参考文章:https://www.cnblogs.com/anbus/p/10000571.html
类型4-array_search()、in_array()绕过
类型5-json绕过
intval 函数绕过
类型转换使用 intval() ,看一下下面例子:需要输入数字经过 intval 处理后小于 2020、加 1 后大于 2021 :
1 2 3 4 5 6 7 8 9 10
| if (isset($_GET['num'])){ $num = $_GET['num']; if(intval($num) < 2020 && intval($num + 1) > 2021){ echo "鎴戜笉缁忔剰闂寸湅浜嗙湅鎴戠殑鍔冲姏澹�, 涓嶆槸鎯崇湅鏃堕棿, 鍙槸鎯充笉缁忔剰闂�, 璁╀綘鐭ラ亾鎴戣繃寰楁瘮浣犲ソ.</br>"; }else{ die("閲戦挶瑙e喅涓嶄簡绌蜂汉鐨勬湰璐ㄩ棶棰�"); } }else{ die("鍘婚潪娲插惂"); }
|
当科学计数法用字符串表示时,如果与数字进行存在四则运算,会被当作科学计数法,否则当作字符串。
1 2 3 4 5 6
| <?php echo intval(1e10); echo intval('1e10'); echo intval('1e10' + 1); echo '1e10'; echo '1e10'+1;
|