|
2 | 2 | "-//Semmle//qhelp//EN" |
3 | 3 | "qhelp.dtd"> |
4 | 4 | <qhelp> |
5 | | -<overview> |
6 | | -<p>Code that passes user input directly to |
7 | | -<code>require('child_process').exec</code>, or some other library |
8 | | -routine that executes a command, allows the user to execute malicious |
9 | | -code.</p> |
10 | 5 |
|
| 6 | +<overview> |
| 7 | +<p>Code that passes untrusted user input directly to |
| 8 | +<code>child_process.exec</code> or similar APIs that execute commands by |
| 9 | +spawning a shell allows the user to execute malicious code.</p> |
11 | 10 | </overview> |
12 | | -<recommendation> |
13 | 11 |
|
14 | | -<p>If possible, use hard-coded string literals to specify the command to run |
15 | | -or library to load. Instead of passing the user input directly to the |
16 | | -process or library function, examine the user input and then choose |
17 | | -among hard-coded string literals.</p> |
| 12 | +<recommendation> |
| 13 | +<p>If possible, use hard-coded string literals to specify the command to run. |
| 14 | +Instead of interpreting the user input directly as a shell command, examine the |
| 15 | +user input and then choose among hard-coded string literals.</p> |
18 | 16 |
|
19 | | -<p>If the applicable libraries or commands cannot be determined at |
20 | | -compile time, then add code to verify that the user input string is |
21 | | -safe before using it.</p> |
| 17 | +<p>If the applicable libraries or commands cannot be determined until runtime, |
| 18 | +then add code to verify that the user input string is safe before using it.</p> |
22 | 19 |
|
| 20 | +<p>If possible, prefer APIs that run the commands directly rather than via a |
| 21 | +shell, and that accept command arguments as an array of strings rather than a |
| 22 | +single concatenated string. This is both safer and more portable.</p> |
23 | 23 | </recommendation> |
24 | | -<example> |
25 | 24 |
|
26 | | -<p>The following example shows code that takes a shell script that can be changed |
27 | | -maliciously by a user, and passes it straight to <code>child_process.exec</code> |
28 | | -without examining it first.</p> |
| 25 | +<example> |
| 26 | +<p>The following example shows code that extracts a filename from an HTTP query |
| 27 | +parameter that may contain untrusted data, and then embeds it into a shell |
| 28 | +command to count its lines without examining it first.</p> |
29 | 29 |
|
30 | 30 | <sample src="examples/command-injection.js" /> |
31 | 31 |
|
| 32 | +<p>A malicious user can exploit this code to execute arbitrary shell commands by |
| 33 | +passing a filename like <code>foo.txt; rm -rf .</code>, which will first count |
| 34 | +the lines in <code>foo.txt</code> and then delete all files in the current |
| 35 | +directory.</p> |
| 36 | + |
| 37 | +<p>To avoid this potentially catastrophic loophole, use an API like |
| 38 | +<code>child_process.execFileSync</code> that does not spawn a shell by |
| 39 | +default:</p> |
| 40 | + |
| 41 | +<sample src="examples/command-injection_fixed.js" /> |
32 | 42 | </example> |
33 | | -<references> |
34 | 43 |
|
| 44 | +<references> |
35 | 45 | <li> |
36 | 46 | OWASP: |
37 | 47 | <a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>. |
38 | 48 | </li> |
39 | | - |
40 | 49 | <!-- LocalWords: CWE untrusted unsanitized Runtime |
41 | 50 | --> |
42 | | - |
43 | 51 | </references> |
| 52 | + |
44 | 53 | </qhelp> |
0 commit comments