- Published on
Security on the Front-End
It's getting increasingly likely to have security vulnerabilities on the frontend due to many factors, one of them being the use of external code through libraries or frameworks such as jQuery, ReactJS, and VueJS, Lodash, not setting up HTTPS to encrypt the data exchanged between the server and the client, use of old or deprecated libraries/frameworks. The consequences of a breach/exploited vulnerability can be fatal that can include harm to customers, lost of trust and in some cases legal liabilities. In this article I will outline some of the things that when neglected can contribute to an insecure Front-End.
One thing worth mentioning is that there are a lot of ways your Front-End can be attacked or vulnerable, that's why I recommend checking the O-WASP Top Ten where you can have a deep insight has to what vulnerabilities plague web applications.
And we're going to start with the most obvious vulnerability that an app can have if not catered for:
Not Using HTTPS
When you use HTTP all data sent from the client to the server and vice-versa is unencrypted that implies that your users sensitive information such as credit cards number(if your site supports payment), social security number, or any other data sent from the server or Front-End is exposed to anyone connected to the network(it gets even more dangerous if the network is public) and sniffing packages and might get the sensitive data and use it for personal gain at the expense of your users.
The remedy for this is to use HTTPS, currently, there are two options for installing HTTPS or getting the SSL certificate, you can either buy from a vendor/provider such as Digi-cert or get the free SSL certificate with let's encrypt.
The downside of using let's encrypt is the browser support, and you can only get the Domain Validation SSL certificate on top of that you have to renew it every three months.
Having HTTPS also allows us to access browser APIs that would not be available if the domain origin does not have a valid SSL certificate(these APIs only work in secure origins) such as Service Workers, Push API, and Location, and others you can check the features restricted to secure contexts.
Not having access to Service workers and other APIs means that your application cannot qualify as a PWA, and the worst thing is that browsers will label your site as being unsecured which can damage your business reputation and SEO.
Taking user input as is(not sanitizing)
Not sanitizing user input extremely dangerous, if you don't sanitize user input your app might be suggested to SQL or XSS. Suppose I'm building an app that allows you to share about development meetups.
The app contains this input
<input type="text" name="meetup_title" placeholder="Meetup title" />
If I take the text inserted into that field and append to markup without sanitizing the user can fill it with the following:
let evilScript = document.body.appendChild(document.createElement('script'))
evilScript.type = 'text/javascript'
evilScript.src = 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.esm.js'
And the browser will execute the following instructions if the input text is appended using the innerHTML
method,
with that the attack perpetrator can:
- Request CSS
- Request images
- Make calls to your API
- Control the browser
- Open another page
- Open another tab
- Read all cookies not marked as HTTP ONLY
It's pretty much game over for your application, the hacker can do as he wishes how he wishes. The best thing to do in
such situation is to escape the text before appending to the DOM, or even better you can use JavaScript's built in
innerText
if you want to append what's typed as text if the content is not supposed to be processed as markup.
Using deprecated libraries/frameworks with widely know vulnerabilities
Using deprecated libraries with widely known vulnerabilities it's almost like asking to be
hacked(seriously don't use jQuery 1), hoping that hackers will not find out that your website's
library or framework has known vulnerabilities is not a good strategy. Making a habit of inspecting
the libraries' versions, if you're using github you can turn on notifications for vulnerabilities
in libraries with dependabot or you can use
snyk which has a web and CLI app that checks vulnerabilities in all dependencies
in project's your package.json
Not inspecting frameworks or libraries before deploying to production or using it
Sometimes the libraries might not be deprecated or have known vulnerabilities but, it is always better to be safe than sorry, when house builders look for tools to aid them in their work they don't choose the latest "fanciest" tools that only a handful of craftsman use, they always in search for tools that stood the test of time, and that's what I think developers should do, use tools that many developers have tried and did not find any tricky or malicious code, I also think that from time to time you should check what code is in your library.
Sending sensitive data using GET requests
One of restful API guides is that we should not mutate data using GET requests, that's a good rule to follow, because asides making an API restful it can also make it safe. Suppose we have the following form for getting users payment credit card number and CVC for issuing a payment to a service your application.
<form method="GET">
<input type="number" name="credit_card_number" placeholder="Credit card number" />
<input type="number" name="credit_card_cvc" placeholder="Credit Card CVC" />
<button type="submit">pay</button>
</form>
Seemingly this form looks okay, but there is a security vulnerability, after submitting a form using a GET request the
browser stores the request URL and all the input fields containing a name
in it will be in the URL and hence in
the users' browser's history and URL bar here is how it looks like:
Accordingly, the URL will the in users history:
If you have an access log here's what your server log will look like:
Given the vulnerabilities pointed above it is important for us developers to always use post requests for sensitive data,
browsers tend to fallback to get requests if the method is not specified, that means we have to remain vigilant and
add method="POST"
attribute when dealing with forms that contains sensitive data.
Not adding noopener noreferer to external links
When we add external links with target="_blank"
attribute the browser allows the opened tab to run in the same process
as the opener website(unless configured with a different behavior), which means that if the newly opened tab has performance
issues that might affect the opener page, moreover a critical security vulnerability would be the fact that the newly opened
tab can access the previous page's properties via window.opener
with that make any changes to the DOM.
Not adding DOCTYPE to force Internet Explorer to use it's best rendering engine
When you add <!DOCTYPE html>
to the HEAD of the html file it lets the browser know that this page is using the latest version
of html, there's nothing new under the sun here, however Internet Explorer and Microsoft Edge usually ship with the
engine from previous browsers which also contain errors and security vulnerabilities from previous browsers, one of these
features is CSS in JS which allows you to write JS in CSS and have the browser execute it, this could be a source for a
XSS in your application.
Keeping API keys in JavaScript code
Unless your API key contains extra protection keeping it in the JavaScript code is a mistake and any user who can access your site will and can use your API key and if it is linked to any special privileges the user can exploit your application as he/she wishes.
Not preferring HTTP only cookies for sensitive data
HTTP ONLY cookies are like the name itself, are only accessible via HTTP, that way evil scripts cannot read your users sensitive cookies and use them for their own interests. You can use them store session tokens or anything that would be a vulnerability to the user if an evil script reads it.