第一关 数字型注入(POST)
操作界面如下图
使用burpsuit对流量进行抓包,把数据包发送到Repeater模块进行测试
发送正常流量,web界面正常响应情况如下图所示
首先我们要了解该关卡注意的考点①数据类型是数字型②提交方式是POST
注入点的判断有很多方式,核心的思想就是id=后面的参数能否带入数据库查询,如果参数是数据库查询语句能否执行payload语句。
判断第一步:id=1 后面加 ‘ “ ‘) “)来查询后台SQL查询语句id的闭合方式
‘ 报错
“报错
‘) 报错
“)报错
正常 其实是可以从报错信息里看出id的参数没有引号或者括号的闭合符号,为什么上面还要不停去尝试,是因为如果遇到没有错误回显的话我们只能用这种笨方法手动一次次去测试。
确定没有闭合字符,接下来就要测试参数包含或者是数据库语句能否去执行
从上图两个简单sql判断语句的不同响应情况可以确定这个id=就是注入点。接下来就是从注入上获取数据库的相关信息,信息的展现方式分为两种一种就是回显、另外一种是无回显。
接下来就需要来测试回显点了
测试回显点分两步
第一步:使用order by猜测字段(列)数量
因为id=1 肯定是带进select name,email from 某个表 where id=1 这样的查询语句中查询得,查询得结果再显示在页面上。order by语句就是看这个表有几列
可以判断该表有两列,接下来就是那些列得数据会显示在web页面上
使用 union select 1,2
最后就可以查询数据库的信息了:版本、数据库名、表名、列名、账号密码等。
值得注意的是:Mysql5.0以下版本注入属于暴力猜解,反之以上版本属于有根据猜解。在MYSQL5包含以上版本自带的数据库名information_schema,它是一个存储有MYSQL所有数据库名,表名,列名信息的数据库,反之MYSQL5以下版本不自带。换句话来说,我们可以借助查询information_schema获取指定数据库名下的表名或列名信息,从而注入实现有根据查询。
information_schema.tables表下的列table_name 存储表名信息的表
information_schema.columns表下的列column_name 存储列名信息的表
information_schema.schemata表下的列shcema_name 存储数据库名信息的表
table_schema 数据库名
table_name 表名
column_name 列名
union select version(),database()
union select 1,group_concat(table_name) from information_schema.tables where table_schema=’pikachu’
union select 1,group_concat(column_name) from information_schema.columns where table_name=’users’
union select username,password from users where id=1
第二关 字符型注入(get)
按照界面操作
使用burpsuit抓包发现,该数据包的可变参数在url中,我们就可以直接使用火狐浏览器进行测试(也可用burpsuit测试,相比较而言直接在浏览器上测试效果直接。平时测试时能用浏览器建议尽量用浏览器)
和第一关卡步骤一样,接下来测试注入点sql语句闭合方式。特别注意字符型注入肯定会用闭合符号,闭合符号有 ‘ “ ’) “)等(更多闭合方式可以百度了解一下)
开始带入闭合符进行测试
注意报错语句,可以翻译一下意思
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘‘admin’’’ at line 1
有个语法错误是 “admin’”
可以设想有没有这种可能
正常select * from ** where user=’admin’
而我测试带进去会是这样 select * from ** where user=’admin’’ 执行语句报错
我们找个mysql数据库执行试试会不会触发上面类型的报错
带进”
没有报错这说明”这个符号没有闭合字符串,查询语句把admin”当成用户名了
接着测试’)
报错了 并且报错语句说’)错了
继续测试”)
没报错这说明”)这个符号没有闭合字符串,查询语句把admin”)当成用户名了
综合看 我们应该在报错里面寻找字符的闭合符号是哪一个 ‘和’)都有’符号所以可以确定是’符号为字符的闭合符。
其实这样就可以确定这个位置就是注入点了
和第一关开始判断这个查询语句所查询的表有几列,进而通过查询语句(union select 1,2,3,4,5…)判断那一列内容回显到web页面。
确定回显点了接下来我们就是查询想要的信息了。
admin’ union select version(),database()–+
为什么后面会加–+ 因为这个符号在mysql数据库中是注释符号也可以用#
Select * from ** where username=’admin’ union select version(),database()–+’
这样就把’符号注释掉了
同关卡一 查询表名、列名、用户名密码
第三关(搜索型注入)
方式方法和关卡二一样
第四关(xx型注入)
同上面的关卡一样先判断参数的闭合符
两个报错提示中都包含)字符 又因为我们测试符号中都有’ 所以我们大胆的猜测参数闭合符应该是 ‘)
下面就是传统的操作步骤
第五关(insert/update注入)
本考点在insert和update按照操作界面
先介绍insert方式
抓取数据包
从数据包中的数据我们可以猜测该数据库的操作语句是:
insert into user(name,password,sex,phone,address1,address2) value(‘xxx’,123,1,2,3,4)
name 的闭合方式我们还是要测试的
name 2’报错 name 3” 没有报错
所以大致判断name的闭合方式是’号
接着,我们可以通过报错查询的方式来获取数据库信息
这里使用updataxml()函数
1’ or updatexml(1,concat(0x7e,database()),1) or ’
1’ or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=‘pikachu’)),1) or ’
查询表
再使用update方式
先正常注册一个账号
登录后的界面如下
发现有修改个人信息的功能
从图里我们可以猜测使用了数据库语句
updata sex=’1’ from xxx where name=’a’
也是同样先确定性别参数的闭合符 这就不赘述了’
这里也使用报错注入 函数updatexml()
语句1’ or updatexml(1,concat(0x7e,database()),1) or ’
第六关 delete注入
先留言在删除
抓包删除语句
因为他这个是使用delete数据库函数,我们还是使用报错注入的方式,使用的函数还是updatexml()函数。
还是测试参数id的闭合符号,这里就不截图了通过测试id参数的闭合没有符号
接下来就开始使用updatexml()函数构造payload了
开始我们使用or updatexml(1,concat(0x7e,database()),1)
结果发现成功删除了而且还没有报错
那我们在浏览器中使用该payload,成功了。
经过百度+or+updatexml(1,concat(0x7e,database()),1) 也可以,原来url编码空格变成加号(天调用rest接口的时候,使用URLEncoder编码将空格转为了+号,而rest接口方需要将空格转为%20)
第七关 http header注入
输入正确的用户名和密码登录
登陆后如下图
把我们的ip,user agent,http accept,端口 都显示在界面上
我们可以先抓包看看
抓到两个数据包
发现修改第二包的header时才有用
老步骤先测试闭合符号
闭合符’
我们也不知道这个数据库语句是什么
有可能是select 也有可能是insert
那就测试被select 用order by
测试insert 用datexml成功破防
接下来交给星弟们了
第八关盲注(base on boolian)
这个关卡原理是这样的
假如我要查寻的uname存在,返回的信息是这样的(之前注册的用户)
不存在的显示是这样的
故意加上闭合符号啥的,结果没有数据库报错回显的信息,统一恢复
您输入的username不存在,请重新输入!
但是我们的闭合符号带入sql语句了。这样我们可以通过在参数后面加上判断语句来构成payload
盲注就是没有回显
有两个难点一个是不知道参数的闭合符是哪一种,这个只能和查询语句组合在一起试
a’ and ascii(substr(database(),1,1))=112 #
这样就知道数据库名的第一个字符是p ascii码是112
第九关盲注(base on time)
如果我连正确的username都不知道,这样就没法根据错误提示来判断是自己的用户名错误的还是payload里面查询结果的对错。
但是聪明的hack想到sleep语句的办法把payload里的查询结果对错通过延迟的方式表现出来。
xxx’ and if((substr(database(),1,1))=‘p’,sleep(5),null)#
延迟五秒才有显示可以判断数据库的第一个字符是p
第十关宽字节注入
宽字节注入的具体原理可以百度,我们只简单说一下
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不会被浏览器编码,我们抓包在数据包中构造payload
接着把payload试试,发现确实有。接着就是order by和union select