首页 » Network_security » CTF » 正文

hackinglab.cn系列->解密关.md5真的能碰撞嘛?

写writeup前先整理下php的隐式类型转换利用方法

1.“==“

//适用于所有版本的php
“==”会在比较的时候进行类型转换再比较。
转换规则:
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行比较
例如:
<?php
$foo = 1 + “10.5”;                // $foo is float (11.5)
$foo = 1 + “-1.3e3”;              // $foo is float (-1299)
$foo = 1 + “bob-1.3e3”;           // $foo is integer (1)
$foo = 1 + “bob3”;                // $foo is integer (1)
$foo = 1 + “10 Small Pigs”;       // $foo is integer (11)
$foo = 4 + “10.2 Little Piggies”; // $foo is float (14.2)
$foo = “10.0 pigs ” + 1;          // $foo is float (11)
$foo = “10.0 pigs ” + 1.0;        // $foo is float (11)
?>

0e 纯数字这种格式的字符串在判断相等的时候会被认为是科学计数法的数字,先做字符串到数字的转换。

再看看函数string md5 ( string $str [, bool $raw_output = false ] )
如果可选的 raw_output 被设置为 TRUE,那么 MD5 报文摘要将以16字节长度的原始二进制格式返回。
为false和没有第二个参数时,为32位的16进制码

md5(‘240610708’)
//0e462097431906509019562988736854.  =0x10【462097431906509019562988736854】次方 =0
md5(‘QNKCDZO’)
//0e830400451993494058024219903391

转换后都成为了0的好多好多次方,都是0,所以
md5(‘240610708’)==md5(‘QNKCDZO’);   //True

即找到md5之后形成0e[0-9].*的hash串就可以绕过md5($password)==md5($rootadmin)这类的后台验证(前提是用户密码的md5也要是0e[0-9].*的hash串)。

*****

类似的有:
”-”(0),”+”,”*”,”^”
”/1(0),”+0,”-0,”*0,”^0
除了+号,其他算术操作符号也会发生类型的类型转换,例如MOD,DIV,*,/,%,-,
bit操作符&,|,^,<< ,>>也有同样的效果

payload: ‘-”#

可以绕过类似:$query = “select * from user where user='”.$_POST[“user”].”‘and password='”.md5($_POST[“password”]).”‘”;的后台验证(前提是user值转换后是数值0才行,像12admin转换后是数值12就不能绕过)
避免‘ or ”=’被防火墙禁。
*****************************************************

2. strcmp漏洞

如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。
期望类型是字符串类型
但是在5.3之前的php中,显示了报错的警告信息后,返回0,也就是判定其相等了

利用方式:传递数组

改写数据包数据为
password[]=admin

比较规则示例:
strcmp(“5”, 5) => 0
strcmp(“15”, 0xf) => 0
strcmp(61529519452809720693702583126814, 61529519452809720000000000000000) => 0
strcmp(NULL, false) => 0
strcmp(NULL, “”) => 0
strcmp(NULL, 0) => -1
strcmp(false, -1) => -2
strcmp(“15”, NULL) => 2
strcmp(NULL, “foo”) => -3
strcmp(“foo”, NULL) => 3
strcmp(“foo”, false) => 3
strcmp(“foo”, 0) => 1
strcmp(“foo”, 5) => 1
strcmp(“foo”, array()) => NULL + PHP Warning
strcmp(“foo”, new stdClass) => NULL + PHP Warning
strcmp(function(){}, “”) => NULL + PHP Warning

*****************************************************************

所以此题writeup:
可以看到后台代码:

<?php
$flag=FLAG;
if(isset($_POST["password"])){
    $password=$_POST['password'];
    $rootadmin="!1793422703!";
    if($password==$rootadmin){die("Please do not attack admin account!");}
    
    if(md5($password)==md5($rootadmin)){
        echo $flag;
    }else{
        die("Password Error!");
    }
}
?>

!1793422703!用md5加密后是 0e332932043729729062996282883873 (32位),符合0e[0-9].*的hash串,而
QNKCDZO用md5加密后是 0e830400451993494058024219903391,也符合0e[0-9].*的hash串,两者比较都是0=0,成功绕过,
构造表单提交QNKCDZO即可得flag:yesyouareclever!

Comment