当前位置: 首页 > article >正文

BUUCTF_[安洵杯 2019]easy_web(preg_match绕过/MD5强碰撞绕过/代码审计)

打开靶场,出现下面的静态html页面,也没有找到什么有价值的信息。

 查看页面源代码

在url里发现了img传参还有cmd

求img参数

这里先从img传参入手,这里我发现img传参好像是base64的样子

进行解码,解码之后还像是base64的样子再次进行解码

这个数好像是16进制的,进行16进制转换成字符串

这里利用这个原理,先将index.php16进制编码,然后进行两次base64编码

输入img=TmprMlpUWTBOalUzT0RKbE56QTJPRGN3,但是页面没反应,尝试Burp抓包,发送到重放器,在Burp上修改img的参数,发现类似base64的字符,尝试base64解码

<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}

?>
<html>
<style>
  body{
   background:url(./bj.png)  no-repeat center center;
   background-size:cover;
   background-attachment:fixed;
   background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>

php代码审计

1. 错误报告和字符编码设置
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
  • error_reporting(E_ALL || ~ E_NOTICE);:设置错误报告级别,表示报告除了 E_NOTICE 级别的所有错误。
  • header('content-type:text/html;charset=utf-8');:设置 HTTP 响应头,指定返回内容的类型为 HTML,字符编码为 UTF - 8。
2. 获取用户输入并进行重定向
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
  • $cmd = $_GET['cmd'];:从 GET 请求中获取 cmd 参数的值。
  • if 语句检查是否传递了 imgcmd 参数,如果没有传递,则使用 header 函数进行页面重定向,跳转到 index.php 并附带默认的 img 和空的 cmd 参数。
3. 处理图片文件路径
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));
$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
  • $file = hex2bin(base64_decode(base64_decode($_GET['img'])));:对 img 参数进行两次 Base64 解码,再进行十六进制解码,得到文件路径。
  • $file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);:使用正则表达式过滤文件路径,只保留字母、数字和点号,防止目录遍历等攻击。
  • if (preg_match("/flag/i", $file)):检查文件路径中是否包含 flag 字样,如果包含则显示一张图片并终止程序。
  • 若不包含 flag,使用 file_get_contents 读取文件内容,进行 Base64 编码后以 data URI 的形式显示图片。

preg_replace
正则表达式函数,用于在字符串中执行搜索和替换操作。
语法: preg_replace(pattern, replacement, subject[, limit = -1[, count]])
-  pattern :要搜索的正则表达式模式。
-  replacement :用于替换匹配内容的字符串或回调函数。
-  subject :要进行搜索和替换的目标字符串或字符串数组。
-  limit :可选参数,指定最多替换的次数,默认 -1 表示无限制。
-  count :可选参数,用于存储实际替换的次数。 

preg_match
用于执行正则表达式匹配的函数。
语法:preg_match(pattern, subject[, matches[, flags = 0[, offset = 0]]])
-  pattern :要匹配的正则表达式模式。
-  subject :要进行匹配操作的目标字符串。
-  matches :可选参数,用于存储匹配结果的数组。如果匹配成功, matches[0] 将包含完整的匹配文本, matches[1] 等将包含正则表达式中捕获组匹配的内容。
-  flags :可选参数,用于指定匹配的标志,常用的有 PREG_OFFSET_CAPTURE ,会使 matches 数组中的每个元素成为一个包含匹配文本和其在 subject 中偏移量的数组。
-  offset :可选参数,指定从 subject 字符串的哪个位置开始匹配,默认为0。

4. 处理命令执行(preg_match绕过,MD5强绕过)
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}
  • 输出 cmd 参数的值。
  • echo "<br>"中<br>表示换行。
  • 使用正则表达式检查 cmd 参数是否包含危险字符或命令,如果包含则输出 forbid ~
  • 若不包含危险字符,检查 POST 请求中的 ab 参数,要求它们的字符串形式不相等,但 MD5 哈希值相等。如果满足条件,则执行 cmd 参数中的命令并输出结果;否则输出 md5 is funny ~
5. HTML 部分
<html>
<style>
  body{
   background:url(./bj.png)  no-repeat center center;
   background-size:cover;
   background-attachment:fixed;
   background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>

设置页面的背景图片,使其居中显示、覆盖整个页面,并且固定背景。

思路

求cmd参数

cmd未知,如果要输出cmd,,,

1.POST 请求中的 ab 参数,要求它们的字符串形式不相等,但 MD5 哈希值相等。

  • MD5 碰撞漏洞:代码依赖 MD5 哈希值的比较来决定是否执行命令,而 MD5 算法存在碰撞漏洞,攻击者可以找到两个不同的字符串,它们的 MD5 哈希值相同。
  • if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b']))

   2.绕过preg_match过滤函数包含的

  • 命令过滤不彻底:虽然代码对 cmd 参数进行了过滤,但可能存在绕过的方法,例如使用其他未被过滤的命令或特殊字符组合。
  • if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd))

MD5 是一种广泛使用的哈希函数,但它存在强碰撞和弱碰撞的问题

哈希碰撞

哈希函数是一种将任意长度的输入数据转换为固定长度输出(哈希值)的算法。理想情况下,不同的输入应该产生不同的哈希值,但由于哈希值的长度是固定的,而输入数据的可能性是无限的,所以必然会存在不同的输入产生相同哈希值的情况。

MD5 弱碰撞

找到一个与给定消息不同但哈希值相同的另一个消息。

MD5 强碰撞

强碰撞是指找到任意两个不同的消息m1和m2,使得它们的哈希值相同。与弱碰撞不同,强碰撞不需要预先给定一个消息。

方法

过滤函数是preg_match,使用/来进行绕过。

 if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b']))

使用了 (string) 强制类型转换,数组都被强制转换为了string(5) “Array”,数组绕过方法失效,所以要采用 MD5 强碰撞的方式来绕过此限制。

a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

原理:原本payload字符串中含有多种空白符号,MD5加密后hash值相等(空白符号不影响md5值)。但是我们上传参数时会自动进行一次url解码,这样过后因为空白字符两个url就不相等了,从而成功绕过

改为POST请求,

(不清楚是哪里出问题了,,,按大佬的wp的步骤做,换了好几种方法,但响应不正确)

cmd传参处传入dir

cmd=l\s%20/ 

cmd=cat flag=>ca\t%20/f\l\a\g

(参数a,b的值的求法暂时没弄清楚)

参考链接:buuctf-[安洵杯 2019]easy_web(小宇特详解)


http://www.kler.cn/a/529613.html

相关文章:

  • 如何构建ObjC语言编译环境?构建无比简洁的clang编译ObjC环境?Windows搭建Swift语言编译环境?
  • DeepSeek r1本地安装全指南
  • Doki Doki Mods Maker小指南
  • 边缘检测算法(candy)
  • 图论——最小生成树
  • electron 应用开发实践
  • 一文了解DeepSeek
  • Linux学习之DNS基础服务器搭建
  • Java死锁问题
  • OpenAI深夜反击:o3-mini免费上线,能否撼动DeepSeek的地位?
  • 青少年编程与数学 02-008 Pyhon语言编程基础 14课题、创建函数
  • C++ Primer 标准库类型string
  • C#面试常考随笔10:C#中有哪些常用的容器类,各有什么特点?
  • 如何使用SliverGrid组件
  • 【含文档+PPT+源码】基于微信小程序连锁药店商城
  • 2025年02月01日Github流行趋势
  • AI赋能医疗信息化与医保新政双轮驱动:医药生物行业投资机遇深度解析
  • MySQL存储过程和存储函数_mysql 存储过 call proc_stat_data(3,null)
  • C++【iostream】数据库的部分函数功能介绍
  • docker部署SpringBoot项目简单流程
  • Kotlin/Js Kotlin 编译为 JS (尝试)
  • 【产品经理学习案例——AI翻译棒出海业务】
  • C# List 列表综合运用实例⁓Hypak原始数据处理编程小结
  • VSCode插件Live Server
  • 【LangChain】Chapter11 - Question Answering
  • 通过Redisson构建延时队列并实现注解式消费