Dynstr, a cool medium-rated linux box that’s all about DNS (as you probably guessed from the name). It features a web service that allows you to update DNS records on the server. One of the parameters in the request used to update DNS records is vulnerable to command injection, which I exploited to gain code execution on the box.
Inside the box www-data
, 2 local users were identified (dyna
and bindmgr
). Some log files generated by the script
utility were obtained in the home directory of bindmgr
. Going through the log files, I was able to recover an SSH private key for the user bindmgr
, but couldn’t get access as the SSH key is mapped to a specific hostname. After bypassing this, I got access to the box as bindmgr
over SSH, and exploited a custom script to gain code execution as root
.
Info
Recon
NMAP
# Nmap 7.70 scan initiated Tue Oct 5 10:33:02 2021 as: nmap -sC -sV -v -oN namp.txt 10.10.10.244
Increasing send delay for 10.10.10.244 from 0 to 5 due to 14 out of 46 dropped probes since last increase.
Increasing send delay for 10.10.10.244 from 5 to 10 due to 13 out of 43 dropped probes since last increase.
Increasing send delay for 10.10.10.244 from 320 to 640 due to 22 out of 73 dropped probes since last increase.
Nmap scan report for dynstr.htb (10.10.10.244)
Host is up (0.28s 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)
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-methods:
|_ Supported Methods: POST OPTIONS HEAD GET
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Dyna DNS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Oct 5 10:35:42 2021 -- 1 IP address (1 host up) scanned in 160.32 seconds
Web
Web technologies detected by Wappalyzer;
Found a credential in the homepage dynadns:sndanyd
, and an email address dns@dyna.htb
;
Testing the credential on SSH didn’t work, and all of the domains listed above point to the same page.
Running gobuster
in vhost enumeration didn’t yield anything. Directory enumeration yield one hit;
The path has no index file nor directory listing. Bruteforcing with ffuf
discovered another directory;
It appears to be a special path as it handles requests for non-existing paths/files;
This is strange to me so I decided to do some google-fu, and found this at https://www.dynu.com/en-US/Forum/ViewTopic/badauth-being-received/439;
Turns out the URL is used to assign a domain name to an IP address in the DNS server.
Using the above info, I crafted a request for the page using the credentials I obtained from the homepage for the user dynadns
;
Sending the request, I got a new response;
I’m gessing the server is not allowing me to modify the root domain. So with the 3 domains found in the home page of the http://dynstr.htb, I was able to change the DNS records of their subdomains;
I started listeners using netcat
in both TCP and UDP modes, but didn’t get any requests. So I setup a wildcard rule *.dnsalias.htb
to match all subdomains, which works, but I still didn’t get any callbacks;
After resuming testing the next day, I discovered something weird: DNS updates are returning a different IP in response. The IP included in the request was the IP I was assigned the last time I connected to the HTB VPN, and the IP in the response is my current IP;
Going through my previous notes, I realised I made a mistake; I have been passing the IP to map to domain name using the ip
GET parameter, instead of myip
. Changing the parameter worked.
Running out of things to do, I started to fuzz the parameters submitted for the DNS update for injection-related vulnerabilities, and was able to get a new response;
A quick check on my debian host showed nsupdate
is a command line utility for DNS update;
I suspect the web app is passing the hostname
GET parameter without proper validation to a system call to nsupdate
. If exploitable, this will give me a foothold into the server.
Foothold
After discovering a possible command injection flaw in the hostname
GET parameter passed to http://dynstr.htb/nic/update, I tried to gain code execution by joining commands using linux ;
, &&
, and ||
operators. None of them worked. The web app also seems to be checking if the submitted hostname ends with a valid domain, in this case either dnsalias.htb, no-ip.htb, and dynamicdns.htb.
After further testing, I was able to execute code by wrapping it in backtick characters. I got a response after 5 seconds due to the sleep 5
command;
Although the above command worked, multiple simple commands to communicate with my attack host kept failing. Using the ping
command for example, I noticed a delay in response that is appropriate with the number of packets sent when pinging localhost. However, attempts to ping my own host returned a response immediately saying; 911 [wrngdom: 10.14.45`www.dnsalias.htb]
This make me suspicious of some kind of filter used by the web app, so I tried to base64-encode the commands. Using the base64
command-line program, I encoded a curl
command to my attack host and sent it to the web app. It worked!
I then used the above described method to spawn a bash reverse shell;
User
Inside the box as the default www-data
user, I found 2 users named dyna
and bindmgr
. The home directory of dyna
is empty, but that of bindmgr
contains some files, including user flag that is not readable to us;
So I downloaded all the files to my attack host for analysis.
The file command-output-C62796521.txt
showed the output of a failed public key authentication to an sftp
service;
The file strace-C62796521.txt
showed the output of strace
command. This is interesting because strace
is used to trace all system calls made by a program.
The file C62796521-debugging.timing
contains some numbers;
While the file C62796521-debugging.script
contains terminal logs that are likely generated using the script
command;
This is also a very interesting file for me as the console log generated by script
is very neat and will be easier to analyse. Going through the file, I noticed multiple outputs of strace
. Towards the end of the file, the user bindmgr
attempted a public key SSH authentication. Since strace
was executed during the authentication, it captured the system call used by the SSH client to load the SSH private key of the user bindmgr
from disk;
I extracted the key to id_rsa
on my attack host and tried to access the user account of bindmgr, but I got a prompt for password despite passing the private key. Enabling verbose output showed that the public key authentication failed.
I used scriptreplay
and gave it the timing file and the typescript to make sense of what the user was actually doing. It showed the user bindmgr
attempting to download a file from an SSH server using sFTP;
Looking at the authorized_keys
file in bindmgr
’s SSH directory, I noticed that access is allowed only to hosts with the name *.infra.dyna.htb
;
This means I need to map my IP to match the above hostname. Using the nsupdate
utility and the keys inside /etc/bin
, I was able to gain SSH access after lots of googling about nsupdate
;
PrivEsc
User can run a script as root
using sudo
;
The script checks for the file .version
in the current working directory. If it does not exist, it aborts. If it does, it compares it’s value against the .version
file in /etc/bind/named.bindmgr
. If the value in the first .version
file is higher, it copies the version file and any other file in the working directory to /etc/bind/named.bindmgr
;
I noticed the call to cp
uses relative path. So I tried to gain root by tampering with the $PATH
variable to execute a cp
script of my own, which failed;
Since the copy operation is done as root, and all files are included using a wildcard *
, I was able to gain root by copying the bash
binary and giving it the SUID permission, then have the permission retained after the copy operation by creating a file with the name --preserve=mode
, which the cp
command will interpret as a special argument;
Summary
- Found a DNS, SSH, and web service running on the host using
nmap
- Found a credential on the homepage of the web service with username
dynadns
and passwordsndanyd
- Discovered
/nic/update
by bruteforcing withffuf
andgobuster
. Requesting the path showedbadauth
, but passing the credentials discovered previously gives anochg <user-IP>
response. - Some googling showed that
/nic/update
is used to update DNS records, and takes the parametershostname
,myip
, andlocation
. The parameterhostname
was found to be vulnerable to command injection through fuzzing after a response mentioningnsupdate
, which is a command-line tool for updating DNS records, was returned. Base64-encoding allows for more complex commands to be injected. This was exploited to gain a foothold into the box as the web userwww-data
. - Inside the box as
www-data
;- Two users,
binmgr
, anddyna
, were discovered. The home directory ofdyna
is practically empty, while that ofbindmgr
contains the user flag which is not readable, and some interesting files. - The files obtained from the home of
bindmgr
include console logs generated by the linuxscript
utility. The user attempted an SSH public key authentication while runningstrace
, which prints out lots of data on all system calls, which include the contents of the user’s private key as it was read from disk. - Attempts to access the account
bindmgr
using the extracted SSH private key failed. Checking/home/bindmgr/.ssh/authorized_keys
showed that access is limited to hosts that match*.infra.dyna.htb
. Using the key file at/etc/bind/infra.key
and thensupdate
tool, I mapped my IP tohacker.infra.dyna.htb
, which satisfied the SSH requirement, and gave me access to thebindmgr
account, and the user flag.
- Two users,
- Inside the box as
bindmgr
;- The user has permission to run
/usr/local/bin/bindmgr.sh
usingsudo
. - Attempt to hijack the relative call to
cp
made by the script through path tampering failed. - Since a wildcard
*
was used in thecp
command to copy all files, creating a SUID bash binary, and an empty file named--preserve=mode
, which will be matched by the wildcard, and be interpreted by thecp
command as a special argument used to preserve permissions during copy operations, resulted in the copied binary being created with the ownership changed to root but the SUID bits retained, which gave me root access to the box.
- The user has permission to run