基础知识要打牢:什么是sql注入
sql注入的测试流程:
- 判断是否存在注入,注入的类型
- 获取数据库版本信息,用户等
- 猜解当前数据库名称
- 猜解数据库中的表名
- 猜解表中的字段名
- 猜解表中的字段值
- 验证字段的有效性
我们遇到了一个让人怀疑的输入框,根据做安全的敏感神经,我们怀疑框里会有注入,于是我们插入了我们输入的恶意字符,那么恶意字符有哪些呢?什么是恶意字符,就是不符合常规的,不符合正常客户输入的就是恶意字符,特殊字符,恶意的算术表达式等等
那么我们遇到了这样的框干嘛呢?我先尝试输入【‘】【”】或者编码过后的看浏览器会返回什么信息,正常的话那就正常呗,不正常那就开始分析返回的信息呗
那么单纯的输入框正常的话我们会去干嘛?这个是时候就是理论扎实的时候了,我有一篇帖子介绍了,什么是sql注入,输入框属于参数注入点,那么还有其他如:User-Agent注入点,Referer注入点,cookie注入点,这里就说这三个,还有另外的后面单说。
那么我们可对这个输入框的提交进行抓包,对上述几个注入点进行fuzz测试【模糊测试】,一个一个的尝试,尝试没有编码的,然后尝试各种编码的奇淫技巧,如果没有返回错误或者也没有想盲注那样有任何反应,那么就放过他,测试其他漏洞,类似xss,csrf等等
Low级别
这是未报错的显示
这是输入特殊字符的报错界面
那么报错的话我们干嘛.我们可以想到干嘛,输入一个'就报错了,后台数据库语句的代码是咋样的啊?报错了就扔sqlmap?如果没有工具我们该怎么办?这些都是我们需要考虑的问题,这就是我们做这个实验的意义.
我们先看low的代码进行分析
我们发现代码对传入的参数没有做任何的过滤就直接带入数据库查询语句了,我们输入的参数导致'产生歧义,不知道是和前面的'闭合还是和后面的'闭合,产生错误,那么我们可以使用sql里的注释符#来将后面的语句注释掉,我们看还会报错吗?
没有报错了,说明我们的做法正确,我们掌握了它的传参逻辑和查询语句的写法,那么我们接下来可以干嘛.我们可以首先确定该表的字段长度,那么如何判断呢?
SQL语句:1' order by number # ,number是你输入的数字,你可以从1开始尝试,如果页面返回正常,那说明表内有1个字段,如果你输入3返回不正常,那说明没有3个字段,只有2个
order by的意思如下所述:
select a,b
from table
order by 2 ;
相当于:
select a,b
from table
order by b ;
当输入3时报错
那么接下来我们可以继续构造sql语句来获取表,列,字段,我们可以利用union语句来构造sql查询,union是连接查询,union意思具体不做赘述
那么我们现在该利用漏洞获取那些的信息呢?
这里我们根据错误回显发现数据库是mariad数据库,是mysql的替代品.
我们会用到的mysql函数,当然如果是其他类型的数据库,根据其内置的函数来进行信息收集即可
- database():当前网站使用的数据库
- version():当前mysql的版本
- user():当前mysql的用户
那么我们可以构造如下sql语句来查询所需的信息
union select database(),version()
我们发现成功的显示了当前网站使用的数据库为dvwa,当前数据库版本为5.5.60-MariaDB
我通过构造查询语句得到了数据库版本的信息
我们了解到Mysql5.0以上版本会有information_schema默认数据库,同时支持多线程,多用户
5.0以下版本不内置这个默认函数,同时支持多线程,但不支持多用户
infomation这个默认数据库会存放当前用户创建的所有数据库的库名,表名,列名,
对应着,SCHEMATA,TABLES,COLUMNS
schemata表存储该用户创建的所有数据库的库名,其中有我们需要记住的字段名为schena_name
tables表存储了该用户创建的所有数据库的库名和表名,对应的我们需要记住其中tables_schema和tables_name两个字段
columns表存储了该用户创建的所有数据库的库名,表名,列名,对应的我们需要记住其中的tables_schema,tables_name,column_name三个字段
那么我们现在可以构造如下语句,来查询默认数据库内的其他数据库名
1' union select 1,schema_name from information_schema.schemata#
构造如下语句来查询默认数据内的其他表名
1' union select 1,table_name from information_schema.tables#
构造如下语句来查询默认数据库内的字段名
1' union select 1,column_name from information_schema.columns#
这里我只是把默认的几个表查询了,实际中我们结合之前查找到的当前网站使用的数据库来做where查询,请看官自行发挥
Medium级别
那么以上dvwa,low级别的sql 显注实验结束,我们进入下一步medium
我们发现中级别的没有输入框了,改成下拉框了,提交参数的方式也改成了post请求
那么我们应该怎么做呢?我们首先想的是应该是抓包看一下数据包是咋样的,
那么我们看到数据包修改成了post,其他的没有很大的改变,我们还是可以尝试我们的几个注入点,我们打开burp的repeater插件进行测试
我们先判断是否存在注入,并且分析注入是字符型还是数字型
发现存在注入点,并且提示'被/转义,说明过滤了字符型注入,我们尝试下构造数字型注入的poc
or 1 = 1
返回正常,说明该注入为数字型注入.
我们分析下源码
我们发现参数在提交的查询前做了一个过滤:
过滤函数为mysql_real_escape_string(),该函数转义sql语句中使用的字符串中的特殊字符
有以下字符受到影响
- \x00
- \n
- \r
- \
- '
- "
- \x1a
如果成功,则该函数返回被转义的字符串,如果失败,则返回false
因此,数字型的注入能够绕过这个漏洞,接下来收集信息的操作就是跟上面的low级别一样,注意一点,联合查询时需要输入''的话我们可以使用类似16进制来达到查询的效果
High级别
接下来我们进入high级别,我们先看代码
代码没有做过滤,我们尝试了'发现报错,存在注入,但是看代码发现加了一个LIMIT 1 ,LIMIT的使用格式为 limit m,n 其中m是指记录开始的位置,n是指取n条记录.,这个我们可以直接通过#来注释掉,那么这样的话后面的操作就和low级别的手工注入一样了
注意:
我们发现高级别的查询提交页面和查询结果显示页面不是同一个,也没有执行302跳转,这样做的目的是为了防止一般的sqlmap注入,因为sqlmap在这个注入的过程中,无法在查询提交页面上获取查询结果,没有了反馈,也就没办法进一步注入
最后我们留一个问题给看官,大家对注入impossible级别有什么骚操作???