JavaScript (JS), as a language, is one of the most widely used languages within web development. As per a recent survey conducted by Stack Overflow, 67% of professional developers use Javascript, while more than 95% of global websites are using this language during their development and functional stages.
Almost every developing/coding language brings its own set of security issues and JavaScript is not far behind. JS ranks fourth in the list of vulnerable languages, while Java, PHP, and C continue to be the top contenders.
So, what makes JavaScript vulnerable? If security threats are becoming your biggest concern, you should check some of the most common threats affecting JavaScript functionalities.
Most Common Security Vulnerability Threats in Javascript
On a high level, it would be easier to classify JavaScript’s security threats into two categories, namely:
- Client
- Server-side
Cross-Site Scripting (XSS)
XSS has been ranked as one of the most dangerous security risks which fall under client-side security threats. Majorly, it occurs as soon as an attacker injects malicious scripts within the victim’s web browser, by using a legitimate web application. This is further enforced as soon as the victim visits the web page/web application.
Some vulnerable vehicles include forums, web pages, and message boards, which are used quite extensively to spread XSS. An attacker can exploit XSS vulnerabilities and make these work in data tampering, account thefts, and malware distribution.
The example below showcases how an XSS attack is executed:
<form>
<input id="query-input" type='TEXT' name="query">
<button type="submit">Click me</button>
</form>
<div id="query-output"></div>//JavaScript
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded', ready)
} else {
ready()
}function ready() {
var query = new URL(window.location).searchParams.get('query')
document.getElementById('query-input').value = query
document.getElementById('query-output').innerHTML = query
}
Preventing XSS attacks
In order to prevent XSS attacks, a developer needs to separate untrusted data and user inputs from within the active browser’s content. Some quick steps include, but are not limited to:
Validating user’s input beforehand: Validate user’s input to ensure it contains acceptable characters, which are not susceptible to XSS attacks.
Use appropriate frameworks: Use frameworks that are immune to XSS vulnerabilities; this can be achieved by using advanced packages, like XSS-filters.
Train developers and other staff: Train all the developers involved in the web application development process, which includes QA staff, DevOps, and system admins, developers etc.
Use encryption: Use an encrypting technique, which captures the user’s input. This can be via any source like JavaScript escape, HTML escape, URL escape, CSS escape etc. Avoid pre-existing libraries for escaping purposes; avoid creating new libraries as much as possible.
Cross-Site Registry Forgery (CSRF) Attack
Deriving its origin from identity theft, the attacker impersonates the intended victim’s identity by hacking into the session’s cookies. CSRF tricks the victim’s browser into submitting an unwanted set of actions within an application.
Such attacks can be devastating for individual users and businesses alike. Not only does it damage client relationships, but any kind of unauthorized fund transfer requests and data thefts can lead to massive financial damages for the affected people.
CSRF attacks are usually driven through social engineering attacks, which includes sending emails or malicious links, by tricking the victims into sending a forged request to the servers. Such links seem authentic, which makes it difficult for users to differentiate between legitimate and non-legitimate links.
Example:
Preventing CSRF attacks:
- In-built CSRF protection: First and foremost, check if your framework has good built-in CSRF protection. If not, then the changing requests should be validated at the backend.
- Use SameSite Cookie Attribute: Make it a point to use SameSite Cookie Attribute for session cookies.
- User Interaction Based Protection: Implement User Interaction Based Protection to aid highly sensitive operations.
- GET requests: Avoid using GET requests, for assisting in state-changing operations.
SQL Injections
Web applications are driven by databases, and SQL statements are widely used to control the underlying databases. In recent years, SQL injection attacks have become a common trend for retrieving sensitive information from organizations and enterprises alike. Most credit card and password breaches happen through the use of SQL injections vulnerabilities.
Through this methodology, hackers often insert SQL queries into input fields, which are further processed by the underlying databases.
Some common side effects of SQL injections include, but are not limited to:
- Extraction of confidential, private data, such as credit card information, passport data, hospital records, etc.
- System compromises
- Unauthorised access and disruption of websites, especially websites which store user information
Example of SQL Injection attack
const express = require('express');
const db = require('./db');
const router = express.Router();
router.get('/email', (req, res) => {
db.query('SELECT email FROM users WHERE id = ' + req.query.id);
.then((record) => {
// logical flow
res.send(record[0]);
})
});
Preventing SQL Injection attacks
- Validate user inputs: Establish and whitelist the valid SQL statements, while unvalidated statements should be left out of the underlying queries.
- Cleanse data by limiting special characters: Underlying data can be cleansed by disabling string concatenation so that hackers are unable to take control of the underlying databases through SQL queries.
- Use only stored database procedures: Stored procedures employ variable binding techniques, as they reside within the underlying database itself. However, stored procedures are not immune to attacks, especially, if dynamic queries are used.
Sensitive Cookie Exposures
Client-side scripts can access server content, which includes sensitive data, especially session IDs. As soon as session identifiers are exposed, may it be via URLs, logs, and error messages, which opens up an application to various types of vulnerabilities, like cross-site request forgery (CSRF), session fixation and session hijacking.
Example:
const express = require('express');
const session = require('express-session');
const SQLiteStore = require('connect-sqlite3')(session);
const util = require('util');
// express-session configuration
const sessionMiddleware = session({
store: new SQLiteStore({
table: 'sessions',
db: 'sessions.db',
dir: __dirname
}),
secret: 'H@rden y0ur c00k1e5',
saveUninitialized: false,
resave: false,
rolling: true,
name: 'ssid',
domain: 'localhost',
httpOnly: true,
secure: true,
sameSite: 'strict'
});
const app = express();
// tell Express to use the 'sessionMiddleware'
app.use(sessionMiddleware);
app.get('/', (req, res) => {
// trigger the 'Set-Cookie' (otherwise no cookie would be set)
req.session.counter = (req.session.counter || 0) + 1;
res.send(util.format('You have ve visited this page %dtimes',
req.session.conter));
});
app.listen(4000, () => {
console.log('Application listening on port 4000');
});
Preventing Sensitive Cookie Exposures attacks
- Prevent unauthorised cookie accesses: Developers can use HTTPS and HTTP-only cookies, which will tell the browser to prevent any unauthorised cookie accesses through the DOM.
- Opting per-requests user authentication requests: Another way to secure user sessions by opting per-requests as compared to per-session identifiers. As soon as the client requests privileged access, the current session would be terminated and the requestor would need to be re-authenticated, before getting access. ###Best practices to reduce risks:
- Define content security policy: A content security policy is a header, which can be set within the Nginx configuration file This way, a developer can define the styles, frames, fonts, media, etc.
- Secure APIs on the client-side: Assign and use individual tokens to each user with their accesses. If the assigned tokens don’t match, the access can be revoked.
Good read- Complete Guide on API Security Mobile Apps
Use safe methods for DOM manipulations: Methods like innerText can go a long way in preventing DOM-induced XSS attacks.
Avoid eval() statement: Avoid the use of the eval() statement within your code, as it executes the said argument, especially if it is a JS expression.
Encrypt: Encrypt the exchanged data using HTTPS/SSL between your client and server sides.
Javascript Security Best Practices
In order to curb JavaScript security attacks, it’s important to adopt good coding practices, which can secure applications against such malicious attacks. To secure JavaScript from such vulnerabilities, developers can follow these practices:
- Don’t trust user inputs blindly
- Use proper methodologies for encoding/escaping
- Sanitize and cleanse your user inputs
- Set secure cookies
- Establish a secure content security policy
- Encrypt data transmissions between client-side and server-side
- Use updated libraries and frameworks
- Perform regular scans on your underlying databases and codebases
By following simple, yet effective practices, one can secure their JavaScript sessions and codes, to enable regular data transmissions from the client to the server and vice-versa.
Additionally you can use Appknox SAST to audit and secure your code resulting in shipping your applications faster into the market.
Top comments (0)