VAITP Dataset

← Back to the dataset

CVE-2023-41329

WireMock proxy mode DNS rebinding vulnerability

  • CVSS 6.6
  • CWE-290 Authentication Bypass by Spoofing
  • Race Conditions
  • Remote

WireMock is a tool for mocking HTTP services. The proxy mode of WireMock, can be protected by the network restrictions configuration, as documented in Preventing proxying to and recording from specific target addresses. These restrictions can be configured using the domain names, and in such a case the configuration is vulnerable to the DNS rebinding attacks. A similar patch was applied in WireMock 3.0.0-beta-15 for the WireMock Webhook Extensions. The root cause of the attack is a defect in the logic which allows for a race condition triggered by a DNS server whose address expires in between the initial validation and the outbound network request that might go to a domain that was supposed to be prohibited. Control over a DNS service is required to exploit this attack, so it has high execution complexity and limited impact. This issue has been addressed in version 2.35.1 of wiremock-jre8 and wiremock-jre8-standalone, version 3.0.3 of wiremock and wiremock-standalone, version 2.6.1 of the python version of wiremock, and versions 2.35.1-1 and 3.0.3-1 of the wiremock/wiremock Docker container. Users are advised to upgrade. Users unable to upgrade should either configure firewall rules to define the list of permitted destinations or to configure WireMock to use IP addresses instead of the domain names.

CVSS base score
6.6
Published
2023-09-06
OWASP
A10 Server Side Request Forgery (SSRF)
Orthogonal defect classification
Timing/Serialization
Code defect classification
Timing Issues
Category
Race Conditions
Subcategory
Race Condition in File Operations
Accessibility scope
Remote
Impact
Denial of Service (DoS)
Fixed by upgrading
Yes

Solution

Upgrade to WireMock version 2.35.1 or higher.

Vulnerable code sample

import socket
import requests

class WireMockProxy:
    def __init__(self, allowed_domains):
        self.allowed_domains = allowed_domains

    def is_domain_allowed(self, domain):
        return domain in self.allowed_domains

    def proxy_request(self, target_domain, request_data):
        if not self.is_domain_allowed(target_domain):
            raise ValueError("Domain not allowed for proxying")

        target_ip = socket.gethostbyname(target_domain)

        response = requests.post(f"http://{target_ip}/proxy", json=request_data)
        return response

allowed_domains = ["example.com", "api.example.com"]
proxy = WireMockProxy(allowed_domains)

try:
    response = proxy.proxy_request("example.com", {"key": "value"})
    print(response.json())
except ValueError as e:
    print(e)

Patched code sample

import socket
import ipaddress
import requests

class WireMockProxy:
    def __init__(self, allowed_domains):
        self.allowed_domains = allowed_domains

    def is_domain_allowed(self, domain):
        return domain in self.allowed_domains

    def check_ip(self, ip):
        try:
            ip_obj = ipaddress.ip_address(ip)
            return not (ip_obj.is_private or ip_obj.is_loopback or ip_obj.is_reserved or ip_obj.is_multicast or ip_obj.is_link_local)
        except ValueError:
            return False

    def proxy_request(self, target_domain, request_data):
        if not self.is_domain_allowed(target_domain):
            raise ValueError("Domain not allowed for proxying")

        target_ip = socket.gethostbyname(target_domain)

        if not self.check_ip(target_ip):
            raise ValueError("Resolved IP is not allowed")

        response = requests.post(f"http://{target_domain}/proxy", json=request_data)
        return response

allowed_domains = ["example.com", "api.example.com"]
proxy = WireMockProxy(allowed_domains)

try:
    response = proxy.proxy_request("example.com", {"key": "value"})
    print(response.json())
except ValueError as e:
    print(e)

Cite this entry

@misc{vaitp:cve202341329,
  title        = {{WireMock proxy mode DNS rebinding vulnerability}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2023},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2023-41329},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2023-41329/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::