-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathCommandInjection.inc.qhelp
More file actions
63 lines (50 loc) · 2.2 KB
/
CommandInjection.inc.qhelp
File metadata and controls
63 lines (50 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Code that passes untrusted user input directly to
<code>child_process.exec</code> or similar APIs that execute shell commands
allows the user to execute malicious code.</p>
</overview>
<recommendation>
<p>If possible, use hard-coded string literals to specify the command to run.
Instead of interpreting the user input directly as a shell command, examine the
user input and then choose among hard-coded string literals.</p>
<p>If the applicable libraries or commands cannot be determined until runtime,
then add code to verify that the user input string is safe before using it.</p>
<p>If possible, use APIs that don't run shell commands, and accept command arguments
as an array of strings rather than a single concatenated string. This is both safer and more portable.</p>
<p>In the latter case, if you are given the arguments as a single string, note
that it is not safe to simply split the string on whitespace, since an argument
may contain quoted whitespace which would cause it to be split into multiple
arguments. Instead, use a library such as <code>shell-quote</code> to parse the
string into an array of arguments.</p>
</recommendation>
<example>
<p>The following example shows code that extracts a filename from an HTTP query
parameter that may contain untrusted data, and then embeds it into a shell
command to count its lines without examining it first.</p>
<sample src="examples/command-injection.js" />
<p>A malicious user can exploit this code to execute arbitrary shell commands by
passing a filename like <code>foo.txt; rm -rf .</code>, which will first count
the lines in <code>foo.txt</code> and then delete all files in the current
directory.</p>
<p>To avoid this catastrophic loophole, use an API like
<code>child_process.execFileSync</code> that does not spawn a shell by
default:</p>
<sample src="examples/command-injection_fixed.js" />
</example>
<references>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
</li>
<li>
npm:
<a href="https://www.npmjs.com/package/shell-quote">shell-quote</a>.
</li>
<!-- LocalWords: CWE untrusted unsanitized Runtime
-->
</references>
</qhelp>