As with any programming language, JavaScript has fair its share of potential security exposures. Exploiting a JavaScript vulnerability can allow you to manipulate and steal data, redirect sessions and lots more. Whilst JavaScript is normally thought of as a client-side application, JavaScript security issues can also create problems on the server-side.
Vulnerabilities in JavaScript Source Code
Because JavaScript is an interpreted, not a compiled, language, it would be virtually impossible to protect application code from being examined by potential hackers with this method. Nonetheless, obfuscation is still a good practice, as it may slow down the hackers in their reverse-engineering attempts.
A major cause of security holes in the source code is the widespread use of public packages and libraries. NPM, a lead player in the JavaScript ecosystem, offers more than a million packages in its registry. Although the variety offered is appealing to developers, this also means potential exposure to a huge number of hidden vulnerabilities in these packages that are installed in web application projects.
Indeed, developers often install packages even for the simplest tasks, thus expanding their project dependencies and this can have other far-reaching consequences.
Monitoring and addressing all potential application dependency vulnerabilities can be very time-consuming, auditing tools can be used help to automate and accelerate the process.
Typical approaches for preventing JavaScript security issues in source code can include: –
- Improving awareness of best practices among developers
- Proper auditing of application code to detect potential vulnerabilities
- Writing unit tests not only to ensure that code behaves as expected, but also that it executes securely
- Implementing tools to scan applications dynamically and identify JavaScript security issues in third-party packages and libraries
Unintended JavaScript Execution
Most unintended script execution attacks involve cross-site scripting (XSS). A particular concern related to JavaScript is the way it interacts with the Document Object Model (DOM) on a web page, which allows scripts to be embedded and executed on client computers across the web.
A basic XSS attack scenario is often seen on forum websites in which users can see each other’s messages on the page. If HTML or JavaScript are not properly encoded when they are part of a message, this could enable unscrupulous users to post malicious script as messages.
To prevent XSS attacks, code should be sanitised with a combination of escaping, filtering, and validating data strings, when handling user inputs
Escaping/Encoding User Input in JavaScript
XSS attacks rely on supplying data that contains certain special characters that are used in the underlying HTML, JavaScript, or CSS of a web page. When the browser is rendering the web page and encounters these characters, it sees them as part of the code of the web page rather than a value to be displayed. This is what allows the attacker to break out of a text field and supply additional browser-side code that is executed.
To prevent this, any time browser-supplied data inputs will be returned in a response (whether immediately reflected or retrieved from a database), these special characters should be replaced with escape codes for those characters.
Filtering Inputs in JavaScript
In some situations, it might be preferable to just remove dangerous characters from the data input. This can provide some degree of protection but should not be relied on alone for protection from data manipulation. There are various techniques attackers can use to evade such filters.
Input Validation in JavaScript
Browser-supplied inputs should be validated to ensure they only contains expected characters. For instance, phone number fields should only be allowed to contain numbers and perhaps a dash or parentheses characters. Input containing characters outside the expected set should be immediately rejected. These filters should be set up to look for acceptable characters and reject everything else.
Client-Side Validation
While all of the methods discussed above are good and work well in browsers, attackers may attempt to send data directly to the server, thus avoiding client-side checks. This would allow entry of potentially malicious or unverified data to the server. Without additional server-side validation, stored data could be compromised.
Preventing such scenarios requires both client and server-side validation. This approach reduces the risk of bad data, while still providing the validation functions on the client that improve results for the end user. Front end validation should be used to inform the user immediately of issues with their input, while server validation will ensure only expected data makes its way into the application.
Stealing Session Data
Client-side script can be very powerful because has access to all the content returned by a web application to the browser. This includes cookies that could potentially contain sensitive data, including user session IDs. A common exploit of XSS attacks is to send the user’s session ID tokens to the attacker so they can hijack the session.
To prevent this, most browsers now support the Http-Only attribute on cookies. When the server sets a cookie on the browser, setting the Http-Only attribute tells the browser not to allow access to the cookie from the DOM. This prevents client-side script-based attacks from accessing the cookies.
Local and session storage browser data can also be stolen in the same way, though it cannot be secured through DOM access. It is therefore best to avoid storing sensitive information, such as tokens, in browser storage unless absolutely necessary.
Cross-site request forgery
Cross-site request forgery (CSRF) attacks attempt to trick a browser into executing malicious requests on the websites the user is already logged in to, even if the site is not actually opened at that time. If sessions on the target site are cookie-based, requests to that site can be automatically enriched with authorisation cookies.
Attackers can also implement their own web pages and have them perform malicious requests to other sites in the background when the user opens it. They can also use social media, forums, and other platforms to post malicious links or other content that forces browsers to make unnoticed calls to other sites using the user’s session cookies.
The general technique for avoiding this vulnerability is implementing tokenization of client-server communication in which an additional token is introduced that is not stored in cookies. Tokens should be generated for each form on the website upon session establishment and should be sent together with each request while the user is present on the website.
Dealing with JavaScript Security Issues?
Protecting applications and servers from JavaScript vulnerabilities can be managed through the adoption of JavaScript security best practices and the use of sophisticated scanning tools.
In the world of web development, software engineers must constantly keep on top of new JavaScript security risks that arise. Not only is it important to conduct functionality tests on applications; using JavaScript security testing tools on a regular basis is also key for preventing vulnerabilities. Last, following some simple and common best practices will definitely increase the durability of your applications.
Some final Tips for Securing your JavaScript
- Avoid eval(): Don’t utilize this command in code, since it simply executes passed argument if it is a JavaScript expression. This means if the hacker succeeds in manipulating input value, he or she will be able to run any script she wants. Instead, opt for alternative options that are more secure.
- Encrypt: Use HTTPS/SSL to encrypt data exchanged between the client and the server.
- Set secure cookies: To ensure SSL/HTTPS is in use, set your cookies as “secure,” which limits the use of your application’s cookies to only secure web pages.
- Set API access keys: Assign individual tokens for each end user. If these tokens don’t match up, access can be denied or revoked.
- Use safe methods of DOM manipulation: Methods such as innerHTML are powerful and potentially dangerous, as they don’t limit or escape/encode the values that are passed to them. Using a method like innerText instead provides inherent escaping of potentially hazardous content. This is particularly useful in preventing DOM-based XSS attacks.
- Identifying potential JavaScript security problems is an essential first step toward preventing vulnerabilities in application development. Test your code with an open-source vulnerability scanner.