You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+8-7
Original file line number
Diff line number
Diff line change
@@ -18,18 +18,19 @@ Add the following to your `.eslintrc` file:
18
18
]
19
19
```
20
20
21
-
22
21
## Developer guide
23
22
24
23
- Use [GitHub pull requests](https://help.github.com/articles/using-pull-requests).
25
24
- Conventions:
26
-
- We use our [custom ESLint setup](https://github.com/nodesecurity/eslint-config-nodesecurity).
27
-
- Please implement a test for each new rule and use this command to be sure the new code respects the style guide and the tests keep passing:
28
-
```sh
29
-
npm run-script cont-int
30
-
```
25
+
- We use our [custom ESLint setup](https://github.com/nodesecurity/eslint-config-nodesecurity).
26
+
- Please implement a test for each new rule and use this command to be sure the new code respects the style guide and the tests keep passing:
27
+
28
+
```sh
29
+
npm run-script cont-int
30
+
```
31
31
32
32
### Tests
33
+
33
34
```sh
34
35
npm test
35
36
```
@@ -58,7 +59,7 @@ More information: [Avoiding Command Injection in Node.js](docs/avoid-command-inj
58
59
59
60
Detects `object.escapeMarkup = false`, which can be used with some template engines to disable escaping of HTML entities. This can lead to Cross-Site Scripting (XSS) vulnerabilities.
60
61
61
-
More information: [OWASP XSS](https://www.owasp.org/index.php/Cross-site_Scripting_(XSS))
62
+
More information: [OWASP XSS](<https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)>)
Copy file name to clipboardExpand all lines: docs/avoid-command-injection-node.md
+9-9
Original file line number
Diff line number
Diff line change
@@ -15,15 +15,15 @@ child_process.exec('ls', function (err, data) {
15
15
What happens though when you need to start getting user input for arguments into your command? The obvious solution is to take the user input and build your command out using string concatenation. But here's something I've learned over the years: When you use string concatenation to send data from one system to another you're probably going to have a bad day.
16
16
17
17
```js
18
-
var path ="user input";
18
+
var path ='user input';
19
19
child_process.exec('ls -l '+ path, function (err, data) {
20
20
console.log(data);
21
21
});
22
22
```
23
23
24
24
## Why is string concatenation a problem?
25
25
26
-
Well, because under the hood, `child_process.exec`makes a call to execute <kbd>/bin/sh</kbd> rather than the target program. The command that was sent just gets passed along as a shell command in the newly spawned <kbd>/bin/sh</kbd> process. `child_process.exec` has a misleading name - it's a bash interpreter, not a program launcher. And that means that all shell metacharacters can have devastating effects if the command is including user input.
26
+
Well, because under the hood, `child_process.exec` makes a call to execute <kbd>/bin/sh</kbd> rather than the target program. The command that was sent just gets passed along as a shell command in the newly spawned <kbd>/bin/sh</kbd> process. `child_process.exec` has a misleading name - it's a bash interpreter, not a program launcher. And that means that all shell metacharacters can have devastating effects if the command is including user input.
27
27
28
28
```sh
29
29
[pid 25170] execve("/bin/sh", ["/bin/sh", "-c", "ls -l user input"], [/* 16 vars */]
@@ -42,9 +42,9 @@ Let's modify our example to use `execFile` and `spawn` and see how the system ca
@@ -61,8 +61,8 @@ Similar example using `spawn` instead.
61
61
```js
62
62
var child_process = require('child_process');
63
63
64
-
var path = "."
65
-
var ls = child_process.spawn('/bin/ls', ['-l', path])
64
+
var path = '.';
65
+
var ls = child_process.spawn('/bin/ls', ['-l', path]);
66
66
ls.stdout.on('data', function(data) {
67
67
console.log(data.toString());
68
68
});
@@ -80,6 +80,6 @@ This does however come with a caveat: using `spawn` or `execFile` is not always
80
80
81
81
So, here's the collective guidance for running system commands from node.js:
82
82
83
-
* Avoid using `child_process.exec`, and never use it if the command contains any input that changes based on user input.
84
-
* Try to avoid letting users pass in options to commands if possible. Typically values are okay when using spawn or execfile, but selecting options via a user controlled string is a bad idea.
85
-
* If you must allow for user controlled options, look at the options for the command extensively, determine which options are safe, and whitelist only those options.
83
+
- Avoid using `child_process.exec`, and never use it if the command contains any input that changes based on user input.
84
+
- Try to avoid letting users pass in options to commands if possible. Typically values are okay when using spawn or execfile, but selecting options via a user controlled string is a bad idea.
85
+
- If you must allow for user controlled options, look at the options for the command extensively, determine which options are safe, and whitelist only those options.
Copy file name to clipboardExpand all lines: docs/regular-expression-dos-and-node.md
+14-14
Original file line number
Diff line number
Diff line change
@@ -2,13 +2,13 @@
2
2
3
3
Imagine you are trying to buy a ticket to your favorite JavaScript conference, and instead of getting the ticket page, you instead get `500 Internal Server Error`. For some reason the site is down. You can't do the thing that you want to do most and the conference is losing out on your purchase, all because the application is unavailable.
4
4
5
-
Availability is not often treated as a security problem, which it is, and it's impacts are immediate, and deeply felt.
5
+
Availability is not often treated as a security problem, which it is, and it's impacts are immediate, and deeply felt.
6
6
7
7
The attack surface for Node.js in regards to loss of availability is quite large, as we are dealing with a single event loop. If an attacker can control and block that event loop, then nothing else gets done.
8
8
9
9
There are many ways to block the event loop, one way an attacker can do that is with [Regular Expression Denial of Service (ReDoS)](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS).
10
10
11
-
If user provided input finds it's way into a regular expression, or a regular expression is designed with certain attributes, such as grouping with repetition, you can find yourself in a vulnerable position, as the regular expression match could take a long time to process. [OWASP](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS) has a deeper explanation of why this occurs.
11
+
If user provided input finds it's way into a regular expression, or a regular expression is designed with certain attributes, such as grouping with repetition, you can find yourself in a vulnerable position, as the regular expression match could take a long time to process. [OWASP](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS) has a deeper explanation of why this occurs.
12
12
13
13
Let's look at an vulnerable example. Below we are attempting the common task of validating an email address on the server.
14
14
@@ -24,19 +24,19 @@ With the example above, we can use this test script to show how bad input can im
Copy file name to clipboardExpand all lines: docs/the-dangers-of-square-bracket-notation.md
+17-26
Original file line number
Diff line number
Diff line change
@@ -4,36 +4,33 @@ We are going to be looking at some peculiar and potentially dangerous implicatio
4
4
5
5
Square bracket notation for objects in JavaScript provides a very convenient way to dynamically access a specific property or method based on the contents of a variable. The end result of this feature is something that is very similar to Ruby's Mass Assignment: Given an object, you are able to dynamically assign and retrieve properties of this object without specifying this property should be accessible.
6
6
7
-
*Note: These examples are simple, and seemingly obvious - we will take a look at that later. For now, disregard the practicality of the examples and focus on the dangerous patterns that they reveal.*
7
+
_Note: These examples are simple, and seemingly obvious - we will take a look at that later. For now, disregard the practicality of the examples and focus on the dangerous patterns that they reveal._
8
8
9
9
Let's take a look at why this could be a problem.
10
10
11
11
### Issue #1: Bracket object notation with user input grants access to every property available on the object.
12
12
13
13
```js
14
-
exampleClass[userInput[1]] = userInput[2]
14
+
exampleClass[userInput[1]] = userInput[2];
15
15
```
16
16
17
17
I won't spend much time here, as I believe this is fairly well known. If exampleClass contains a sensitive property, the above code will allow it to be edited.
18
18
19
-
### Issue #2: Bracket object notation with user input grants access to every property available on the object, __*including prototypes.*__
19
+
### Issue #2: Bracket object notation with user input grants access to every property available on the object, **_including prototypes._**
20
20
21
21
```js
22
-
userInput = [
23
-
'constructor',
24
-
'{}'
25
-
]
26
-
exampleClass[userInput[1]] = userInput[2]
22
+
userInput = ['constructor', '{}'];
23
+
exampleClass[userInput[1]] = userInput[2];
27
24
```
28
25
29
-
This looks pretty innocuous, even if it is an uncommon pattern. The problem here is that we can access or overwrite prototypes such as `constructor` or `__defineGetter__`, which may be used later on. The most likely outcome of this scenario would be an application crash, when a string is attempted to be called as a function.
26
+
This looks pretty innocuous, even if it is an uncommon pattern. The problem here is that we can access or overwrite prototypes such as `constructor` or `__defineGetter__`, which may be used later on. The most likely outcome of this scenario would be an application crash, when a string is attempted to be called as a function.
30
27
31
-
### Issue #3: Bracket object notation with user input grants access to every property available on the object, including prototypes, __*which can lead to Remote Code Execution.*__
28
+
### Issue #3: Bracket object notation with user input grants access to every property available on the object, including prototypes, **_which can lead to Remote Code Execution._**
32
29
33
30
Now here's where things get really dangerous. It's also where example code gets really implausible - bear with me.
34
31
35
32
```js
36
-
varuser=function() {
33
+
varuser=function() {
37
34
this.name='jon';
38
35
//An empty user constructor.
39
36
};
@@ -44,24 +41,18 @@ function handler(userInput) {
44
41
}
45
42
```
46
43
47
-
In the previous section, I mentioned that constructor can be accessed from square brackets. In this case, since we are dealing with a function, the constructor we get back is the `Function` Constructor, which compiles a string of code into a function.
44
+
In the previous section, I mentioned that constructor can be accessed from square brackets. In this case, since we are dealing with a function, the constructor we get back is the `Function` Constructor, which compiles a string of code into a function.
48
45
49
46
### Exploitation:
50
47
51
-
In order to exploit the above code, we need a two stage exploit function.
48
+
In order to exploit the above code, we need a two stage exploit function.
0 commit comments