ShopDB Security Audit Report

Date
September 12, 2026
Duration
3 hours 13 minutes
Cost
$60.42
Methodology
Cloudflare Glasswing

Executive Summary

A comprehensive 8-stage vulnerability discovery audit was conducted against the ShopDB manufacturing asset management system using the Glasswing methodology (Recon, Hunt, Validate, Gapfill, Dedupe, Trace, Feedback, Report). The audit discovered 7 confirmed exploitable vulnerabilities across authentication, authorization, cryptography, and resource management domains.

7
Confirmed Vulnerabilities
3
HIGH Severity
100%
Reachable
19%
Confirmation Rate

Risk Breakdown

Severity Count Risk Level
HIGH 3 Critical attention required
MEDIUM 3 Important but lower priority
LOW 1 Informational

Confirmed Vulnerabilities

HIGH CWE-345 1. Agent Binary Injection
Description

The agent binary upload endpoint accepts ANY Windows PE executable without code signing or publisher verification. A compromised operator with endpoints.agentpackage + endpoints.agentupdate permissions can upload and deploy malicious binaries that execute as SYSTEM across the entire Windows endpoint fleet.

Location

plugins/endpoints/api/agentupload.py:127-131

Attack Chain
  1. POST /api/endpoints/siteagent/binaries/agent with malicious PE (only checks for "MZ" header)
  2. Binary staged to instance/siteagent/agent/<version>/shopdbagent.exe
  3. Packaged as Application object in database
  4. POST /api/endpoints/<asset_id>/agentupgrade to push to endpoints
  5. PowerShell script executes with Unblock-File (bypasses SmartScreen) and runs as SYSTEM
Vulnerable Code
def looks_like_pe(data):
    """Whether data begins with the Windows PE 'MZ' magic."""
    return len(data) >= 2 and data[:2] == _PE_MAGIC
Impact
  • Complete fleet compromise
  • SYSTEM-level code execution on all Windows endpoints
  • Persistence via Windows service replacement
  • Active bypass of OS-level protections (SmartScreen)
Remediation
  • Immediate: Implement Authenticode signature verification
  • Short-term: Maintain SHA256 whitelist of approved binaries
  • Long-term: Implement two-person rule (separate upload/deploy permissions)
  • Defense-in-depth: Remove Unblock-File from upgrade script
HIGH CWE-204 2. Account Enumeration via Lockout Disclosure
Description

The login endpoint leaks valid usernames through observable HTTP status code and message differences. Locked accounts return HTTP 403 "Account is locked", while invalid usernames return HTTP 401 "Invalid username or password".

Location

shopdb/core/api/auth.py:102-107

Attack Vector
  1. Make 5-6 failed login attempts with candidate username
  2. Observe response: 401 → 403 transition indicates valid username
  3. Per-IP rate limiting (30 req/5min) allows ~5 username tests per window per IP
Impact
  • Username enumeration enables targeted password attacks
  • Reduces credential brute-force search space
  • Undermines username anonymity security assumption
Remediation
  • Always return HTTP 401 "Invalid username or password" regardless of account state
  • Enforce lockout post-password-check to eliminate timing differences
  • Implement constant-time response strategy
Validation: Successfully reproduced against live target at http://192.168.100.1:5173
HIGH CWE-208 3. Collector API Key Timing Attack
Description

Collector API key authentication uses Python's == operator for string comparison instead of constant-time comparison (hmac.compare_digest). This allows byte-by-byte extraction of COLLECTOR_API_KEY via timing side-channel attacks.

Location

shopdb/core/api/collector.py:135-137

Vulnerable Code
# Line 135 - Non-constant-time comparison
if expected_key and api_key == expected_key \
        and not _env_fallback_disabled(pluginname):
    return None
Correct Usage (Found Elsewhere)
# setup.py:65, usb plugin, endpoints plugin
if hmac.compare_digest(expected, provided):
    # Constant-time comparison
Impact
  • Full API key extraction enables unauthenticated access to collector endpoints
  • Create/update assets without authentication
  • Inject false telemetry data
Remediation
import hmac
# Replace line 135 with:
if expected_key and hmac.compare_digest(api_key, expected_key) \
        and not _env_fallback_disabled(pluginname):
    return None
MEDIUM CWE-613 4. Refresh Token Non-Rotation
Description

The /refresh endpoint does not rotate refresh tokens when issuing new access tokens. A compromised refresh token remains valid for 30 days and can be reused unlimited times.

Location

shopdb/core/api/auth.py:160-186

Impact
  • Stolen refresh token provides 30-day persistent access
  • No revocation mechanism (only full account deactivation)
  • Unlimited token generation enables log pollution
Remediation
  • Implement refresh token rotation (issue new refresh token with each refresh)
  • Implement JTI-based token blacklist
  • Add rate limiting to /refresh endpoint
  • Reduce refresh token lifetime to 7 days
MEDIUM CWE-770 5. Token Refresh Rate Limit Bypass
Description

The /api/auth/refresh endpoint lacks rate limiting. In contrast, /api/auth/login implements fixed-window rate limiting (30 req/5min). Successfully executed 100 token refresh requests in 3.8 seconds (26.3 req/s).

Location

shopdb/core/api/auth.py:160-186

Impact
  • DoS via database query spam
  • Log pollution hinders forensic analysis
  • Enables rapid token generation for distributed attacks
Remediation
# Add rate limiting decorator
@auth_bp.route('/refresh', methods=['POST'])
@limiter.limit("10 per minute")
@jwt_required(refresh=True)
def refresh():
    ...
MEDIUM CWE-307 6. File Upload DoS
Description

File upload endpoints lack rate limiting. An authenticated user with upload permissions can repeatedly upload large files (up to 256MB per request) without throttling.

Location

shopdb/config.py:145-151

Affected Endpoints
  • /api/endpoints/siteagent/binaries/<binkey>
  • /api/applications/<app_id>/package
  • Others identified in Hunt Round 4
Impact
  • Disk exhaustion (repeated 128-256MB uploads)
  • Memory exhaustion (file processing)
  • Amplifies other upload vulnerabilities
Remediation
from flask_limiter import Limiter

@upload_bp.before_request
@limiter.limit("10 per hour")
def rate_limit_uploads():
    pass
LOW CWE-362 7. Race Condition in Event Deduplication
Description

Event deduplication check-then-insert (TOCTOU) race allows duplicate EndpointEvent records. Concurrent collector POSTs can both bypass the deduplication check, causing IntegrityError that aborts the entire transaction and loses ALL telemetry in the batch.

Location

plugins/endpoints/plugin.py:1259-1278

Impact
  • Transaction rollback loses state updates AND other events
  • Defense-in-depth mechanism becomes failure mode under load
Remediation
# Option 1: Row-level locking
rows = db.session.query(...)
    .with_for_update()  # Acquire row locks
    .all()

# Option 2: PostgreSQL ON CONFLICT
INSERT INTO endpointevent (...) VALUES (...)
ON CONFLICT (assetid, eventchannel, eventrecordid) DO NOTHING;

Additional Findings

40 unvalidated findings discovered in Hunt Round 4 (budget exhausted before validation). Based on historical false positive rates (80% rejection), approximately 8 of these 40 may be real vulnerabilities.

Categories:

Remediation Priority

Timeline Vulnerability Action
Week 1
(Immediate)
#1: Agent Binary Injection Implement Authenticode signature verification
Week 1
(Immediate)
#2: Account Enumeration Fix constant-time responses (always 401)
Week 1
(Immediate)
#3: Timing Attack Replace == with hmac.compare_digest()
Weeks 2-4
(Short-term)
#5: Rate Limit Bypass Add rate limiting to /refresh endpoint
Weeks 2-4
(Short-term)
#4: Token Non-Rotation Implement refresh token rotation
Weeks 2-4
(Short-term)
#6: Upload DoS Add rate limiting to upload endpoints
Month 2+
(Long-term)
#7: Race Condition Implement SELECT FOR UPDATE or ON CONFLICT

Audit Methodology

Stages Completed
  1. Recon: Mapped 10 subsystems, 11 entry points
  2. Hunt Round 1-3: 31 tasks, 36 potential findings
  3. Validate Round 1-3: 7 confirmed, 29 rejected (19% confirmation rate)
  4. Gapfill 1-2: Identified coverage gaps, added 16 tasks
  5. Dedupe: Grouped into 7 unique vulnerabilities
  6. Trace: All 7 confirmed reachable from attacker input
  7. Feedback: Generated 39 additional hunt tasks
  8. Hunt Round 4: 39 tasks, 40 findings (unvalidated, budget exhausted)
Adversarial Validation

Each finding was challenged by a second AI agent attempting to disprove it. Only 19% of initial findings survived validation (7 confirmed, 29 rejected as false positives). This high rejection rate demonstrates the effectiveness of adversarial validation in eliminating false positives.

Recommendations

  1. Fix immediate vulnerabilities (Week 1 priority)
  2. Add security testing to CI/CD pipeline
  3. Periodic audits - quarterly recommended
  4. Code review focus - constant-time comparisons, rate limiting patterns
  5. Budget for Round 4 validation - $20 to validate 40 additional findings