clawd/memory/shannon-scan-2026-02-14/deliverables/ssrf_exploitation_evidence.md

285 lines
13 KiB
Markdown

# SSRF Exploitation Evidence
## Executive Summary
This report documents the comprehensive exploitation testing of one Server-Side Request Forgery (SSRF) vulnerability candidate identified during the analysis phase. After exhaustive testing and verification, the finding has been reclassified as a **FALSE POSITIVE** for SSRF vulnerability.
**Key Finding:** The OAuth Dynamic Client Registration vulnerability (SSRF-VULN-01) was initially classified as SSRF but is actually an **Open Redirect vulnerability**. The server does not make outbound HTTP requests to attacker-controlled destinations; instead, it redirects the client's browser using HTTP 303 status codes. This does not meet the definition of Server-Side Request Forgery.
**Exploitation Status:**
- Successfully Exploited: 0
- Potential Vulnerabilities: 0
- False Positives: 1
## Successfully Exploited Vulnerabilities
*No SSRF vulnerabilities were successfully exploited.*
## Potential Vulnerabilities (Validation Blocked)
*No potential SSRF vulnerabilities requiring further investigation.*
## False Positive Analysis
### SSRF-VULN-01: OAuth Dynamic Client Registration - Open Redirect (NOT SSRF)
**Summary:**
- **Vulnerable location:** POST /register (unauthenticated), GET /oauth/authorize (authenticated)
- **Initial Classification:** Server-Side Request Forgery (SSRF) with internal service access capability
- **Corrected Classification:** Open Redirect vulnerability
- **Reason for Reclassification:** The server uses `http.Redirect()` which sends an HTTP 303 response to the client's browser, not a server-side HTTP request to the target URL
- **SSRF Criteria:** ❌ FAILED - Server does not make outbound HTTP requests to attacker-controlled destinations
**Detailed Analysis:**
The vulnerability allows unauthenticated attackers to register OAuth clients with arbitrary redirect URIs, including internal network addresses. However, the exploitation mechanism does not match the definition of SSRF:
**What Actually Happens:**
1. Attacker registers OAuth client with malicious redirect_uri (e.g., `http://169.254.169.254/latest/meta-data/`)
2. Attacker (or victim) initiates OAuth authorization flow
3. Server generates authorization code
4. **Server sends HTTP 303 redirect response to the CLIENT'S BROWSER**
5. Client's browser attempts to navigate to the internal URL (and fails from external network)
**What Does NOT Happen (SSRF behavior):**
- ❌ Server does not make HTTP requests to the redirect_uri
- ❌ Server does not establish connections to internal services
- ❌ Server does not access internal network resources
- ❌ Server does not leak internal service responses back to the attacker
**Code Evidence:**
File: `/repos/inou-portal/portal/oauth.go:139`
```go
http.Redirect(w, r, redirectURL.String(), http.StatusSeeOther)
```
This function sends an HTTP 303 status code with a `Location` header - it does NOT make an outbound request. The Go documentation confirms:
> "Redirect replies to the request with a redirect to url, which may be a path relative to the request path. The provided code should be in the 3xx range and is usually StatusMovedPermanently, StatusFound or StatusSeeOther."
**Exploitation Attempts:**
#### Attempt 1: Register OAuth Client with AWS Metadata Endpoint
**Objective:** Force server to access AWS EC2 instance metadata service
**Method:**
```http
POST /register HTTP/1.1
Host: inou.com
Content-Type: application/json
```
**Result:**
```json
HTTP/1.1 201 Created
Content-Type: application/json
{
"client_id": "243f06b1598fb12d49c862ba047b9d1e",
"client_secret": "b3cec86e5fdf34ddde72a35d945eddb57ec6a985d2dc808e55c42420032cee3f",
"redirect_uris": [
"http://169.254.169.254/latest/meta-data/iam/security-credentials/"
],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"token_endpoint_auth_method": "client_secret_post"
}
```
**Outcome:** ✅ Client registration successful - No validation of redirect_uri against internal IP ranges
---
#### Attempt 2: Trigger OAuth Authorization Flow
**Objective:** Force server to make HTTP request to AWS metadata endpoint
**Prerequisites:**
- Valid user session (obtained via passwordless authentication with backdoor code 250365)
- Registered malicious OAuth client from Attempt 1
**Method:**
```http
GET /oauth/authorize?client_id=243f06b1598fb12d49c862ba047b9d1e&redirect_uri=http%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data%2Fiam%2Fsecurity-credentials%2F&response_type=code&state=test HTTP/1.1
Host: inou.com
Cookie: login=6a484f3f85735a03
```
**Server Response:**
```http
HTTP/1.1 303 See Other
Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/?code=4f4f3e67fcf804ce05487c18fdaee6f5b354ecb467f834d9747285369a4b31d7&state=test
Content-Type: text/html; charset=utf-8
Content-Length: 177
```
**Analysis:**
- Server returned HTTP 303 redirect (client-side redirect)
- **Server did NOT make an HTTP request to 169.254.169.254**
- Server did NOT receive or return data from the metadata service
- Browser attempted to navigate to the internal URL (network error from client side)
**Outcome:** ❌ NOT SSRF - This is an Open Redirect vulnerability, not server-side request forgery
---
#### Attempt 3: Register Additional Clients for Internal Services
**Objective:** Test if different internal targets yield server-side requests
**Targets Tested:**
1. **Internal API Server:** `http://127.0.0.1:8082/api/access`
- Client ID: 9863b518919c5c11532b2775e81a0b82
- Registration: ✅ Successful
2. **Signal RPC Service:** `http://192.168.1.16:8080/api/v1/rpc`
- Client ID: 96478c7a51bc4447f2a54cf6c30ae970
- Registration: ✅ Successful
3. **DICOM Viewer:** `http://localhost:8765/viewer`
- Client ID: afb78106315871695217d878f6c8b6b9
- Registration: ✅ Successful
**Result:** All clients successfully registered with internal network targets, confirming complete lack of redirect URI validation. However, all subsequent authorization flows resulted in the same behavior: HTTP 303 client-side redirects, not server-side HTTP requests.
**Outcome:** ❌ NOT SSRF - Consistent client-side redirect behavior across all internal targets
---
#### Attempt 4: Search for Alternative SSRF Sinks
**Objective:** Identify any code paths where the server actually makes outbound HTTP requests with user-controlled URLs
**Code Review Findings:**
1. **Google Gemini API Integration** (`/repos/inou-portal/lib/llm.go:109`)
- URL construction: `fmt.Sprintf("https://generativelanguage.googleapis.com/v1beta/models/%s:generateContent?key=%s", *config.Model, GeminiKey)`
- User control: ❌ NONE - Model parameter never populated from user input
- Verdict: Not exploitable
2. **Signal Messaging RPC** (`/repos/inou-portal/lib/signal.go:10`)
- Endpoint: `const signalAPI = "http://192.168.1.16:8080/api/v1/rpc"`
- User control: ❌ NONE - Hardcoded destination
- Verdict: Not exploitable
3. **Internal API Proxy** (`/repos/inou-portal/portal/api_proxy.go:22`)
- Endpoint: `const apiBackend = "http://127.0.0.1:8082"`
- User control: ❌ NONE - Hardcoded destination
- Verdict: Not exploitable
4. **SMTP Email Delivery** (`/repos/inou-portal/lib/email.go`)
- Configuration: Loaded from environment file
- User control: ❌ NONE - Administrative configuration only
- Verdict: Not exploitable
**Outcome:** ❌ No true SSRF sinks identified - All outbound HTTP requests use hardcoded or configuration-based destinations
---
**SSRF vs Open Redirect - Technical Distinction:**
| Characteristic | SSRF | Open Redirect (This Vulnerability) |
|---|---|---|
| **Server Behavior** | Server makes HTTP request to attacker-controlled URL | Server sends HTTP 3xx redirect to client |
| **Request Origin** | Server's network context | Client's network context |
| **Access to Internal Services** | Yes - server can reach internal networks | No - client cannot reach internal networks from external position |
| **Data Exfiltration** | Yes - server returns internal service responses | No - server never sees internal service data |
| **Network Boundary Bypass** | Yes - server is inside the network | No - redirect fails from external client |
| **HTTP Status Codes** | 200 OK (or error from internal service) | 303 See Other (redirect to client) |
**Why This Matters for Classification:**
The analysis phase correctly identified that the application allows arbitrary redirect URIs to be registered without validation. However, the **exploitation mechanism** does not meet the SSRF threat model:
- **SSRF Definition:** Server-Side Request Forgery occurs when an attacker can cause the server to make HTTP requests to arbitrary destinations, leveraging the server's network position and credentials.
- **This Vulnerability:** The server generates a redirect response (HTTP 303) that instructs the client's browser to navigate to an arbitrary URL. The server itself never makes the request.
**Attempted Bypass Techniques:**
To ensure thorough testing, the following bypass attempts were made to see if the redirect could be leveraged into true SSRF:
1.**Multiple Protocol Tests:** Tried `file://`, `gopher://`, `ftp://` - All accepted in registration but still result in client-side redirects
2.**Redirect Chaining:** Attempted to chain redirects to see if server would follow - No server-side request initiated
3.**DNS Rebinding Simulation:** Cannot be tested externally, but would not matter since redirect is client-side
4.**SSRF via Request Smuggling:** OAuth flow doesn't involve request parsing that could be smuggled
**Actual Security Impact:**
While not SSRF, this vulnerability still has security implications:
1. **Open Redirect Risk:** Attackers can redirect users to phishing sites via trusted inou.com domain
2. **OAuth Code Leakage:** If an attacker can register a client with their own domain, they receive the authorization code when users authorize
3. **Network Topology Disclosure:** Error messages and timing differences may reveal which internal IPs/ports exist
4. **Authorization Code in URL:** Codes appear in URL parameters of the redirect, violating OAuth security best practices (should use POST-based flows for sensitive redirects)
**Recommended Fix:**
While this is not SSRF, the underlying vulnerability (unrestricted redirect URIs) should still be fixed:
```go
// In /repos/inou-portal/portal/mcp_http.go, before line 131:
func validateRedirectURI(uri string) error {
parsed, err := url.ParseRequestURI(uri)
if err != nil {
return fmt.Errorf("invalid URI format: %w", err)
}
// Require HTTPS for all redirect URIs
if parsed.Scheme != "https" {
return fmt.Errorf("only HTTPS redirect URIs allowed")
}
// Block private IP ranges
if ip := net.ParseIP(parsed.Hostname()); ip != nil {
if ip.IsPrivate() || ip.IsLoopback() || ip.IsLinkLocalUnicast() {
return fmt.Errorf("private/internal IP addresses not allowed")
}
}
// Domain allowlist for production
allowedDomains := []string{"claude.ai", "anthropic.com"}
hostname := strings.ToLower(parsed.Hostname())
allowed := false
for _, domain := range allowedDomains {
if hostname == domain || strings.HasSuffix(hostname, "."+domain) {
allowed = true
break
}
}
if !allowed {
return fmt.Errorf("redirect domain not in allowlist")
}
return nil
}
```
**Conclusion:**
After exhaustive exploitation attempts across multiple attack vectors and internal targets, I have determined with high confidence that **SSRF-VULN-01 is a FALSE POSITIVE for SSRF classification**. The vulnerability is correctly identified as a lack of redirect URI validation, but the exploitation mechanism (HTTP 303 client-side redirect) does not allow server-side network boundary bypass or internal service access.
The vulnerability should be reclassified as:
- **Type:** Open Redirect + OAuth Security Misconfiguration
- **Severity:** Medium (was incorrectly rated High for SSRF impact)
- **Exploitability:** High (unauthenticated registration, no validation)
- **Impact:** Phishing, OAuth code theft, but NOT internal network access
**Exploitation Classification Decision Framework Applied:**
> "Is this preventing factor a security implementation designed to stop this attack, or an external operational constraint?"
**Answer:** Neither. The "prevention" is the fundamental design of HTTP redirects - they are client-side by definition in the HTTP specification (RFC 7231). This is not a security control that could be bypassed; it's the architectural reality of how `http.Redirect()` functions.
The correct classification is: **FALSE POSITIVE** - The vulnerability does not enable Server-Side Request Forgery.