hash扩展攻击

网上借鉴的一段介绍

想象一下,有一个秘密盒子(哈希函数),这个盒子可以把任何东西(数据)变成一堆乱码(哈希值),而且这个过程是单向的,就是说你不能从乱码再变回原来的东西。
通常,当你把一些东西放进这个盒子时,如果想要让盒子正常工作,你需要在东西的后面放些填充物,比如棉花。这个填充过程是按照一定的规则来的,比如先放一点特别的棉花,再放一些普通的棉花,最后放一点标记原来东西大小的棉花。
哈希长度扩展攻击就是有人发现了这个秘密:他们不需要知道你原来放进去的是什么,只要知道最后的乱码和你放进去东西的大小,他们就能在不打开盒子的情况下,在你的东西后面加上更多的东西和填充物,然后算出这个新组合的乱码。
这样他们就能假装知道你最初放进去的东西,实际上他们只是在你的东西后面加了些自己的东西,然后算出了一个看起来合理的乱码。
这种攻击之所以可行,是因为填充规则是公开的,而且这个秘密盒子在处理东西时有一些可以预测的特点。所以,如果别人知道你的乱码和你放进去东西的大小,他们就可能利用这些信息进行攻击。

核心原理就是

在已知flag长度和md5值的情况下
flag长度和flag的md5值
md5(md5(flag)+yusa) == md5(flag+yusa)
可以使得这两个值相等

实验吧题目

$flag = "XXXXXXXXXXXXXXXXXXXXXXX";
$secret = "XXXXXXXXXXXXXXX"; // This secret is 15 characters long for security!

$username = $_POST["username"];
$password = $_POST["password"];

if (!empty($_COOKIE["getmein"])) {
    if (urldecode($username) === "admin" && urldecode($password) != "admin") {
        if ($COOKIE["getmein"] === md5($secret . urldecode($username . $password))) {
            echo "Congratulations! You are a registered user.\n";
            die ("The flag is ". $flag);
        }
        else {
            die ("Your cookies don't match up! STOP HACKING THIS SITE.");
        }
    }
    else {
        die ("You are not an admin! LEAVE.");
    }
}

setcookie("sample-hash", md5($secret . urldecode("admin" . "admin")), time() + (60 * 60 * 24 * 7));

if (empty($_COOKIE["source"])) {
    setcookie("source", 0, time() + (60 * 60 * 24 * 7));
}
else {
    if ($_COOKIE["source"] != 0) {
        echo ""; // This source code is outputted here
    }
}

这段代码的关键因素是

if ($COOKIE["getmein"] === md5($secret . urldecode($username . $password))) 

通过阅读源码,我们可以知道,如果想要得到flag,需要几个条件:

1、cookei字段的getmein不能为空
2、发送过去的username = admin,并且,password != admin
3、getmein的值 = $secret + $username + p a s s w o r d 的 m d 5 值前两个条件都很容易满足,关键是第三个,因为我们不知道 password 的md5值 前两个条件都很容易满足,关键是第三个,因为我们不知道 passwordmd5值前两个条件都很容易满足,关键是第三个,因为我们不知道secret的内容,只知道长度为15,不过继续阅读后面的内容,可以获得一个信息是:

md5($secret + adminadmin)已知,也就是请求头中的sample-hash :

在这里插入图片描述

那么,

如果 u s e r n a m e = a d m i n , username = admin, username=adminpassword = adminwn,则问题则转化成:

已知md5(‘xxxxxxxxxxxxxxxadminadmin’),求md5(‘xxxxxxxxxxxxxxxadminadminwn’)的值,然后只要把该值赋给geimein即可。综上,可以利用md5扩展长度攻击。
用法:

输入已知的字符串和md5结果(在这里是adminadmin和在这里插入图片描述
),输入密钥的长度(15),再输入你想要在后面添加的字符串,它会自动给你返回md5后的结果,以及填充数据:
在这里插入图片描述

把数据在burpsuite中填入后重发即可得到flag。
在这里插入图片描述

另一个题目

<?php
error_reporting(0);
$flag=getenv("DASFLAG");#`$flag=getenv("DASFLAG");` 从环境变量中获取标志值 `DASFLAG`

if(isset($_GET["md5"]) && isset($_GET["i"]) && isset($_GET["s"])){#代码检查GET请求中是否存在三个参数:`md5`、`i` 和 `s`。
    $fl4g = substr_replace($flag, $_GET["s"], $_GET["i"], 1);
    if($_GET["md5"] === md5($fl4g)){
        echo $flag;
    }else{
        die("please try again");
    }
}else{
    highlight_file(__FILE__);
    echo md5($flag."yusa");
} 1c3de59d2f68788cc792e0eb7d604710

这个题目核心的地方在if($_GET["md5"] === md5($fl4g)
我们get的变量md5值需要和题目环境变量DASFLAG的值经过字符替换之后的MD5值相同,会给flag。也就是说要去构造MD5的参数值。
这里已知了flag也就是secret值为38位,data值为yusa。

f l 4 g = s u b s t r r e p l a c e ( fl4g = substr_replace( fl4g=substrreplace(flag, $_GET[“s”], G E T [ " i " ] , 1 ) ; 这行代码的作用是用 ‘ _GET["i"], 1); 这行代码的作用是用 ` GET["i"],1);这行代码的作用是用_GET[“s”]中的字符替换 f l a g ‘ 中第 ‘ flag` 中第 ` flag中第_GET[“i”]个位置的字符,并将结果存储在$fl4g` 变量中。

已知md5(flag+yusa),然后我们构造
md5(md5(flag+yusa)+11) == md5(flag+yusa+11)
这个11是随意的都可以,然后构造相等

在这里插入图片描述

payload
http://127.0.0.1/index.php?md5=94584097b4cc31f15df9abdcf2df87b9&i=-1&s=}yusa%80%00%00%00%00%00%00%00%00%00%00%00%00%00P%01%00%00%00%00%00%0011
在这里插入图片描述

在这里插入图片描述

考试题

<?php
function generateToken($salt, $message){#传入的是uniqid和guest
	if($salt == "" || $message == "") {
		return false;
	}
	return sprintf("%s.%s", base64_encode($message), md5($salt . $message));#输出的是guestbase64的编码和md5(uniqid+guest)
}
function validateToken($token, $salt) {
	list($payload, $hash) = explode(".", $token);#这行代码将提供给函数的$token(一个以点分隔的字符串)分割成两个部分。`explode`函数使用点号`.`作为分隔符,将字符串分割成数组,其中包含前后的元素和每个分隔符之间的内容。在这种情况下,$token被假定为一个类似于 `a.b` 的格式化的令牌,其中$a对应`$payload`,而$b对应`$hash`。
	$message = base64_decode($payload);
	if(md5($salt . $message) == $hash) {
		return $message;
	}
	return false;
}
session_start();
@$salt = $_SESSION["salt"];
if($salt == "") {
	$salt = $_SESSION["salt"] = uniqid();#uniqid为13位数字
	#print($salt);
	$defaultToken = generateToken($salt, "guest");#调用 generateToken 函数,使用 salt 和字符串 "guest" 生成一个默认的安全令牌。这个函数应该实现了某种加密或哈希机制,用于生成 token。
	setcookie("token", $defaultToken);#通过 setcookie 函数将生成的 defaultToken 存储在名为 "token" 的 cookie 中。这个 token 可以在后续的请求中用于验证用户身份。
}

@$token = $_REQUEST["token"];

$greeting = "";
if ($token && $token != "") {
	$message = validateToken($token, $salt);
	if($message !== false) {
		$greeting = "Wellcome: " . $message . PHP_EOL;
		if ($message !== "guest") {			
			$greeting .= print("flag{123123123}");
		}
	}else{
		$greeting = "Login failure.";
	}
}
?>

稍微改了一下,出哈哈哈你做出来了就是flag

核心就是这段

function validateToken($token, $salt) {
	list($payload, $hash) = explode(".", $token);#这行代码将提供给函数的$token(一个以点分隔的字符串)分割成两个部分。`explode`函数使用点号`.`作为分隔符,将字符串分割成数组,其中包含前后的元素和每个分隔符之间的内容。在这种情况下,$token被假定为一个类似于 `a.b` 的格式化的令牌,其中$a对应`$payload`,而$b对应`$hash`。
	$message = base64_decode($payload);
	if(md5($salt . $message) == $hash) {
		return $message;
	}
	return false;
}

要求你传进来的token必须是xxx.xxx的这种形式
因为咱们已经已知了uniqid()+yusa的md5值,所以咱们套用公式

md5(md5(flag)+yusa) == md5(flag+yusa)
md5(md5(uniqid()+yusa)+xx) == md5(uniqid()+yusa+xx)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风实验室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值