Introduction

Security is vital but variable according to the functionality of the web application. Some companies might have a greater concern for multi-factor authentication than others. However, one cannot completely rule out attempted break-ins. Therefore, a good web security is always a must.

This post attempts to shed some light on possible threats and will act as an entry point for further personal research.

Mass Assignment

Mass assignment is known to be a vulnerability when a web application’s ORM (object-relational mapping) interface is exploited to change the certain type of information in the database, which in any case shouldn’t be allowed to be changed by the user. These types of information include session keys, cookie data, passwords, permissions, and admin access.

Almost all of the latest web application frameworks, such as Django, Java Spring, or even when SQLAlchemy was used for frameworks like Flask, implement an ORM interface over which the application can interact more easily with the database. This is where the data in serialization formats are automatically converted into internal objects by generating SQL statements to reflect onto your database. It has never been this easy!

Moving on to the downtimes, if the selected framework’s interface is like a three-legged chair, or if it is a mistake on behalf of the developer that he or she failed to mark specific fields to be immutable, it is possible that the bad guy will try to overwrite fields that you actually never intended to be changed from the outside. Big trouble, mate.

If the bad guy has access to source code and can review the models for sensitive fields. Similarly, such information should not be posted on collaborative platforms such as GitHub. They have bots that scan such platforms for sensitive information, which, in turn, results in them hunting you down.

The object with sensitive fields has an empty constructor or setter.

The easiest way to block this kind of breach in Django is to use Forms. There will be custom cases and requirements, but forms are almost always the right thing to do. The trick is just to use them in the right way.

This whitelists the fields the user can change. Similarly, this also excludes the property that lets us blacklist fields.

We have ourModelForminstance. If we want to add in our custom requirements, we can use custom validation logic. Django offers features where we can display an error to the user saying “your password needs to be of so and so length," or any type of password policy that you want to incorporate. It also includes constraints on Age, username, email address, and different fields, too. How to run all the validation for us in our code? Call the built-in is_valid()in your template, and it will do just that, furthermore, allowing the users to change only what they are authorized to change.

Clickjacking

Hijacking is to vehicles as Clickjacking is to clicks. They are also known as “UI redress attacks," where the attacker renders a concealed layer on your website, in the hope of deceiving the client into clicking on to it, may it be a button, or link, which redirects it to another page that is owned by another application, domain, or both.

Suppose this new endpoint’s functionality is to install a script introducing a worm on your machine, which, in this case, is connected to your production server network. This worm will be the cause of replication of itself on every other host with which it can communicate with, resulting in big trouble.

Similarly, keyboard strokes can also be hijacked. With a carefully crafted combination of stylesheets, iframes, and text boxes, a user can be deceived into typing their password to their social account, or banking websites when they are actually typing into the attacker’s form input, thus giving them access to the secret data from the user.

This can either be done by using an XSS vector, which interchanges the endpoints and the links, or even entire segments of your page or can be even done by putting your page in an iframe and rendering the attacker’s content over yours.

The common solutions that can be discussed for the same consists of:

Framekillers

Framekillers are the solution to the problem of Clickjacking. They are written in JavaScript with the intended functionality of checking whether the current window is the main window.

The suggested approach would be to hinder rendering of the window and unblock it only after being sure that the current window is the primary one:

The latest Internet browsers have an inbuilt system of the HTTP header, X-Frame-Options, which can be thought of as a setting that allows you to permit resources loading within a frame or iframe. The header takes two values:

SAMEORIGINwill result in permission to load the resource in a frame, if and only if the request is from the primary site.

DENYwill result in blocking the permission to load any resource in any kind of frame or iframe, regardless of the request origin.

Django’s Implementation of Clickjacking Protection

A simple middleware that sets the header in all responses.

A set of view decorators that can be used to override the middleware or to only set the header for certain views.

The X-Frame-Options HTTP header will only be set by the middleware or view decorators if it is not already present in the response.

Setting X-Frame-Options for all Responses

To set the same X-Frame-Options value for all responses in your site, put ‘django.middleware.clickjacking.XFrameOptionsMiddleware’ to MIDDLEWARE:

The middleware displayed above will set the X-Frame-Options header value to SAMEORIGINfor every HttpResponse. If your requirements are such that you want to use DENYin place of that, you can always set this setting to the value you want.

X_FRAME_OPTIONS = 'DENY'

There may be requirements where you want some views where you do not want the X-Frame-Options header value set. For such cases, Django offers view decorators that instructs the middleware not to set the header.

from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_exempt
@xframe_options_exempt
def let_load_in_an_iframe(request):
return HttpResponse("This page is safe to load in an iframe on any site.")

@xframe_options_denyand @xframe_options_sameoriginare other decorators that Django provides apart from @xframe_options_exempt, to set the X-Frame-Options header on a selective view basis.

Session Fixation and Hijacking

It is always advised for a website’s security to force redirect all HTTP communication attempts via HTTPS. This will prevent malicious network users from using software, such as Wireshark and smartsniff, which were intended towards the use of testing inter-connectivity among networks and can be used for sniffing authentication credentials or any other data that are being passed between the client and the server. This can also be done through ARP poisoning.

In some very realizable cases, the data can be changed between the transit from client to server or vice versa. The people responsible for this are called active network trespassers.

Embrace the protection HTTPS provides. Enable it on your server. There may be additional steps in Django that you may want to look through:

Set SECURE_PROXY_SSL_HEADER. Inability to do as such can bring about CSRF vulnerabilities.

Set SECURE_SSL_REDIRECT to True so that requests across HTTP are wheeled through to HTTPS.

You should set your SESSION_COOKIE_SECURE and CSRF_COOKIE_SECUREsettings to True. This instructs the browser to only send these cookies over HTTPS connections.

Use HTTP Strict Transport Security (HSTS), which is an HTTP header that notifies the browser that all future connections to a specific site should always use HTTPS.

Finally, make sure your cookies have the secure and HttpOnlyflags, especially the session cookie. Django defaults to HttpOnlyin the latest releases. Let us run through a scenario where an attacker found a way to run any code written in JS on your site through the Google developer tools JS console. And due to your bad luck, the session cookies weren’t HTTPOnly. They could execute various types of code to steal state of your cookies. Something like this:

This could very well result in grabbing every cookie on the site, but especially the session ID, and impersonating a poor, well-intentioned user.

In the end, it would be positive to delete the session data for a particular user after they log out. You could, in turn, mark it invalid upon further use or generate something like a temporary random generated security token upon each login to initiate the session in an intended manner.

CSRF: Cross-Site Request Forgeries

An example of a GET request:

http://badevilcorpbank.com/transfer?from=act1&to=act2&amt=100000.00

Leaving aside how we haven’t used HTTPS in spite of the above content, and following that, there is no confirmed validation that the request is coming from a legit requester. I could append an image tag with the URL, thus, resulting in receiving a hundred rupees every time someone hit the endpoint.

Most web frameworks, like Django, have built-in CSRF protection that uses the concept of a nonce, or one-time-use number. These are submitted with a form (over the POST, hopefully, if not, sigh!) to the server. If the number generated on the server is the same as that was sent through the form, the request is allowed to pass through. If the number doesn’t match, the request is disallowed.

When installed with HTTPS, CsrfViewMiddlewarein Django will check the authentication of the HTTP referer header. It will further check that the header is set to a URL, which is of the same origin including domain, subdomain, and port.

Since HTTPS offers extra security. It is of utmost importance to do the following:

Ensure the validity of the connections utilizing HTTPS

The areas over which HTTPS is accessible

Can be tested by sending insecure connection requests

Utilizing the HSTS support provided in the latest browsers

Taking care of all the security paradigms across different browsers

A neat tool named also comes in handy in such situations. Django-session-CSRF is an alternative implementation of Django’s CSRF protection that does not use cookies. Instead, it maintains the CSRF token on the server using Django’s session backend. The CSRF token must still be included in all POST requests (either with csrfmiddlewaretokenin the form or with the X-CSRFTOKENheader).

A Django third-party package named Django-session-csrf is of vital importance in such situations. It provides a custom setting interface of Django’s CSRF protection. It does not run on cookies as legacy dDjango’s CSRF protection does. In place, it just maintains the CSRF token on the physical server using Django’s SESSSION BACKEND.

Either way, the CSRF token must be included in all future POST requests.

This can be done in two ways:

We could csrfmiddlewaretokenin the form itself, or,

We could use the CSRFTOKENheader

Password Storage

The most important credential to authenticate and recognize a user is the password, which is why we need robust ways to store it in an encrypted way.

So, what is The Right Thing to do?

Use a cryptographically slow hash function. bcrypt, and PBKDF2 are excellent choices. Even if someone has complete access to your database, it’ll take a long time (longer for longer passwords) to calculate these, and as processors get faster, they both have a work factor that can be increased, so the time to generate each hash can remain constant.

Use HMAC with expirable keys stored on the filesystem, or anywhere outside the user database.

This can be achieved by tools like Django-sha2, which adds strength, but backward-compatible, password hashing support to Django.

The image, being self-explanatory, highlights the need for security best practices to be implemented during the development of web applications. There are certain immediate steps you can take to quickly and effectively improve the security of your application. However, as applications grow, they become more cumbersome to keep track of in terms of security. Putting the proper web application security best practices in place, as outlined in the list above, will help ensure that your applications remain safe for everyone to use.