3

Can someone recommend a secure coding guideline for JavaScript?

Is there a set of common vulnerabilities that are closely related to the JavaScript programming language? What I am searching for are equivalent vulnerabilities to stack, heap or buffer overflows which are closely related to the c/c++ programming language.

Can one recommend tools for static code analysis tools within the JavaScript context?

Xander
  • 35,525
  • 27
  • 113
  • 141
Dennis1818
  • 59
  • 1
  • 5
  • 3
    Don't eval user input (goes for every language with eval). Don't use the Function constructor (same reason). Most other web vulnerabilities (e.g. XSS, SQL injection) are not problems with JavaScript code per se. Any linter worth it's salt (JSLint, JSHint, ESLint) will warn you of potentially problematic code (e.g. eval). – Jared Smith Mar 28 '18 at 15:02
  • [This thread](https://stackoverflow.com/questions/194397/how-can-i-obfuscate-protect-javascript) over at Stack Overflow may have the answers you're looking for. –  Mar 28 '18 at 20:07
  • js doesn't really have vulnerabilities (though other areas of the browser reachable by JS might, example flash) and when something with core does popup, like timing attacks, it gets rapidly fixed. In short there's not a lot to scan for; it's all about how the code is used/abused, principally social engineering. – dandavis Mar 28 '18 at 23:51
  • 1
    @dandavis What are you talking about? Look at any recent MSFA. The _majority_ of them are related to JavaScript. Some are exclusively issues with the JS engine, while others "merely" rely on JavaScript to access the interfaces (e.g. WebGL bugs). – forest Mar 29 '18 at 00:35
  • @forest: well, looking at https://www.mozilla.org/en-US/security/advisories/, the last js vuln i see is from 2015: 2015-29. in fact on the whole page, there's only a few JS vulns, ever. Maybe i'm missing something, can you link a recent core vuln (not a crash) or two? core bugs in a basically 20-year old spec would be surprising; there's simply not that much in JS to go wrong (~30 keywords). – dandavis Mar 29 '18 at 01:54
  • @dandavis Most vulnerabilities will be listed as causing crashes "or other unspecified impact". This essentially just means that it's very possibly exploitable but no one wants to put the time into actually finding out if it is or not. CVE-2018-5103 seems to be exploitable through mouse events. – forest Mar 29 '18 at 01:56
  • @forest: mouse event issues are not JS; they are DOM/browser issues. maybe our terms don't match. I stand by JS not having vulns. you say "merely" like it's a bad thing, but it behooves us to be specific and seperate browser bugs (endless) with JS vulns (few and far between). JS can reach most of the buggy browser/extension pieces, but that doesn't mean JS causes the problems. – dandavis Mar 29 '18 at 01:57
  • Perhaps not. By JavaScript vulnerability I mean any vulnerability that requires JavaScript or is related to how it handles input. I don't mean exclusively bugs in the interpreter or JIT compiler itself. Basically any vulnerability where disabling JavaScript would be a complete mitigation. – forest Mar 29 '18 at 01:59
  • @Dennis: You ask several questions at once. While one is IMO on-topic, others definitely aren't. A list of vulnerabilities will never be complete, because we can never be sure that it is up-to-date or this will be maintained. Tools will not be recommended here. A secure coding guideline on the other hand might be something to consider. So you might want to edit your question. – Tom K. Apr 04 '18 at 13:27

2 Answers2

2

Full disclosure: the following guide was written by the research team of Checkmarx, creator of CxSAST (static code analysis tool), where I am employed.

Here is a JavaScript Secure Coding Practices guide:


Since JavaScript is used these days both in front and back ends of applications, a plethora of vulnerabilities and issues are relevant and important to know while developing in JavaScript:

  • Cross Site Scripting (XSS) - Reflected, Stored and DOM based.
  • SQL and NoSQL injections
  • Authentication and password management issues
  • Session management issues
  • Access control issues
  • Unsafe use of cryptography - Hashing, Encryption, Decryption and Random number generators
  • Error Handling and Logging issues

To name a few... :)

yaloner
  • 250
  • 1
  • 6
  • 2
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/116696) – Josef Mar 29 '18 at 11:03
  • You are right. I will add an outline. – yaloner Mar 29 '18 at 20:13
1

I wrote an article about JavaScript vulnerabilities, so I believe I can help here:

Most security vulnerabilities in javascript come as a result of end-user interaction.

Malicious users can input query strings into forms to access or contaminate protected data.

It is, therefore, a responsibility on engineering teams to add a validation middleware on user inputs.

Listed below are the most common JavaScript vulnerabilities:

  • Cross-Site Scripting (XSS)
  • SQL injection (SQLi)
  • Open-source vulnerabilities

Cross-Site Scripting (XSS)

One of the most common attacks involving web applications and JavaScript are Cross-site Scripting vulnerabilities which are included in the OWASP Top 10 web application security risks.

An XSS attack is a flaw in web applications which allow malicious users to execute JavaScript code on a website hence its popularity because almost every website requires JavaScript turned on in users browsers.

Cross-Site Scripting is primarily of two types namely: - Client XSS - Server XSS

Client XSS

This type of vulnerability occurs when untrusted data supplied from a remote location (mostly APIs) is used to update the DOM with an unsafe JavaScript call. As an example, the following snippet below gets weather information from an untrusted API to display current weather information.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>DEMO XSS</title>
</head>
<body>
<p>Today's weather information reads: </br>
<div id="temp"></div>
</p>
<script type="text/javascript">
let untrusted_ajax_res = document.write(location.replace("https://www.w3schools.com"));
document.getElementById("temp").innerHTML=untrusted_ajax_res;
</script>
</body>
</html>
The snippet above shows how malicious code from an untrusted API can be injected into the DOM.
To prevent client xss attacks, developers can install secure xss filters which can be used to sanitise inputs gotten from untrusted domains/locations. A snippet for a web use-case can be seen below:
<!DOCTYPE html>
...
<script src="dist/xss-filters.min.js"></script>
<script>
let untrusted_ajax_res = document.write(location.replace("https://www.w3schools.com"));
document.getElementById("temp").innerHTML=xssFilters.inHTMLData(untrusted_ajax_res);
</script>

-The xss-filters package must only be applied to UTF-8 encoded documents. HTML5 mode is also required.

Server XSS This type of vulnerability occurs when untrusted data is included as user input and sent into the backend to be stored on the database. This data is used to compute a response to be sent back to the user which contains malicious JavaScript code when sent back to the user.

An example of a server XSS attack on an express based node server can be seen in the snippet below:

...
app.get('/search', (req, res) => {
const results = db.search(req.query.product);
if (results.length === 0) {
return res.send('<p>No results found for "' + req.query.product + '"</p>');
}
...
});

The snippet above shows the definition of a products search route for http://www.domain.com. An XSS attack can be performed by passing javascript code as a query for the server like so:

https://www.domain.com/search?product=<script>alert(XSS:Gat Ya!!)</script>

Since there wouldn’t be any record like

<script>alert(XSS:Gat Ya!!)</script>

on the database, the server’s response will be:

<p>No results found for "<script>alert(XSS:Gat Ya!!)</script> </p>

After the server’s response is received and No results found for is displayed, the script is then injected into the DOM to give the output shown below:

enter image description here

Even though this doesn’t look very severe as this script doesn’t pose any serious threat of sort. Attackers, however, can save malicious code as “comments” in blogs/social media sites. These so-called comments, when served to other users, is then injected into the DOM and performs the wishes of the attacker. To fix this vulnerability we can install the xss-filter package using npm like so:

$ npm i xss-filters --save

After installing, we can now filter the user’s input in our server’s response like so:

...
var xssFilters = require('xss-filters');
app.get('/search', (req, res) => {
var productParam = req.query.product;
const results = db.search(req.query.product);
if (results.length === 0) {
res.send('<p>No result found for "' + xssFilters.inHTMLData(productParam) + '"</p>');
}
});
...
  • Using the xss-filters packages comes with certain warnings that can be found on its installation page

SQL Injection

SQL Injection is a type of attack which makes it possible to execute SQL statements to control a database behind a web application. An SQL Injection attack can be seen in the code snippet below:

...
const db = require('./db');
app.get('/products', (req, res) => {
db.query('SELECT * FROM products WHERE id = ' + req.query.id);
.then((product) => {
...
res.send(product);
})
});

There are two things wrong with the code snippet above:

  1. The user’s input which is not to be trusted is directly concatenated with the query string.
  2. The database query is built via string concatenation.

    db.query('SELECT * FROM products WHERE id = $1', req.query.id);

In the snippet above, the database client will pass in the req.query.id as the first argument. Although the MySQL package for node doesn’t support parameterised queries, you can escape users input (i.e remove all special characters ) before it’s concatenated with the query string like so:

const query = 'SELECT * FROM products WHERE id = ' + connection.escape(req.query.id);