一次SQL注入不成但解锁爆出额外信息的 Tips
- 前言
- 基本介绍
- 获取到数据库用户名步骤
- 本地 MySQL 分析
- 查看当前用户权限
- 爆出库名【任意用户都可以】
- Ending...
前言
一次渗透测试项目中朋友甩过来的疑似SQL注入点, 当时并没有注入成功, 并已经感觉几乎是没有概率造成 SQL 注入的. 随后第二天朋友通过一些手段拿到了数据库用户名称. 下面来看一下原因~
基本介绍
先来一个脱敏的报告吧, 来描述一下大致场景:
这边通过单引号爆出语法错误, 那么按理来说是存在注入的, 并且通过字段名与直觉可以感觉到这是一个基于 ORDER BY 的注入, ORDER BY 注入我会啊, 只要 ORDER BY 一个不存在的列名就好了, 就能看出来是不是注入:
WTF?不应该啊, 为什么不会报错呢?正常情况应该这样:
后来简单尝试了几下基于 ORDER BY 的 Payload 就没再看这个点了, 一方面不知道代码和SQL是怎么写的, 另一方面爆出来的错误有点模糊, 感觉很奇怪.
获取到数据库用户名步骤
再后来就听朋友说获取到了数据库名称?我有点不信, 步骤如下:
payload 中, 输入了数字 + 字母
, 得到了Unknown column
的错误, 这就有戏, 随后下面的 payload 如:
就能够获得到用户名?到现在我还是有点晕, 为什么会这样...
本地 MySQL 分析
对于思考为什么ORDER BY + 任意列名
都不会报错, 这里想到的是可能后端将其转为了字符串, 所以导致每次 ORDER BY 了一个常量, 并不会对排序进行发生实质性的改变:
不过针对于这种情况, 后续可以通过往列名后面依次增加单引号来进行判断是否存在注入, 如下:
package com.heihu577;
import java.sql.*;
publicclassMySQLConnectorTest{
publicstaticvoidmain(String[] args)throws Exception {
Connection connection =
DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/docker_database?useSSL=false&useUnicode=true&characterEncoding=UTF-8", "root", "root");
String sql = "SELECT * FROM user ORDER BY 'hacker''";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
}
}
一个单引号, 打乱了SQL顺序, 包报错:
两个单引号可正常发送数据:
package com.heihu577;
import java.sql.*;
publicclassMySQLConnectorTest{
publicstaticvoidmain(String[] args)throws Exception {
Connection connection =
DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/docker_database?useSSL=false&useUnicode=true&characterEncoding=UTF-8", "root", "root");
String sql = "SELECT * FROM user ORDER BY 'hacker'''";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
System.out.println(resultSet.getString("user"));
/**
* admin
* guest
*/
}
}
}
为什么数字 + 字母
前面会增加r.
, r.
通常是 SQL 语句中的别名, 如下:
可能是开发者调试某些数据的原因, 做了这么一个判断与转换. 那么接下来看一下之前抛出的异常:
去搜了一下, 发现这篇文章: https://wenku.csdn.net/answer/4xfnmxod5k
所以这边是触发了函数调用导致的, 当一个用户不存在某些函数的具体权限的话, 则会抛出异常信息, 将用户名带出来, 为了验证这个说法, 先在本地创建一个普通用户:
mysql> create user 'heihu577'@'%' identified by 'heihu577';
Query OK, 0 rows affected (0.00 sec)
mysql> grant all privileges on docker_database.* to 'heihu577'@'%' identified by 'heihu577' with grant option;
Query OK, 0 rows affected, 1 warning (0.00 sec)
并且给予这个用户docker_database
这个数据库下的操作权限, 首先是正常的函数调用:
看起来其实没什么大问题, 不过怎么样将用户名暴露出来呢?
由于当前heihu577
这个用户只存在docker_database
下的权限, 当调用abcdefg.1()
时会发生歧义, 误以为会去abcdefg中调用函数
:
查看当前用户权限
除了可以爆出用户名以外, 也可以用来判断当前用户的权限, 如果是 root 这种权限比较大的用户, 如图:
会爆出函数不存在, 如果是普通用户 (或权限较小的用户), 会爆出具体的用户名:
爆出库名【任意用户都可以】
Ending...
原文始发于微信公众号(Heihu Share):渗透测试 | 一次SQL注入不成但解锁爆出额外信息的 Tips
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论