Summary
The builtin directive templates for the shell-backed platforms interpolate the unauthenticated query target into a command string that is executed by a POSIX shell. A shell metacharacter in the query target breaks out of the intended argument, so a single unauthenticated POST /api/query can run arbitrary OS commands on the managed router as the SSH login user.
Version
v2.0.0 through current main (v2.0.4).
Affected platforms
Backends whose command string is parsed by a shell:
- FRR, BIRD, OpenBGPD — mapped to
device_type="linux_ssh", so netmiko delivers the command to a host bash shell.
- TNSR — the directive runs
dataplane shell sudo vtysh -c "...", which drops to a host shell.
The non-shell NOS platforms (Cisco/Arista/Juniper/Nokia/Huawei/MikroTik/VyOS) are not shell-injectable, but an embedded newline in the target survives netmiko's rstrip-only normalize_cmd and is executed as a second CLI line.
Root cause
Two things combine:
Construct.format() substitutes the target with a bare str.format() — no shell escaping:
# hyperglass/execution/drivers/_construct.py
return command.format(target=self.target, mask=mask, **attrs)
with templates like 'vtysh -c "show bgp ipv4 unicast regexp {target}"'.
- The default
condition="*" rule compiles to re.compile(".+").match() (hyperglass/models/directive.py), which is start-anchored and matches any non-empty string, so no shell metacharacter is rejected.
A " in the target closes the quote and a following ; / ` / $(...) reaches bash. OpenBGPD's template (bgpctl show rib inet as {target}) is unquoted, so a bare ; injects directly.
Steps to Reproduce
- Deploy hyperglass with an FRR (or BIRD/OpenBGPD/TNSR) device — the default builtin
BGP AS Path directive.
- Send an unauthenticated query whose target contains a shell metacharacter, e.g. a
queryTarget of:
- The constructed command becomes
vtysh -c "show bgp ipv4 unicast regexp _65000"; id; echo "", and bash executes the injected id.
Expected Behavior
The query target should be treated as a single, literal argument to the device command; shell metacharacters in it should have no effect beyond (at most) failing to match.
Observed Behavior
The injected command executes on the router host. The HTTP response still returns the legitimate show bgp output, so the injection is not visible in the query result.
Fix
Proposed in #382 — shell-quote the target at construction for shell-backed platforms, and reject ASCII control characters at the query model (for the newline vector on non-shell platforms).
Summary
The builtin directive templates for the shell-backed platforms interpolate the unauthenticated query target into a command string that is executed by a POSIX shell. A shell metacharacter in the query target breaks out of the intended argument, so a single unauthenticated
POST /api/querycan run arbitrary OS commands on the managed router as the SSH login user.Version
v2.0.0 through current
main(v2.0.4).Affected platforms
Backends whose command string is parsed by a shell:
device_type="linux_ssh", so netmiko delivers the command to a host bash shell.dataplane shell sudo vtysh -c "...", which drops to a host shell.The non-shell NOS platforms (Cisco/Arista/Juniper/Nokia/Huawei/MikroTik/VyOS) are not shell-injectable, but an embedded newline in the target survives netmiko's
rstrip-onlynormalize_cmdand is executed as a second CLI line.Root cause
Two things combine:
Construct.format()substitutes the target with a barestr.format()— no shell escaping:'vtysh -c "show bgp ipv4 unicast regexp {target}"'.condition="*"rule compiles tore.compile(".+").match()(hyperglass/models/directive.py), which is start-anchored and matches any non-empty string, so no shell metacharacter is rejected.A
"in the target closes the quote and a following;/`/$(...)reaches bash. OpenBGPD's template (bgpctl show rib inet as {target}) is unquoted, so a bare;injects directly.Steps to Reproduce
BGP AS Pathdirective.queryTargetof:vtysh -c "show bgp ipv4 unicast regexp _65000"; id; echo "", and bash executes the injectedid.Expected Behavior
The query target should be treated as a single, literal argument to the device command; shell metacharacters in it should have no effect beyond (at most) failing to match.
Observed Behavior
The injected command executes on the router host. The HTTP response still returns the legitimate
show bgpoutput, so the injection is not visible in the query result.Fix
Proposed in #382 — shell-quote the target at construction for shell-backed platforms, and reject ASCII control characters at the query model (for the newline vector on non-shell platforms).