T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/run_monitor.py:34
- Finding
- Shell Command Injection Through Unsanitized Portfolio Input<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_monitor.py`, lines 34-40 **Vulnerability Type**: OS command injection **Risk Level**: High ### Vulnerable Code ```python elif choice == '3': code = input("股票代码: ") cost = input("成本价: ") qty = input("数量: ") os.system(f"python portfolio.py add {code} --cost {cost} --qty {qty}") elif choice == '4': code = input("股票代码: ") os.system(f"python portfolio.py remove {code}") ``` ### Technical Analysis Values read from `code`, `cost`, and `qty` are interpolated directly into command strings passed to `os.system`. This function invokes a system shell, so shell metacharacters contained in any of these values are interpreted as command syntax rather than as literal arguments. The program does not restrict stock codes to the expected numeric format and does not ensure that cost and quantity values are valid positive numbers before constructing the command. Consequently, any user or process able to supply interactive input can append an additional shell command. This vulnerability does not itself elevate privileges. Injected commands execute with the same operating-system privileges, environment, filesystem access, and credentials as the user running the monitor. ### Attack Path 1. A victim launches `scripts/run_monitor.py`. 2. The attacker supplies input directly, through a wrapper, or through a manipulated terminal/input stream. 3. The attacker selects the add or remove operation. 4. A stock-code value containing a shell command separator is entered, such as: - POSIX shell: `600000; id` - Windows command shell: `600000 & whoami` 5. The application constructs a command containing the injected separator. 6. `os.system` passes the complete string to the system shell. 7. The shell runs both the intended portfolio operation and the injected command with the victim's privileges. ### Impact Assessment Successful exploitation provides arbitrary command execution in the context ...[truncated 566 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Avoid invoking a shell. Use `subprocess.run` with an argument list, the current Python interpreter, and an absolute script path: ```python import re import subprocess from pathlib import Path SCRIPT_DIR = Path(__file__).resolve().parent PORTFOLIO_SCRIPT = SCRIPT_DIR / "portfolio.py" def validate_code(value: str) -> str: value = value.strip() if not re.fullmatch(r"\d{6}", value): raise ValueError("The stock code must contain exactly six digits.") return value code = validate_code(input("Stock code: ")) cost = float(input("Cost: ")) qty = int(input("Quantity: ")) if cost <= 0 or qty <= 0: raise ValueError("Cost and quantity must be positive.") subprocess.run( [ sys.executable, str(PORTFOLIO_SCRIPT), "add", code, "--cost", str(cost), "--qty", str(qty), ], check=True, ) ``` Apply equivalent validation to remove operations. Do not attempt to fix this solely by escaping shell characters; eliminating the shell is more reliable. Handle conversion and subprocess errors explicitly so invalid input cannot produce a partially executed operation. ]]>
