← THE INDEX  ·  WRITEUP

AXIS OS dnsupdate.cgi Delete Path Missing Input Validation

The add path validates all input through a dedicated function that rejects shell metacharacters. The delete path skips it entirely, passing raw user input into an nsupdate heredoc.

Summary

The dnsupdate.cgi endpoint on AXIS OS cameras delegates DNS record operations to /usr/sbin/dnsupdate.script. The add command validates every argument through dnsupdate_validate, a strict function that rejects spaces, semicolons, shell metacharacters, and any non-alphanumeric character outside . and -. The delete command calls dnsupdate_delete directly, with no validation at all.

dnsupdate_delete builds an nsupdate command file using an unquoted shell heredoc. Injected spaces alter record types and targets in the generated commands. Newline injection, if deliverable over HTTP, would allow arbitrary DNS records to be created or deleted on the camera's configured DNS server.

Authentication required: admin. Finding extracted from firmware static analysis and simulation; live newline delivery was documented as pending hardware verification at submission time.

Impact

An authenticated admin can inject spaces into the generated nsupdate commands, altering DNS record types and targets. If a literal newline can be delivered through the query string on live hardware, the injection becomes a full DNS record injection: arbitrary update add commands can be inserted, creating records on the camera's DNS server for all downstream clients.

The inconsistency is the core finding: the defensive validation function exists, is correct, and is applied on the add path. The delete path simply omits the call.

Root cause

The vulnerable sink is in dnsupdate_delete (line 116 of dnsupdate.script). The first argument is interpolated unquoted into a heredoc:

cat <<-EOF >> $_tmp
    update delete $1 0 IN A
    update delete $1 0 IN AAAA
    send
EOF

The add handler calls dnsupdate_validate "$@" before calling dnsupdate_add. The delete handler calls dnsupdate_delete "$@" with no preceding validation. The dnsupdate_validate function would reject every injection payload (spaces, semicolons, newlines, shell special characters) because the field must match [.[:alnum:]-]*. Nothing prevents applying that same check before the delete call.

Proof of concept

The following reproduces the finding from extracted firmware. All camera-specific identifiers have been replaced with placeholders.

Proof of concept (continued)

The heredoc simulation below shows how injected spaces alter the generated nsupdate commands.

Disclosure and fix

Reported to the AXIS Security team through their coordinated disclosure process. The one-line fix is to call dnsupdate_validate on the delete path before delegating to dnsupdate_delete:

     delete)
         if [ $# -lt 2 ] || [ $# -gt 3 ]; then
             echo "Usage: $0 delete NAME [IP]" >&2
             exit 1
         fi

         shift 1
+        dnsupdate_validate "$1" "" "all" || exit 1
         dnsupdate_delete "$@" || exit 1
         ;;

Additional hardening: quote $1 in the heredoc (update delete "$1" 0 IN A) and URL-decode input in dnsupdate.cgi before passing to the script, so the validation and the heredoc both operate on the same decoded value.