Jump Ahead: Enum – Initial Shell – User – Root – Resources
Like all machines, we begin by enumerating open ports – finding ports
80 open. Enumerating the webserver, we find a path that we further enumerate to find a file. When we try accessing the file, we receive an error message. Combining the error message with disclosed information we found on the main index page, we learn that we can supply arguments to a command running on the server backend. Fuzzing the arguments for command injection, we find that it is vulnerable. Exploiting the vulnerability, we get a shell on the machine as
www-data. While enumerating the machine locally, we learn that several files potentially house the SSH private key for the
bindmgr user. After updating DNS records, we are able to use the SSH key to log into the machine as
bindmgr – which grants us access to
bindmgr is able to run a script as
root, which is vulnerable to command injection. Exploiting the vulnerability, we are able to get a shell as
root on the machine – allowing access to
Like all machines, we begin by enumerating open ports – finding ports
$ sudo nmap -v -p- --min-rate 3000 $RHOST [...] $ sudo nmap -sV -A -oA enum/nmap/tcp-scripts $RHOST # Nmap 7.91 scan initiated Sat Jun 12 19:33:08 2021 as: nmap -sV -A -oA enum/nmap/tcp-scripts 10.129.125.12 Nmap scan report for 10.129.125.12 Host is up (0.048s latency). Not shown: 997 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 05:7c:5e:b1:83:f9:4f:ae:2f:08:e1:33:ff:f5:83:9e (RSA) | 256 3f:73:b4:95:72:ca:5e:33:f6:8a:8f:46:cf:43:35:b9 (ECDSA) |_ 256 cc:0a:41:b7:a1:9a:43:da:1b:68:f5:2a:f8:2a:75:2c (ED25519) 53/tcp open domain ISC BIND 9.16.1 (Ubuntu Linux) | dns-nsid: |_ bind.version: 9.16.1-Ubuntu 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-server-header: Apache/2.4.41 (Ubuntu) |_http-title: Dyna DNS No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.91%E=4%D=6/12%OT=22%CT=1%CU=43100%PV=Y%DS=2%DC=T%G=Y%TM=60C5527 OS:6%P=x86_64-pc-linux-gnu)SEQ(SP=FF%GCD=1%ISR=108%TI=Z%CI=Z%TS=A)OPS(O1=M5 OS:4DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST11NW7%O OS:6=M54DST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%D OS:F=Y%T=40%W=FAF0%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0 OS:%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF= OS:Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=% OS:RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%I OS:PL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S) Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 23/tcp) HOP RTT ADDRESS 1 50.05 ms 10.10.14.1 2 50.12 ms 10.129.125.12 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Sat Jun 12 19:33:58 2021 -- 1 IP address (1 host up) scanned in 50.56 seconds
nikto, we do not find anything that stands outs. Next, we enumerate directories and files using
gobuster and find a couple directories that seem interesting.
$ for i in files directories; do gobuster dir -t 30 -u $RHOST -w /opt/wordlists/seclists/Discovery/Web-Content/raft-medium-$i.txt; done /assets (Status: 301) [Size: 315] [--> http://10.129.125.12/assets/] /server-status (Status: 403) [Size: 278] /nic (Status: 301) [Size: 312] [--> http://10.129.125.12/nic/]
Further enumerating the directories, we find /
nic/update which sounds notable. Before we start attempting to find a path forward with the information we have, we should manually enumerate the webserver. Going to the main webpage, we learn the site is a dynamic DNS provider.
Looking throughout the webpage, we find a few interesting items. Under the “Services” section, we learn the provider uses the same dynamic DNS API as
https://no-ip.com. Additionally, we are told the dynamic DNS is available for a few domains, and are also given a pair of credentials. Since we have several new FQDNs, we add them to
/etc/hosts for further enumeration.
Attempting to use the credentials on the SSH server, however, does not gain us access. Lastly, since DNS is available over TCP, we attempt to enumerate the domains we’ve gathered, however, we only get 1 result.
Attempting to access the discovered subdomain and previously discovered domains returns the same webpage. This indicates the webserver may not be configured to use virtual hosts.
/nic/update in our browser, we are given a message that says “badauth”.
Since the website disclosed its use of the
no-ip.com Dynamic DNS api, we research “no-ip authentication” to get more information. Based on the message we received, we may be able to use the credentials that were disclosed to authenticate. In our researched, we find documentation on using the credentials we found to log in. Additionally, the documentation details this API call allows us to update DNS records. After using
curl to make the DNS update, we also use
nslookup to verify our changes are made.
Since we are able to presumably supply input to a system command on the remote machine, we decide to test for code/command injection. In our tests, the “;” yielded a “nsupdate” error, so this may likely be a good shell metacharacter to use. For our proof of concept, we try to get a directory listing, but based on the documentation, the responses are fixed.
Since responses may be fixed, a basic out-of-band proof of concept we can perform is to get the machine to send us an ICMP Echo (ping) request. For this, we should also use
tcpdump to monitor the network traffic. Additionally, since we may be executing commands in the shell, we can enclose the injected command in
``. When we do this, we get a response that the first octet of our IP address is dropped, and that it doesn’t match the allowed domains. Since some level of input sansitization is taking place, we attempt to convert the IP address into an integer, and resubmit the request. This time we get a “nsupdate” error, however, we also get the ping requests.
Since this proved we have command injection, we now utilize this vulnerability to get a bash reverse shell as the
Having received a shell as
www-data, the first thing we want to do is enumerate the local machine for paths of privilege escalation. We start manual enumeration, however, do not find anything immediately. Next, we use an automated enumeration script such as
linpeas to do more thorough enumeration. From the script output, we get pointed to potential SSH keys located in a couple files owned by the
/home/bindmgr/support-case-C62796521/strace-C62796521.txt, we find there is indeed a private SSH key we are able to extract from the
read syscall output.
We copy the key, and correctly format it with
echo -e "<key>" on our local machine. When we attempt to use the key to login as
bindmgr, we are denied access. Looking at the
/home/bindmgr/.ssh/authorized_keys file, we see the key is restricted to use from a “*.infra.dyna.htb” subdomain.
From our steps to get access on the machine, we know we are able to manipulate DNS records. To bypass the key restriction, we do more research on
nsupdate. In our research, we find this article that gives examples on setting DNS records using
nsupdate. The article says we will likely need a key file to sign the DNS update, so we attempt to find one using
We find several key files, however,
/etc/bin/infra.key is likely the one we need. Next, we follow the guide to add PTR (reverse-DNS) and A (forward-DNS) records for our host. Since the subdomain does not matter, we used the subdomain
khaotic.infra.dyna.htb. To verify our update was successful, we make DNS queries to the DNS server.
Since our DNS updates worked, we are now able to log into the machine via SSH as
bindmgr, and read
After gaining access to the machine as
bindmgr, we begin to enumerate for additional access. The first command we run is
sudo -l. Once we run this, we see we are able to execute
root without a password.
Looking through the code, we make a couple observations. First, we see we will need to create a
.version file which returns a value greater than that of
$BINDMGR_DIR/.version. Secondly, we observe there is a potential command injection vulnerability with the
cp command the script executes. Particularly, user-generated files can be submitted as command arguments.
Before we attempt to exploit the
cp command, we need to make sure our
.version value is larger, so we attempt to read the value of
$BINDMGR_DIR/.version. When try to read the file, we get an error it doesn’t exist. This, however, is fine, since the error code is still returned. In this case, the returned value is “1”.
Since “1” is the value our
.version file needs to be larger than, we create a file with the value of “2”. Next, we are ready to attempt to exploit the
cp command. Essentially, the
cp command will copy all files in the current directory to
/etc/bind/named.bindmgr/. To exploit this, we can copy
/bin/bash to our directory, and give it the “setuid” permission. Next, we need to create a file named
--preserve=mode, so when our copy of bash is copied, the permissions are left as we set them. This works because the command will treat the filename as a command argument. Once we create the file, we execute the script using
sudo. After checking the
/etc/bind/named.bindmgr/ directory, we find
bash were successfully copied.
Lastly, we execute the copied bash with the “-p” argument to preserve the effective user id (due to setuid). Doing so, we get a shell as
root, and can now read
Thank you for taking the time to read my write-up. I am interested in other ways this machine has been solved. Feel free to reach out to me and we can discuss it. Thanks!