[BJDCTF2020]Easy MD5

[BJDCTF2020]Easy MD5

目录

[BJDCTF2020]Easy MD5

题目:buu平台上的,    题目链接

解题过程:

 1.关于password=md5($pass,true)

2.md5弱碰撞

3.md5强比较

 相关链接:


题目:buu平台上的,    题目链接

解题过程:

打开题目后是这样滴

随便输入了几个数值,只能发现get传参password,其他没啥发现,然后在消息头里找到了一些线索

select * from 'admin' where password=md5($pass,true)

 

 1.关于password=md5($pass,true)

做题的时候在网上找大佬的关于这方面的wp,看了许多,大部分的话直接说输入ffifdyop就行了,但是没有将具体原因说清楚,所以继续找,找到了一个讲的相对而言比较有用而且详细的,链接在博客结尾,这里的话摘一些

首先找了一下关于md5(string,raw)的定义,为接下来的操作做铺垫

这个块引用原文章链接为原文章,同时在博客结尾也有
  1. content: ffifdyop

  2. hex: 276f722736c95d99e921722cf9ed621c

  3. raw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c

  4. string: 'or'6]!r,b

    这里需要注意的是,当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是  'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c  这种。

       上面的’ffifdyop‘字符串对应的16位原始二进制的字符串就是”    'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c    “  。  '  \  '后面的3个字符连同'  \  '算一个字符,比如’    \xc9    ‘,所以上述一共16个。当然,像’    \xc9    ‘这种字符会显示乱码。

       然后我们可以用’ffifdyop‘带入,看一下实际的效果。

      

      

       这里32位的16进制的字符串,两个一组就是上面的16位二进制的字符串。比如27,这是16进制的,先要转化为10进制的,就是39,39在ASC码表里面就是’    '    ‘字符。6f就是对应‘    o    ’。

       然后我们得到的sql语句就是 SELECT * FROM admin WHERE username = 'admin' and password = ''or'6�]��!r,��b'

       为什么password = ''or'6�]��!r,��b'的返回值会是true呢,因为or后面的单引号里面的字符串(6�]��!r,��b),是数字开头的。当然不能以0开头。(我不知道在数据库里面查询的时候,�这种会不会显示)

       这里引用一篇文章,连接在下面,里面的原话“a string starting with a 1 is cast as an integer when used as a boolean.“

      在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数。要注意的是这种情况是必须要有单引号括起来的,比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1  ,也就相当于password=‘xxx’ or true,所以返回值就是true。当然在我后来测试中发现,不只是1开头,只要是数字开头都是可以的。

       当然如果只有数字的话,就不需要单引号,比如password=‘xxx’ or 1,那么返回值也是true。(xxx指代任意字符)

       表里就只有一条数据,用于测试。

       

       

       

       

       所以到这里为止,就完成了sql注入。同时要注意的是,这种sql语句,在mysql里面是可以行得通的,但是在oracle数据库里面这样的语句是有语法错误的。

       所以回过头来为什么ffifdyop就是答案,因为ffifdyop的md5的原始二进制字符串里面有‘or’6这一部分的字符。那么进一步思考这个单引号是否是必要的,这两个单引号是为了与原有的语句的单引号配对。所以我们理解了这个sql注入的原理,那么就明白了我们需要怎样的字符串。

 然后输入ffifdyop之后,跳转

 

2.md5弱碰撞

 

注意f12中的信息


$a = $GET['a'];
$b = $_GET['b'];

if($a != $b && md5($a) == md5($b)){
    // wow, glzjin wants a girl friend.

 这个时候要寻找md5后开头是0e的字符串,0e在比较的时候会将其视为科学计数法,所以其后面无论是什么都无所谓,get传参

?a=QNKCDZO&b=s155964671a

网上找了一些md5相同的字符串,原文链接

QNKCDZO
0e830400451993494058024219903391

s878926199a
0e545993274517709034328855841020
 
s155964671a
0e342768416822451524974117254469
 
s214587387a
0e848240448830537924465865611904
 
s214587387a
0e848240448830537924465865611904
 
s878926199a
0e545993274517709034328855841020
 
s1091221200a
0e940624217856561557816327384675
 
s1885207154a
0e509367213418206700842008763514

然后传参后再次跳转

 

3.md5强比较

 <?php
error_reporting(0);
include "flag.php";

highlight_file(__FILE__);

if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    echo $flag;
} 

 数组进行绕过,因为md5不能处理数组,所以md5(param1[])返回false,===两边都返回false,自然就相等(同样弱比较也可以用数组绕过进行操作)

post传值

param1[]=1&param2[]=2

得到flag


 相关链接:

1.关于password=md5($pass,true)的解释

2.php弱类型总结

 

 

 

 

 

 

 

 

 

  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值