A remote shell in a camera you forgot was on the network
Qihoo 360 D603-2, D600-2, D606-6, and D706 smart cameras running firmware up to 6.4.9 contain an OS command injection in the testspeed_command function of /fs2/bin/iscm. An attacker can manipulate the host argument to inject arbitrary shell commands, leading to remote code execution on the camera's embedded Linux OS.
The vendor rates this CRITICAL 10.0, but the real-world severity is tempered by the fact that these are four specific consumer/SMB camera models, not enterprise infrastructure. Most deployments sit behind NAT or cloud relay, so direct internet exposure is low. However, the vulnerability requires no authentication, has low complexity, and a public exploit exists with no vendor patch — so any exposed or flat-network camera is an immediate foothold. Assessed as HIGH, not Critical, because the affected population is narrow and the device is not a high-value asset, but unauthenticated RCE with no patch demands quick segmentation.
4 steps from start to impact.
Find a reachable Qihoo 360 camera
- Network access to the camera's management interface or LAN
- Camera not isolated by VLAN/firewall
- Most cameras are behind NAT/firewall, not directly internet-facing
- Cloud relay does not directly expose the local
/fs2/bin/iscmbinary
Send crafted speed-test request
host parameter containing shell metacharacters (e.g., ; rm -rf /tmp/x;). The testspeed_command function passes the parameter to a shell without sanitization, triggering command injection.- No authentication required (per CVSS)
- Vulnerable firmware ≤6.4.9
- Attacker can reach the vulnerable endpoint
- Some deployments may have disabled the speed-test feature or blocked the endpoint
- WAF/IPS may flag obvious command injection patterns if traffic is inspected
Achieve OS command execution as root
- Injection is not blocked by input validation
- Camera process has sufficient privileges (root)
- None if the endpoint is reachable and unpatched—this step is reliable once exploit is public
Pivot, exfiltrate video, or join botnet
- Camera resides on a network with other reachable hosts
- Outbound network from camera allows command-and-control
- VLAN segmentation limits lateral movement
- If the camera is on an isolated IoT VLAN, impact is contained to video/audio
/fs2/bin/iscm from untrusted sources. Deploy within 30 days.- Traditional antivirus or EDR on the camera — embedded Linux devices rarely have agents; no protection.
- Blocking inbound internet only — outbound reverse shells still work if camera can reach attacker.
- Firmware signature verification — this is a separate issue; it doesn't mitigate command injection.
The supporting signals.
| In-the-wild status | No known active exploitation or CISA KEV listing as of 2026-11-04 |
|---|---|
| PoC availability | Public exploit exists per disclosure; no named GitHub repos or researchers confirmed in search results |
| EPSS score | EPSS score not populated for this CVE; likelihood of exploitation is moderate given public PoC but no observed mass scanning |
| KEV status | Not listed in CISA KEV |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — assumes direct network access and changed scope; actual scope may be lower if camera isolated |
| Affected versions | Qihoo 360 D603-2, D600-2, D606-6, D706 firmware ≤6.4.9 |
| Fixed versions | None published; vendor contacted but did not respond |
| Scanning/exposure data | No GreyNoise/Shodan fingerprint confirmed; typical IP camera internet exposure is <5% for these consumer models |
| Disclosure date | 2026-11-04 |
| Reporting researcher/org | Not named in public record; VulDB submission |
Sources.
Why this verdict
- Friction audit: Unauthenticated remote, but requires direct network path; most cameras are NAT'd, so reachable population is small.
- Role multiplier: Device is a low-value IoT camera; compromise yields camera shell/video, not domain/fleet/identity impact. No high-value role floor triggered because these models are not canonical high-value components (not in IdP/hypervisor/edge class).
- Public exploit + no patch: Exploit is public and vendor unresponsive, so exposed devices are at immediate risk; keeps severity above medium.
Why not higher?
Not Critical because the affected product line is a set of consumer/SMB smart cameras with limited enterprise deployment and low internet exposure. The high-value role catalog doesn't apply; worst plausible outcome is camera compromise/pivot, not domain takeover or fleet-scale supply chain.
Why not lower?
Not Medium because the vulnerability is unauthenticated, low complexity, and has a public exploit with no vendor patch. If one of these cameras is exposed or on a flat enterprise network, it provides an immediate foothold for lateral movement.
Crowdsourced verification payload.
Run on a network scanner host with access to the camera management VLAN. Pass one or more IP addresses as arguments; the script probes HTTP/HTTPS root pages and attempts to fingerprint Qihoo 360 camera firmware. No root required; requires outbound TCP 80/443 to targets. Example: python3 check_cve-2026-121607.py 192.168.1.10 192.168.1.11
#!/usr/bin/env python3
import sys, http.client, ssl, re
def check_host(ip, port=80, use_ssl=False):
try:
conn = http.client.HTTPConnection(ip, port, timeout=5) if not use_ssl else http.client.HTTPSConnection(ip, port, timeout=5, context=ssl._create_unverified_context())
conn.request("GET", "/", headers={"User-Agent":"Mozilla/5.0"})
resp = conn.getresponse()
body = resp.read(1024).decode(errors='ignore')
conn.close()
# Look for Qihoo 360 camera signatures and firmware version
if 'Qihoo' in body or '360' in body or 'D603' in body or 'D600' in body or 'D606' in body or 'D706' in body:
m = re.search(r'firmware[^\d]*(\d+\.\d+(?:\.\d+)?)', body, re.I)
if m:
ver = m.group(1)
if tuple(map(int, ver.split('.'))) <= (6,4,9):
return 'VULNERABLE'
else:
return 'PATCHED'
else:
return 'UNKNOWN'
else:
return 'UNKNOWN'
except Exception:
return 'UNKNOWN'
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: python3 check_cve-2026-121607.py <ip> [ip ...]")
sys.exit(2)
vulnerable = False
for ip in sys.argv[1:]:
result = check_host(ip)
if result == 'VULNERABLE':
vulnerable = True
print(f"{ip}: {result}")
sys.exit(0 if vulnerable else 1)