Skip to content

fix: [cisco_firesight_manager_ACL_rule_export] shell-escape interpolated values in generated script - #895

Open
elhoim wants to merge 1 commit into
MISP:mainfrom
elhoim:fix/082-firesight-acl-shell-escape
Open

fix: [cisco_firesight_manager_ACL_rule_export] shell-escape interpolated values in generated script#895
elhoim wants to merge 1 commit into
MISP:mainfrom
elhoim:fix/082-firesight-acl-shell-escape

Conversation

@elhoim

@elhoim elhoim commented Aug 31, 2026

Copy link
Copy Markdown
Member

The generated Cisco fireSIGHT export .sh script interpolates config fields and event data directly into single-quoted shell strings:

output += "FIRESIGHT_IP_ADDR='{}'\n".format(config["fmc_ip_addr"])

output += "LOGINPASS_BASE64=`echo -n '{}:{}' | base64`\n".format(config["fmc_login"], config["fmc_pass"])
output += "DOMAIN_ID='{}'\n".format(config["domain_id"])
output += "ACPOLICY_ID='{}'\n\n".format(config["acpolicy_id"])
...
BLOCK_RULE='{{ "action": "BLOCK", ... "name": "{rule_name}", ... "newComments": [ "{event_info_comment}" ] }}'

Any of these values — a config field, or event_info_comment built from the MISP event — is attacker- or operator-influenced text placed inside a single-quoted shell literal. A single quote in the value closes the quoting early, and the rest of the string is then interpreted as shell syntax rather than data.

Also, config was referenced unconditionally later in handler() even though it was only assigned inside if "config" in request:, causing a NameError (referenced-before-assignment) whenever the request omitted config.

Impact: An analyst who exports and runs the generated .sh script against their fireSIGHT Management Center executes attacker-influenced shell commands if any interpolated value (a config setting or event/attribute data feeding into the rule comment) contains a single quote.

Fix: Every interpolated value — the four config fields and the fully-assembled JSON access-rule block — is now passed through shlex.quote() before being written into the script, so a single quote can no longer break out of the quoting. config is also initialized to {} up front, fixing the referenced-before-assignment bug.

This is a pure hardening fix with no intended behaviour change: for benign values (no shell metacharacters), shlex.quote() produces an equivalent quoted string, so existing exported scripts behave identically.

Verification

  • flake8 clean (exit 0); py_compile ok
  • 161 passed, 4 skipped, 5 subtests passed in 77.38s (0:01:17)

Found during a review of the repository; other findings are being submitted as separate PRs.

🤖 Generated with Claude Code

https://claude.ai/code/session_018dfYpyaSZd1nxSRLr8suj8

…ted values in generated script

The module builds a shell script that authenticates to and calls the Cisco
fireSIGHT manager API, interpolating the module config (IP, login,
password, domain/policy IDs) and attribute values (destination IPs, URLs,
event info) directly into single-quoted shell strings. Any of those
values containing a single quote breaks out of the quoting, so an
attacker-controlled attribute value (e.g. an ip-dst or url attribute with
a `'` in it) can inject arbitrary shell commands into the exported .sh
file, which an analyst may run unmodified. Separately, `config` was only
assigned inside `if "config" in request:` but read unconditionally right
after, raising a NameError whenever the request carries no "config" key.

Every value written into the generated script is now passed through
shlex.quote(). For the JSON access-rule block, which embeds several
attribute values inside one shell-quoted assignment, the JSON content is
built as plain text first and the whole assembled string is shlex-quoted
once, since quoting the individual sub-values would leave stray quote
characters inside the outer quoted string. `config` is initialised to
`{}` before the conditional assignment so referencing it never raises a
NameError.

Verified with flake8 (clean) and the full pytest suite against a live
misp-modules server: 161 passed, 4 skipped, 5 subtests passed, matching
the baseline.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018dfYpyaSZd1nxSRLr8suj8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant