- 前言
在代码审计的时候,我们不难发现很多很多的函数需要我们bypass,这些知识点很多又很小,基本上是一眼就明白,但是下一次遇见又不太清晰,需要反反复复查找,这篇文章浅浅做个汇总,如有不足,欢迎补充。
md5加密bypass
弱比较绕过
代码语言:javascript复制<?php
$a = $_GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
echo 'success!';
}
方法一:0e绕过
绕过原理:PHP在处理字符串时会出现缺陷,如果字符串为’5e2’,本来只是一个正常字符串,但PHP会认为这是科学计数法里的e,那么PHP进行比较时会将这个字符串按照科学计数法计算,即5e2=5*10^2=500,由此0e100被认为和0相等。md5加密后的哈希值是一串16进制数,因此需要哈希值第一位为0,第二位为e即可,后面不论是什么都认为和0相等
以下字符串经过md5函数后以’0e’开头:
- QNKCDZO
- 240610708
- s878926199a
- s155964671a
- s1091221200a
- s1665632922a
经过md5函数加密一次和两次后均以’0e’开头:
- 7r4lGXCH2Ksu2JNT3BYM
- CbDLytmyGm2xQyaLNhWn
- 770hQgrBOjrcqftrlaZk
有时候题目还会用ctype_alnum()、is_numeric()或正则表达式来限制原值是纯字母或纯数字
方法二:数组绕过
绕过原理:无论是PHP弱比较还是强比较,md5()函数无法处理数组,如果传入的是数组,会返回NULL,两个数组经过加密后返回值均为NULL,形成相等。
payload:
代码语言:javascript复制?a[]=1&b[]=2
强比较绕过
代码语言:javascript复制<?php
$a = $_GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) === md5($b)){
echo 'success!';
}
虽然 PHP 是弱类型语言,但也需要明白变量类型及它们的意义,因为我们经常需要对 PHP 变量进行比较,包含松散和严格比较。
- 松散比较:使用两个等号 == 比较,只比较值,不比较类型。
- 严格比较:用三个等号 === 比较,除了比较值,也比较类型。
例如,”42” 是一个字符串而 42 是一个整数。FALSE 是一个布尔值而 “FALSE” 是一个字符串。
方法:数组绕过
细节如上所述
md5碰撞绕过
代码语言:javascript复制<?php
$a = (string)$_POST['a'];
$b = (string)$_POST['b'];
if($a != $b && md5($a) === md5($b)){
echo 'success!';
}
由于强制类型转换,传入数组会得到’Array’,这里我们只能需要一个md5前不等,md5后相等的值。
方法:使用Fastcoll生成
详细可见这篇文章
下面给出payload供使用:
代码语言:javascript复制a=M�h�� �r�w{r��o���V�J=�x>{���� �(K�n�KU�_Bu��Igm��U]�`�_��&b=M�h�� �r�w{r��o���V�J=�x>{�����(K�n�KU�_Bu��Igm���]�`�_��
POST传参时需要再次url编码
代码语言:javascript复制a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
md5截断比较
代码语言:javascript复制<?php
$a=$_GET['a'];
if(substr(md5($str), 0, 6) === "edef"){
echo 'success!';
}
方法:脚本爆破
遇到这种情况可以通过写脚本爆破的方法,通常花费时间较长
代码语言:javascript复制from multiprocessing.dummy import Pool as tp
import hashlib
knownMd5 = '666666' #已知的md5明文
def md5(text):
return hashlib.md5(str(text).encode('utf-8')).hexdigest()
def findCode(code):
key = code.split(':')
start = int(key[0])
end = int(key[1])
for code in range(start, end):
if md5(code)[0:6] == knownMd5:
print(code)
list=[]
for i in range(1): # 这里的range(number)指爆破出多少结果停止
list.append(str(10000000*i) ':' str(10000000*(i 1)))
pool = tp() # 使用多线程加快爆破速度
pool.map(findCode, list)
pool.close()
pool.join()
原值和md5加密后哈希值弱比较绕过
代码语言:javascript复制<?php
$a=$_GET['a'];
if($a == md5($a)){
echo 'success!';
}
方法:0e绕过
0e215962017
的 md5 值也是由’0e’开头,在 PHP 弱类型比较中相等
SQL注入中的md5绕过
代码语言:javascript复制Select * from ’admin’ where password=md5($pass,true)
方法:构造万能密码
ffifdyop
这个特殊的字符串,非常之经典
绕过原理:利用ffifdyop这个字符串md5函数处理后哈希值为276f722736c95d99e921722cf9ed621c,Mysql刚好会把hex转化成字符串,恰好这个哈希值转化后是’or’6<乱码> 即 'or'66�]��!r,��b
,这样就构成了一个万能密码。除了这个字符串之外,129581926211651571912466741651878684928也有同样的效果
NAN和INF
代码语言:javascript复制<?php
$a = NAN;
$b = NAN;
if($a != $b && md5($a) == md5($b)){
echo 'success!';
}
绕过原理:NAN和INF,分别为非数字和无穷大,但是var_dump一下它们的数据类型却是double,那么在md5函数处理它们的时候,是将其直接转换为字符串”NAN”和字符串”INF”使用的,但是它们拥有特殊的性质,它们与任何数据类型(除了true)做强类型或弱类型比较均为false,甚至NAN=NAN都是false,但md5(‘NAN’)=md5(‘NAN’)为true。(我试了试发现NAN雀实可以,但INF没成功不知道为啥,不解…)
sha1加密bypass
sha1加密的绕过和MD5是异曲同工的
强弱比较绕过
方法:数组绕过
sha1函数同样无法处理数组,如果传入数组会返回NULL,可以绕过强弱比较
sha1碰撞
代码语言:javascript复制a=%PDF-1.3
%����
1 0 obj
<>
stream
���� $SHA-1 is dead!!!!!�/� #9u�9���>
stream
���� $SHA-1 is dead!!!!!�/� #9u�9���