Most Common Security Vulnerabilities Using JavaScript

Most Common Security Vulnerabilities Using JavaScript

JavaScript is undoubtedly the most popular programming language for web development. A survey by Stack Overflow shows that over 67% of professional developers use JavaScript. Additionally, it is used by more than 95% of websites on the web. 

 

From a security perspective, JavaScript is fourth on the list of the most vulnerable languages – only behind Java, PHP, and C. For this reason, developers must remain proactive and defensive in securing their JavaScript applications to keep the web safe.

 

This post dives into common JavaScript vulnerabilities, the risks they pose, and how developers can address these vulnerabilities to keep their web applications secure. 

 

Cross-Site Scripting

 

According to OWASP, cross-site scripting (XSS) is one of the most widespread security risks in web applications. It occurs when an attacker injects malicious code into the client-side of an application. This normally happens when an application accepts untrusted (or user-supplied) data on a web page without escaping or validating it properly.

 

A successful XSS attack occurs when the browser executes the malicious scripts from in a manner determined by the threat actor. Generally, XSS attacks will require some form of interaction from the victim, either through social engineering or request to visit a particular page. 

 

If an attacker exploits XSS vulnerabilities, they could perform malicious actions like account tampering, data theft, remote control, or even malware distribution.

 

To prevent XSS attacks, developers should separate untrusted data or user input from the active browser content. In JavaScript, you can achieve this by:

 

  • Validating and sanitizing input from users to ensure it only contains acceptable characters that cannot be used to launch XSS attacks.

 

  • Using safe methods such as innerText for manipulating the DOM. Unlike innerHTML, this method escapes dangerous content, thereby preventing DOM-based XSS.

 

  • Using frameworks that automatically escape XSS vulnerabilities by design. For instance, Node JS has the encodeURI and encodeURIComponent global functions that help prevent XSS attacks. You should also consider using advanced packages like the xss-filters .

 

The following code snippet shows how to use XSS filters from the npm package in express applications.

 

 

SQL Injection

 

SQL databases are vulnerable to injection attacks where query parameters are exploited to execute arbitrary instructions. 

 

Below is an express framework router that is vulnerable to an SQL injection attack:

 

 

In the example above, the application gets user IDs from URLs and retrieves the corresponding email address by querying the database. Two things are wrong in the code snippet.

 

First, the database query is built using a string concatenation. The second issue is that the user input is concatenated to the query instead of being handled as untrusted data.

 

An attacker might craft a query string id parameter in such a way that it retrieves all tables or writes into the database. For instance, when the attacker supplies these string parameters:

 

 

This would result to a query like this one:

 

 

When this query is executed successfully, it would pull the list of all tables in the databases. An attacker can then retrieve any information they want.

 

To mitigate SQL injections, developers should always perform proper input validation. When input from the user fails the validation checks, the SQL query is not executed.

 

Another way of preventing SQL injection is using parameterized queries or prepared statements instead of concatenations. Parameterized queries are used to abstract the SQL syntax from the input parameters.

 

In the example below, a prepared statement, which is Java’s implementation of parameterized queries, is used to prevent potential SQL injection attacks.

 

 

Sensitive cookie exposure

 

The client-side script on every browser can access all the content returned by an application to the server. This includes cookies that often contain sensitive data such as session IDs. 

 

Exposing session identifiers, whether in URLs, error messages, or logs is a bad practice that opens up an application to security issues like cross-site request forgery(CSRF), session hijacking and session fixation.

 

To prevent this, developers must consistently use HTTPS and implement HTTP-Only cookies. The HTTP-Only attribute in cookies tells the browser to prevent cookie access through the DOM. By doing this, client-side script attacks are prevented from accessing sensitive data stored in cookies.

 

Another way of securing user sessions is opting by per-requests as opposed to using per-session identifiers. Any time the client requests privileged access permissions, terminate the session and re-authenticate them before granting access.

 

Here is an example cookie that uses Express – Node.js and stores session data on the SQLite database using the connect-sqlite3 package. Notice how we use HTTP only secure cookies.

 

 

Components with known vulnerabilities

 

There are tons of security risks associated with the use of vulnerable application components. For instance, vulnerabilities in some libraries or other elements such as browser plugin code are a security loophole in your applications. 

 

To ensure the components you’re using do not compromise your application’s security, always keep up with the current versions of all. Do not rely on unpatched components for building or integrating into your web application.

 

Another security concern is re-using JavaScript code from open source directories such as GitHub. When you copy code from a random user and re-use it in your application without auditing it, you might introduce security issues in your application.

 

Instead, exercise caution and inspect every component of your application. You do not want to use any broken code that comes your way, or even worse, code with intentionally malicious scripts.

 

Putting it all together

 

Adopting good coding practices can secure applications against common JavaScript vulnerabilities on both the client-side and server-side. When using JavaScript, always follow the following key guidelines for enhanced security:

 

  • Never trust user input
  • Use proper encoding/escaping
  • Sanitize user input
  • Define a content security policy
  • Set secure cookies
  • Secure API keys on the client-side
  • Encrypt data transmitted between the client and the server
  • Use secure components and APIs for development
  • Use updated libraries and frameworks
  • Conduct regular scans on your codebase

 

Following these best coding practices is usually the first step for securing your web applications.

Michael Hollander

Michael Hollander / About Author

Michael is a Senior Product Manager and the Data Protection Officer at WhiteSource. Before joining WhiteSource, Michael was a Product Manager at GE Digital, and he previously held a number of software development positions spanning over 10 years. Michael is currently leading WhiteSource for Developers, a suite of native developer integrations empowering developers to secure products faster without slowing down development. LinkedIn | Twitter