Sky's blog

PHP函数黑魔法小总结

Word count: 1,273 / Reading time: 6 min
2017/07/22 Share

前言

暑假在家闲得慌,做了一些题,每次都能遇到一个php黑魔法的小trick题……今天就来总结一下
其实所谓黑魔法,无非就是php弱比较,一些函数遇到数组返回null这些问题……

弱比较

若字符串以数字开头,则取开头数字作为转换结果,若无则输出0

md5(),sha1()

md5()是不能处理数组的,md5(数组)会返回null,两个null相等绕过
sha1()也是同理

转换

php会自动进行转换,比如16进制,科学计数法等,有时也用这点绕过

intval()

intval()转换的时候,会将从字符串的开始进行转换知道遇到一个非数字的字符。
即使出现无法转换的字符串,intval()不会报错而是返回0。
注:
在科学计数法字符串转换为数字时,如果 E 后面的数小于某个值会弄成 double 类型,再强制转换为 int 类型时可能会有奇妙的结果,测试发现某变量为 1e-1000 时已经可以触发这个漏洞绕过两个检查,使得某变量既大于 0 又不大于 0。
例如:

1
2
var_dump((int)('1e-1000')>0);
var_dump('1e-1000'>0);

结果

1
2
3
4
Command line code:1:
bool(true)
Command line code:1:
bool(false)

再如:

1
2
var_dump((int)('1e-10')>0);
var_dump('1e-10'>0);

结果

1
2
3
4
Command line code:1:
bool(true)
Command line code:1:
bool(true)

strcmp()

strcmp()函数只有在相等的情况下返回0。
那么我们传入一个数组,它会返回NULL,而判断使用了==,而NULL==0是bool(true),这样就成功绕过。

ereg()

字符串对比解析,ereg函数存在NULL截断漏洞,当ereg读取字符串string时,如果遇到了%00,后面的字符串就不会被解析。
注:这里的%00是需要urldecode才可以截断的,这是url终止符,且%00长度是1不是3

is_numeric()

当有两个is_numeric判断并用and连接时,and后面的is_numeric可以绕过
16进制也可以绕过is_numeric()检验,可以用来绕过sql注入里的过滤

switch()

当switch没有break时可以继续往下执行。
这里也有自动转换,比如$switch_bug = a,会当0执行,=1a,会当1执行……

用到了PHP弱类型的一个特性,当一个整形和一个其他类型行比较的时候,会先把其他类型intval再比。
当检索中带入字符串,比如”sky”,会intval(‘sky’)==0,从而致使数字数组也可以查询成功

json_decode()

这个漏洞迷一样……我也是偶然发现,只能自己从下面的样例代码中领悟了

黑魔法实例脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?php 
echo "---------------- 弱比较黑魔法 -------------------------";
echo "<br>";echo "<br>";
if (1 == "1abc") {
if (0 == "abc") {
if ("0e132456789" == "0e7124511451155") {
#常见于md5弱比较绕过
echo "两个'=='的弱比较成功";
}
}
}
echo "<br>";echo "<br>";
echo "---------------- md5(),sha1()黑魔法 -------------------------";
echo "<br>";echo "<br>";
if (md5($md5_bug1[]=1) === md5($md5_bug2[]=1)){
if (sha1($md5_bug1[]=1) === sha1($md5_bug2[]=1)){
echo "md5传入数组绕过成功";
}
}
echo "<br>";echo "<br>";
echo "---------------- 转换黑魔法 -------------------------";
echo "<br>";echo "<br>";
echo "0x1e240 自动转换10进制:",0x1e240;
echo "<br>";
echo "123456 十进制数:",123456;
echo "<br>";
echo "1e240 科学计数法自动转换:",1e240;
echo "<br>";echo "<br>";
echo " ---------------- intval()黑魔法 -------------------------";
echo "<br>";echo "<br>";
echo "2 的intval()转换结果:",intval('2');
echo "<br>";
echo "3abcd 的intval()转换结果:",intval('3abcd');
echo "<br>";
echo "abcd 的intval()转换结果:",intval('abcd');
echo "<br>";echo "<br>";
$intval_bug = '1e-1000';
if ((int)($intval_bug) > 0) {
if ($intval_bug <= 0) {
echo "intval()转换问题绕过成功";
}
}
echo "<br>";echo "<br>";
echo "---------------- strcmp()黑魔法 -------------------------";
echo "<br>";echo "<br>";
$strcmp_bug[]=1;
if (@strcmp($strcmp_bug, "you_don't_know_this_string") == 0){
echo "strcmp()数组黑魔法绕过成功";
}
echo "<br>";echo "<br>";
echo "---------------- ereg()黑魔法 -------------------------";
echo "<br>";echo "<br>";
$input = urldecode('1e8%00*-*');
// echo strlen($input); #7
if (isset($input)){
if (@ereg ("^[a-zA-Z0-9]+$",$input) === FALSE){
echo $input;
echo '输入只能是数字和字母!';
}
else{
echo "ereg()%00截断绕过成功";
}
}
echo "<br>";echo "<br>";
echo "---------------- is_numeric()黑魔法 -------------------------";
echo "<br>";echo "<br>";
$is_numeric1 = "0123";
$is_numeric2 = "abc";
$c=is_numeric($is_numeric1) and is_numeric($is_numeric2);

if ($c) {
if (is_numeric(' +.1234e5678')) {
echo "is_numeric()连用漏洞绕过";
# 这样也能绕过检测……
}
}
echo "<br>";echo "<br>";
echo "---------------- switch()黑魔法 -------------------------";
echo "<br>";echo "<br>";
@$switch_bug = 0;
if (isset ( $switch_bug )) {
switch ($switch_bug) {
case 0 :
echo '你已经运行到了case0';
echo "<br>";
case 1 :
echo '你已经运行到了case1';
echo "<br>";
case 2 :
echo '你已经运行到了case2';
echo "<br>";
echo "switch()没有break连续运行绕过成功";
break;
default :
echo "1";
break;
}
}
echo "<br>";echo "<br>";
echo "---------------- array_search()黑魔法 -------------------------";
echo "<br>";echo "<br>";
$array_search=[1,0];
$eee = @array_search("XMAN", $array_search);
if($eee){
echo "array_search()检索字符串绕过成功";
}
echo "<br>";echo "<br>";
echo "---------------- json_decode()黑魔法 -------------------------";
echo "<br>";echo "<br>";
$v3=0;
$input = '{"key":0001}';
$b=json_decode(@$input);
if($var = $b === NULL){
($var === true)?$v3=1:NULL;
if ($v3) {
echo "json_decode()函数漏洞绕过成功";
}
}
?>
CATALOG
  1. 1. 前言
  2. 2. 弱比较
  3. 3. md5(),sha1()
  4. 4. 转换
  5. 5. intval()
  6. 6. strcmp()
  7. 7. ereg()
  8. 8. is_numeric()
  9. 9. switch()
  10. 10. array_search()
  11. 11. json_decode()
  12. 12. 黑魔法实例脚本