目录
基础:
盐(Salt):
哈希长度拓展攻击:
kali下载相关工具hash-ext-attack:
hash拓展题目特征:
哈希拓展ctf题:
2023楚慧杯upload_shell
实验吧之让我进去:
前言:具体怎么加密解密补位的原理我不懂,深入理解的部分我在文末挂了链接,以下也只是我做题的结论和通解,可能不准确(但是做题还挺准确),有错误欢迎指出:
是在密码加密过程中引入的一个随机值,它与密码结合使用,目的是增加密码的复杂性和安全性。在密码加密中,常见的做法是将用户提供的密码进行哈希处理,然后存储哈希值而不是明文密码。这样可以防止密码被明文泄露,但也带来了一些安全风险。盐的作用是对密码进行加强并增加密码的熵。具体而言,它通过在密码中添加一个随机生成的字符串,使得相同的密码在加密后生成不同的哈希值。这样即使两个用户拥有相同的密码,它们的哈希值也会不同,从而增加了破解密码的难度。使用盐的典型示例是将盐值和密码一起输入到哈希函数中进行计算,然后将盐值和生成的哈希值一起存储在数据库中。在验证密码时,系统会从数据库中获取盐值,并将用户输入的密码和盐值一起传递给哈希函数进行匹配。
可以被用来构造一个新的有效哈希值,从而绕过原有的认证。这是因为,MD5和SHA-1算法的哈希函数存在一个特定的性质:给定一个消息M和其哈希值H,可以很容易地计算出一个新的消息M',使得M'的哈希值为任意指定的值H'。也就是说我们可以在不知道a的字符串具体字母:(前提知道字符串a的md5值和字符串a的长度) 可以算出字符串(a+b)的md5值 ,b为你自己构造的一个字符串。
如果一个应用程序是这样操作的:
- 准备了一个密文和一些数据构造成一个字符串里,并且使用了MD5之类的哈希函数生成了一个哈希值(也就是所谓的signature/签名)
- 让攻击者可以提交数据以及哈希值,虽然攻击者不知道密文
- 服务器把提交的数据跟密文构造成字符串,并经过哈希后判断是否等同于提交上来的哈希值
这个时候,该应用程序就易受长度扩展攻击,攻击者可以构造出{$secret || data || attacker_controlled_data}的哈希值。
git clone https://github.com/shellfeel/hash-ext-attack.gitcd /home/kali/hash-ext-attack/
pip install -r requirements.txt
通常会给出$secert+“一串明文”的md5值,虽然不知道$secret是什么但是会给出$secret的长度,出现这种情况题目就大概率掺杂了哈希拓展攻击
";
echo(md5($secret."adminpassword"));
@$username = urldecode($_POST["username"]);
@$password = urldecode($_POST["password"]);
if (!empty($_COOKIE["source"])) {
if ($username === "admin" && $password != "password") {
if ($_COOKIE["source"] === md5($secret.$username.$password)) {
// 在验证用户后,如果登录成功,设置会话变量来表示用户已登录
$_SESSION['loggedin'] = true;
$_SESSION['username'] = 'admin'; // 用户名
$_SESSION['role'] = 'admin'; // 用户角色或权限
echo "";
}
else {
echo "
";
die ("你的cookie好像不太对啊");
}
}
else {
die ("可不会轻易放你进去");
}
}
14
879bd10c8628894d388c068a25326c21
关于该源码解析:
首先,通过
highlight_file(__FILE__);
将当前文件的源代码显示在页面上,这可能是为了方便调试和查看代码。通过
include "./my.php";
引入了一个名为"my.php"的文件,其中可能包含了一些相关的变量或函数。
echo strlen($secret);
输出了变量$secret
的长度为14。
echo(md5($secret."adminpassword"));
计算了$secret
与字符串"adminpassword"拼接后的MD5哈希值,并将结果输出。通过
$_POST
获取了通过POST请求发送的"username"和"password"参数,并使用urldecode
对其进行解码。如果存在名为"source"的Cookie,执行以下逻辑:
- 检查输入的用户名是否为"admin",并且密码不等于"password"。
- 检查Cookie中的"source"是否等于
md5($secret.$username.$password)
的值。如果验证通过,则设置会话变量来表示用户已登录,包括
$_SESSION['loggedin'] = true;
、$_SESSION['username'] = 'admin';
和$_SESSION['role'] = 'admin';
,然后重定向到"upload.php"页面。如果验证未通过,输出错误信息"你的cookie好像不太对啊"。
如果用户名不是"admin"或密码为"password",则输出错误信息"可不会轻易放你进去"。
我们注意到,md5($salt+“adminroot”)=e6ccbf12de9d33ec27a5bcfb6a3293df,对于未知salt的MD5或SHA-1哈希,哈希长度拓展攻击可以被用来构造一个新的有效哈希值,从而绕过原有的认证。这是因为,MD5和SHA-1算法的哈希函数存在一个特定的性质:给定一个消息M和其哈希值H,可以很容易地计算出一个新的消息M',使得M'的哈希值为任意指定的值H'。也就是说我们可以在不知道a的字符串具体字母:(前提知道字符串a的md5值和字符串a的长度) 可以算出字符串(a+b)的md5值 ,b为你自己构造的一个字符串。
具体怎么加密解密补位的原理我不懂,以下也只是我做题的结论,可能不准确,有错误欢迎指出:
这里我们得知了md5($secret."adminpassword"),即$secret拼接上adminpassword这13个字符等于879bd10c8628894d388c068a25326c21,secret的长度是14,明文的长度是13,明文加秘钥的长度必须要有27。秘钥的长度可以是14到27(14加13),规定了username=admin,下面是把admin当做秘钥的一部分塞进秘钥的长度里,那么秘钥长度就是19,已知明文就是password(不能是其他的,因为我们已知的MD5值就是$secret+adminpassword拼接起来的MD5值),已知hash就是源码里给出的879bd10c8628894d388c068a25326c21,扩展字符随便。把新hash和新明文url塞进包里上传绕过验证
后面对上传页面用sqlmap得到flag
靶场链接:http://ctf5.shiyanbar.com/web/kzhan.php
抓包把里面的source=0改成source=1,得到源码
源码:
$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
}
}
代码分析:
- 变量
$flag
存储了一个标志字符串,表示注册用户成功登录后可以获取到flag。- 变量
$secret
是用于加密和验证的秘密字符串,长度为 15 个字符。- 变量
$username
和$password
存储了从用户输入中获取的用户名和密码。- 如果存在名为 "getmein" 的 Cookie,会执行以下判断:
判断用户名解码后是否等于 "admin",且密码解码后不等于 "admin"。
- 如果 "getmein" Cookie 的值等于将秘密字符串与用户名和密码解码拼接后进行哈希得到的结果(md5(secret.urldecode(secret.urldecode(username . $password)))。
- 如果以上条件都满足,则输出一条成功登录的消息,并终止程序并显示标志字符串。
- 否则,终止程序并显示错误消息。
- 设置名为 "sample-hash" 的 Cookie,值为将秘密字符串与用户名为 "admin",密码为 "admin" 的组合进行哈希得到的结果(md5($secret . urldecode("admin" . "admin"))),有效期为 7 天。
- 如果不存在名为 "source" 的 Cookie,会设置一个名为 "source" 的 Cookie,值为 0,有效期为 7 天。
- 如果存在名为 "source" 的 Cookie,会进行一个条件判断:
- 如果 "source" Cookie 的值不等于 0,则输出一段空字符串。这可能是为了输出当前的源代码。
重点在这一行:
setcookie("sample-hash", md5($secret . urldecode("admin" . "admin")), time() + (60 * 60 * 24 * 7));
代码逻辑如下:
使用
md5($secret . urldecode("admin" . "admin"))
计算了字符串"adminadmin"与变量$secret
拼接后的MD5哈希值。
setcookie("sample-hash", md5($secret . urldecode("admin" . "admin")), time() + (60 * 60 * 24 * 7));
将名为"sample-hash"的Cookie设置为上一步计算得到的哈希值。
time() + (60 * 60 * 24 * 7)
设置了Cookie的过期时间,当前时间加上7天的秒数,即表示Cookie在7天后过期。
抓包后再cookie里能看见sample-hash的值,也就是说我们已知$secert+adminadmin的md5值,还知道 secert的长度为15,我们题里面password不能为admin 但必须是admin开头的字符,因为前提是已知secert+adminadmin的md5值,把admin传给username,新明文传给password,以下两种都能成功得到flag,但是注意第二种在传给password的时候需要删掉一个admin,以保证$username . $password拼接的结果是adminadmin+一串东西,而不是adminadminadmin+一串东西,毕竟我们知道的不是$secert+adminadminadmin的md5值
相关深度理解的链接:
hash哈希长度扩展攻击解析(记录一下,保证不忘)_攻击者对hash算法进行长度扩展攻击的是-CSDN博客
Everything you need to know about hash length extension attacks | SkullSecurity Blog
用MD5实现hash长度扩展攻击 By Assassin_hash_extender-CSDN博客从一个题目到hash扩展攻击 - 先知社区用MD5实现hash长度扩展攻击 By Assassin_hash_extender-CSDN博客
实验吧之【让我进去】(哈希长度扩展攻击)-CSDN博客