Various Ways to secure the modern web applications
Most modern application frameworks like Spring, Rails, Django comes with out of the box security features like Forgery Request protection, Content Sharing securely, defining the Security Headers etc.. By default, they are turn ON by the framework configurations itself. But based on the application’s needs, tailoring the security configurations and implementing the best security coding practices (especially for apis and for micro services) are still in the hands of the architects / developers.
Few of the security configurations involves
1. Protecting the forgery attacks in the APIs
2. Sending the API session data securely(esp not accessible by the JavaScript)
3. Enabling cross origin resource sharing securely
4. Creating security Policy for the contents
5. Setting all the necessary security headers etc..
Few of the best security coding practices needs
1. Strictly following the encapsulation
2. Sanitizing the user data before using in the SQL queries or storing in the Database.
3. Implementing the Global exceptional handler in the app
4. Tightening the authorization for every resources
5. Adding only the secured open source dependencies etc…
The Security, in general, is a non functional feature of an application and it is not tangible from the business perspective but it should exist as a core part of an app with all its mightiness to withstand the most critical attacks. Since it’s intangible and the frameworks come with the out of the box security features, most of the time, it is not in the developer’s radar to contemplate about it. Hence, the developers may tend to open up the security holes in the application by unknowingly disabling the CSRF protection provided by the framework or not making right decision to find the best secure storage in the browser or sending the session data insecurely or directly using the user’s data in the SQL queries or rendering the user’s data (containing the malicious javascript to steal the cookie / defame the web page) in the browser.
In order to raise the awareness among the developer’s community, OWASP is actively building the security documents, tools, teaching environments, guidelines, checklists, and other materials to help the organizations improve their capability to produce secure codes. With the help of OSWAP top 10, the developers can easily square away the security aspects of the app.
Here are the most critical attacks
1. Cross Site Scripting(XSS)
2. Cross Site Request Forgery (CSRF)
3. Cross Origin Resource Sharing(CORS)
4. SQL injections
5. Session hijacking
6. Session Fixation
7. Man-in-the-Middle attack
The countermeasures to mitigate the attacks
1. Proper storage of Session and Cookie data
In the browser, there are three main storage options available.
- Local Storage — stores the key value pairs with no expiration date. These data can only be used by the browser and won’t be send to the server. Javascript can easily read the LocalStorage object like
JSON.stringify(localStorage)
. Hence it’s not ideal to use them to store session data. - Session Storage—stores the key value pairs but expires once the browser is closed. Like LocalStorage, the data never be send to the server and used only be the browser. Again, it’s not a ideal storage solution on the client side
- Cookie — Expires based on the duration set by the server. Its data is used to interchange with server to maintain the http protocol user’s state b/w requests. Storing the session data or auth token in a cookie is considered relatively secure when the server sets the
secure
andhttp-only
flags withSameSite
cookie attribute. It is even more secure along with CORS headers configurations. When the secure and http-only flags are used, the cookie is only sent using SSL and JS can never be able to read the cookie.
2. Utilize the HTTPS
Communication happens over the TLS/SSL protocol prevents the one of the most common threats — man in the middle(MITM) attack. It facilitates to communicate the sensitive data like auth token b/w sever and client more securely using the encryption. Hence it comforts the developer that data in the transit is safe and secure.
In Rails, config.force_ssl=true
enables the browser to redirect HTTP to HTTPS. It adds secure
flag to the cookies and it enables HSTS, each of which are very good protections against SSL stripping and MITM attack.
3. Set the security headers
Via, the HTTP headers (mostly in the response headers), the servers can set the limitation on the browser’s ability to perform the request which in turn makes the modern browsers to become more immune to the vulnerabilities. Mostly, the frameworks like Rails, Spring sets the security response headers by default. But, when these frameworks are operated in the API mode, the developers may need to configure them explicitly. The OWSAP foundation came up with OWASP Secure Headers Project and defines these headers in detail along with its value options. We can explore them here.
- HTTP Strict Transport Security
- X-Frame-Options
- X-Content-Type-Options
- Content-Security-Policy
- X-Permitted-Cross-Domain-Policies
- Referrer-Policy
- Clear-Site-Data
- Cross-Origin-Embedder-Policy
- Cross-Origin-Opener-Policy
- Cross-Origin-Resource-Policy
4. Enable CSRF protection
A hacker can send an object state changing request like transferring the money from his site (a different domain) after he had stolen the session data from a victim OR he can submit the form data from his site. So by enabling this feature, we can prevent the forgery request from a cross(different) site.
- In general, the most of the frameworks come with CSRF protection ON by default.
- Usually, the CSRF protection mechanism is implemented by a (CSRF) token -generated in the server side . The CSRF token is sent to the browser via Cookie and the same token is automatically added in the forms as a hidden input field if the web page renders the form.
- When the form data gets submitted, the framework will validate the CSRF token by comparing the CSRF token from Cookie and from the hidden field of the HTML form. If both matches, then form data gets accepted and stored in the DB.
- If the client side framework ( Angular, React. Vuejs, ) is used for an app, then it’s the developers’ responsibility to configure the CSRF protection feature explicitly.
- Developer needs to generate a CSRF token (Rails provides a helper method called form_authenticity_token) and send it to the browser in the Cookie. Then client side framework needs read the cookie and set a request header like
X-CSRF-Token
. Then the server will validate the token from the cookie and request header and accepts the request.
5. Whitelist the domains in the app
This is one of the must-to-have configuration to mitigate the CSRF threats. This configuration defines who are all allowed to the access the resources.
There could be a scenario where a CSRF token was stolen and a hacker was using it for CSRF requests. He can post any type of data. This is so scary to imagine. But if the hosts are whitelisted in the server, then this kind of attacks can be highly preventable.
By default, the access control is be opened up for the all domains in most frameworks. Suppose the server runs in the API mode, more than one client can access it. So leverage the hosts whitelisting configuration of the framework to define the allowed hosts. In case of Rails, config.hosts
configuration is used helps to whitelist the domain.
6. Enable the CORS header
Through the HTTP security response headers like X-Frame-options
, the browser’s ability to communicate with server gets defined.
CORS — Cross Origin Resource Sharing — the headers are used to define the ability of the cross origin (the client side domain) to request the resource from server’s domain. It is very powerful headers to define the client’s ability to interact with server. As per the CORS specification, these are headers
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240
Generally, the browsers perform a pre-flight check
Request before making a non GET methods. The response for the pre-flight request with CORS headers helps the browsers to decide whether the POST/PUT/PATCH/DELETE requests can be made or not.
7. Enable the CSP
Content Security Policy is very useful and powerful headers helps to mitigate various threats like CSRF, XSS, injections, site defamation etc. It defines a policy which lets the clients(browser) know how the contents of the page can be loaded and what are contents are allowed. It’s set using the header Content-Security-Policy
. Here is the detail explanation of CSP.
8. Security Coding Practice
- Only allow the non GET request to change the state of the an object
- Validate the user inputs
- Sanitize the user inputs before rendering the web pages
- Parameterize the queries variables
- Monitor the errors and handle the errors globally in the app
9. Code Review
Code Review process can be very well utilized to ensure the security aspects of the application. If the organizations come up with their own security policy documents and train their developers well on the security aspects, the applications will be very much secured.
10. Software Testing/QA
Along with Code Review Process, the QA testing process can also be very well utilized to mimic the attacks to see how well the applications withstand all top 10 OWASP attacks.
Generally, for an application to withstand all attacks, setting only few configurations or implementing only few coding practices will not help. It takes majority of the security configurations and implementing majority of the security coding practices. Overall, the developers always need to look for the ways to increase their application protection/security while the hackers, using the same technology, are trying very hard to pass through the security holes.