Server-side Request Forgery (SSRF) Affecting mindsdb package, versions [,23.12.4.2)


Severity

Recommended
0.0
high
0
10

CVSS assessment made by Snyk's Security Team. Learn more

Threat Intelligence

Exploit Maturity
Proof of concept
EPSS
0.08% (38th percentile)

Do your applications use this vulnerable package?

In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.

Test your applications

Snyk Learn

Learn about Server-side Request Forgery (SSRF) vulnerabilities in an interactive lesson.

Start learning
  • Snyk IDSNYK-PYTHON-MINDSDB-7919087
  • published6 Sept 2024
  • disclosed5 Sept 2024
  • creditSim4n6

Introduced: 5 Sep 2024

CVE-2024-24759  (opens in a new tab)
CWE-918  (opens in a new tab)

How to fix?

Upgrade MindsDB to version 23.12.4.2 or higher.

Overview

MindsDB is a MindsDB server, provides server capabilities to mindsdb native python library

Affected versions of this package are vulnerable to Server-side Request Forgery (SSRF) through the is_private_url function. An attacker can manipulate DNS responses to redirect traffic to malicious sites or local IP addresses by exploiting the DNS rebinding technique.

PoC

from flask import Flask, request, jsonify
from urllib.parse import urlparse
import socket
import ipaddress
import requests

app = Flask(__name__)


def is_private_url(url: str):
    """
    Raises exception if url is private

    :param url: url to check
    """

    hostname = urlparse(url).hostname
    if not hostname:
        # Unable to find hostname in url
        return True
    ip = socket.gethostbyname(hostname)
    if ipaddress.ip_address(ip).is_private:
        raise Exception(f"Private IP address found for {url}")


@app.route("/", methods=["GET"])
def index():
    return "http://127.0.0.1:5000/check_private_url?url=https://www.google.Fr"


@app.route("/check_private_url", methods=["GET"])
def check_private_url():
    url = request.args.get("url")

    if not url:
        return jsonify({"error": 'Missing "url" parameter'}), 400

    try:
        is_private_url(url)
        response = requests.get(url)

        return jsonify(
            {
                "url": url,
                "is_private": False,
                "text": response.text,
                "status_code": response.status_code,
            }
        )
    except Exception as e:
        return jsonify({"url": url, "is_private": True, "error": str(e)})


if __name__ == "__main__":
    app.run(debug=True)

References

CVSS Scores

version 4.0
version 3.1