T09 · Insecure Skill Coding Practices
- Location
scripts/script.sh:145- Finding
Command Injection Through Dynamically Constructed GNU sed Program
- Content
View full analysis
/dev/null; then sed -i "s|^${key}=.*|${key}=${val}|" "$cfg" ``` ### Technical Analysis The `key` and `val` command-line arguments are embedded directly into a GNU `sed` program. Neither argument is validated or escaped for use in a regular expression, replacement expression, or `sed` command. An attacker can inject the `sed` delimiter and the GNU-specific `e` flag. The `e` flag executes the resulting pattern space through a shell. By first creating a configuration key containing a shell command and then updating that key with a value that terminates the replacement expression, an attacker can cause arbitrary shell commands to run. The use of shell quoting around the overall `sed` argument does not prevent this vulnerability because the injection occurs in the language interpreted by `sed`, rather than through initial shell word splitting. ### Attack Path 1. The attacker must be able to invoke the Skill and control the arguments supplied to the `config` command. 2. The attacker creates a configuration key whose text is also a valid shell command, with a comment marker preventing the remainder from affecting execution: ```bash scripts/script.sh config 'touch /tmp/ledger-pwned #' seed ``` 3. This creates the following configuration entry: ```text touch /tmp/ledger-pwned #=seed ``` 4. The attacker updates the same key with a value that closes the replacement field, enables GNU `sed` execution, and comments out the final delimiter: ```bash scripts/script.sh config 'touch /tmp/ledger-pwned #' 'x|e;#' ``` 5. The dynamically generated `sed` expression replaces the matching line with text beginning with: ```text touch /tmp/ledger-pwned #=x ``` 6. GNU `sed` processes the injected `e ...[truncated 772 chars]- Remediation
View remediation
&2 return 1 fi ``` 2. Replace the dynamic `sed` expression with a parser that treats the key and value strictly as data. A temporary file can be generated with `awk`, followed by an atomic rename. 3. If `awk` is used, pass values through `-v` rather than concatenating them into program source. 4. Reject or safely encode newline characters in configuration values. 5. Write the replacement file in the same directory, apply mode `600`, and atomically rename it over the original. 6. Add regression tests using `sed` delimiters, regular-expression metacharacters, semicolons, newlines, and GNU `sed` flags in both key and value arguments. ]]>
