Security in JavaScript

 1. Cross Site Scripting (XSS Attack)

This type of attack allows an attacker to inject malicious scripts into web pages viewed by other users.

Example: Consider you have an anchor tag that sets the value of href somewhere in your code based on query parameter.

?redirect=https://www.youtube.com/

should take you to youtube when a redirect link is clicked.

But a hacker can have any other JavaScript code in the query parameter instead

?redirect=javascript:document.getElementsByTagName(%27button%27)[0].click()

Issue: https://stackblitz.com/edit/js-r6efjx

Fix: https://stackblitz.com/edit/js-bwcj8v

<a href id="redirectLink">Redirect</a>
<br>
<button>make payment</button>

//?redirect=https://www.youtube.com/
//?redirect=javascript:document.getElementsByTagName(%27button%27)[0].click()
const a = document.getElementById('redirectLink');
const makePaymentElement = document.getElementsByTagName('button')[0];
const queryParams = new URLSearchParams(window.location.search);
const redirectParam = queryParams.get('redirect');

makePaymentElement.addEventListener('click', () => {
  alert('payment made!');
});

a.setAttribute('href'redirectParam);
//a.setAttribute("href", "javascript:document.getElementsByTagName('button')[0].click()");

Here, the hacker is trying to click the "payment" button when a "redirect" link is clicked

To resolve this, make sure the URL is first validated to confirm that it contains "https" or it does not contain "javascript:" 

//?redirect=https://www.youtube.com/ -- valid redirection
//?redirect=javascript:document.getElementsByTagName(%27button%27)[0].click() -- invalid redirection
const redirectElement = document.getElementById('redirectLink');
const makePaymentElement = document.getElementsByTagName('button')[0];
const queryParams = new URLSearchParams(window.location.search);
const redirectParam = queryParams.get('redirect');

makePaymentElement.addEventListener('click', () => {
  alert('payment made!');
});

redirectElement.addEventListener('click', () => {
  redirectElement.setAttribute('href'isValidURL(redirectParam));
});

function isValidURL(url) {
  const parsedURL = new URL(url);
  if (parsedURL.protocol === 'https:' && !url.includes('javascript')) {
    return url;
  }
  return '/';
}


2. CSRF Attack

Consider a simple web app that listens to GET requests. It is going to be listening to an endpoint "/api/data"and fetches the "url" query parameter and makes a call to that path (/api/data?url="countries")


This attack is targeted on an "authenticated" user who is using a website so they can now make API calls with the token stored in the browser session.

Consider we have few public facing APIs: /api/data?url="countries" , /api/data?url="states"

But other private API: /api/data?url="users" (which should not be made by un-authenticated users)

Now, because the user is authenticated, hacker can now add a link as an advertisement that will make a request to "users" API. 

<a href="http://bank.com/transfer.do?acct=MARIA&amount=100000">View my Pictures!</a>

<form method="GET" action="https://jsonplaceholder.typicode.com/users">
  <button type="submit">
    View my Pictures!
  </button>
</form>

To fix this, whitelist the URLs for any action before making API calls to ANY call received for ANY random action

3. Timing Attack

consider the below code:

const service = { token: { id: "abc" } } 
const retreiveAccount = (userSentToken=> {
  if(service.token.id === userSentToken) {
    return true
  }
  return false
}

Here a secret token is matched to check if the token is correct or not using "===" 

The " = = = " will compare every character

like comparing abcd = = = pqr will immediately give false

comparing abcd = = = abcx will take some time and then give false

So the hacker will know that part of their string is already correct and keep trying with brute force.

You can avoid this using crypto package

import crypto from "crypto"
const service = { token: { id: "abc" } } 
const retreiveAccount = (userSentToken=> {
  if(crypto.timingSafeEqual(service.token.id,userSentToken)) {
    return true
  }
  return false
}




Comments

Popular posts from this blog

Inside the JavaScript Memory Box: Visualizing Variables, References, and Copies

React & State Management: All Concepts

React: Communication between components