Tips to Secure Your Angular Application

Jignesh Trivedi  Print 
04 Oct 2018
 
Advanced
278

Software security is major concern for every application. There are some common vulnerabilities reported for web application that we need to care for all the application. In this article, I will discuss the vulnerabilities possible with Angular application and how to prevent these vulnerabilities by using best practices.

Prevent application from Cross-Site Scripting (XSS)

XSS allows attackers to inject client-side script or malicious code into web pages that can be view by the other users. This kind of attack mostly happened via the query string, input field, request headers. For Preventing XSS attacks, we must present user to enter malicious code from DOM. For example, attacker might enter some script tag to input filed and that might render as read-only text.

By default, Angular treats all values as untrusted when the values are inserted into the DOM via the attribute, interpolation, properties, etc. It escapes and sanitizes values before render. The XSS related security in Angular defined in "BrowserModule". Angular's DomSanitizer help to clean untrusted parts of the value. The DomSanitizer class looks like as following.

export declare abstract class DomSanitizer implements Sanitizer {
 abstract sanitize(context: SecurityContext, value: SafeValue | string | null): string | null;
 abstract bypassSecurityTrustHtml(value: string): SafeHtml;
 abstract bypassSecurityTrustStyle(value: string): SafeStyle;
 abstract bypassSecurityTrustScript(value: string): SafeScript;
 abstract bypassSecurityTrustUrl(value: string): SafeUrl;
 abstract bypassSecurityTrustResourceUrl(value: string): SafeResourceUrl;
}

Here, there are two type of method patterns: sanitize and bypassSecurityTrustX (bypassSecurityTrustHtml, bypassSecurityTrustStyle, etc.). The sanitize method gets untrusted value from the context and returns the trusted value. The bypassSecurityTrustX methods gets untrusted values from the context and according to the value usage it returns a trusted value.In specific condition, we might require disabling sanitization. By setting up any one bypassSecurityTrustX methods, We can bypass security and binding the value.

Example
import {BrowserModule, DomSanitizer} from '@angular/platform-browser'

@Component({
 selector: test-Component',
 template: `
 <div [innerHtml]="myHtml"></div>
 `,
})
export class App {
public myHtml: string;
 constructor(private sanitizer: DomSanitizer) {
 this. myHtml = sanitizer.bypassSecurityTrustHtml('<h1>Example: Dom Sanitizer: Trusted HTML </h1>') ;
 }
}

Be careful when turn-off or bypass any security setting that might malicious code and we might inject security vulnerability to our application.Sanitization inspect all the untrusted values and convert it into a value that is safe to insert into the DOM tree. It does not change the value at all the time and Angular allows some untrusted values for HTML, styles, and URLs. Angular defined some security contexts as following.

  • It uses HTML context when interpreting a value as HTML

  • It uses Style context when any CSS bind into the style property

  • It uses URL context when bind URL (example<a href>)

    Angular generate the warning and print into the console when it changes the value during sanitization.

Use Route guards when required

The router guards are the interface that tell the weather route to request URL or not. It makes a decision by interface return value i.e. if interface return true then it routes to the new URL else not. There are mainly five type of guards and all are called in particular sequence. We can modify routing behavior depending on which guard used. Following are the provided route guard

  • CanActivate : checks the route access

  • CanActivateChild :Checks the child route access

  • CanDeactivate : it asks the permission to discard the changes

  • CanLoad : Checks before load feature module

  • Resolve : it pre-fetch the route data

    In the following example code, I have implemented CanActivate route guard that allowed route if token data available in local storage else redirect to login page. In the route guards, we can put any kind of checking such as user roles has right to access page, etc.

Route Guard Example

 
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

@Injectable()
export class AuthorizationCheck implements CanActivate {

 constructor(private router: Router) { }

 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
 //If token data exist, user may login to application
 if (localStorage.getItem('TokenInfo')) {
 return true;
 }

 // otherwise redirect to login page with the return url
 this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
 return false;
 }
}

We can apply this route guard to the route in RouteModule. Following example code, I have defined route app.module file.

 
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
....
....
...
import { AuthorizationCheck } from './Services/authorizationCheck'
...
...
@NgModule({
 declarations: [
 ....
 ....
 ....
 ],
 imports: [
 ....
 ....
 RouterModule.forRoot([
 { path: '', component: HomeComponent, pathMatch: 'full', canActivate: [AuthorizationCheck] },
 { path: 'counter', component: CounterComponent, canActivate: [AuthorizationCheck] },
 ....
 ....
 ])
 ],
 ...
 ...
})
export class AppModule { }

In this way, we can protect our route, and this cannot be easily hackable. However, if user has knowledge about the system then he/she can brake route guard.

You can refer full Authentication example here Token-based Authentication in Angular.

Remove Local storage and windows session storage data after logout from application

After, successful login to the application, generally we store user data such as user name, authentication token, etc. to either local storage or windows session storage. This type of user information may use by the hacker/attacker and take access of application if they are available after user logout.

Local storage can be shared between multiple tabs as well as multiple browser session. Windows session storage can only accessible to particular browser session and it kill when browser is closed. I recommended to use windows session storage instead of local storage to store such information. But it is depending on the application requirement. So, it is best practice to remove such data from local storage and windows session storage after logout.

Implement CSP (Content Security Policies)

It added layer of security which help us to detect and mitigate certain types of attacks (including data injection and XSS attack). To enable Content Security Policy, our web server (API) must return appropriate Content-Security-Policy HTTP header. We can implement CSP either by using HTTP Meta tag or defining "Content-Security-Policy" to header.

<meta http-equiv="Content-Security-Policy" content="default-src https://myexample.com; child-src 'none'; object-src 'none'">

Or

Content-Security-Policy: script-src 'self' https://myexample.com

Do not use DOM’s APIs directly

Angular recommended to use Angular templates rather than using DOM API such as document, ElementRef etc. Angular does not have control over these DOM API, so it does not provide the protection against security vulnerabilities and attacker can inject malicious code in DOM tree.

Prevent CSRF (Cross-site request forgery)

It is also known as Session riding. Attacker copies forge as a trusted source and execute actions on user behalf. This kind of attack can damage both client relation and business. The common mechanism used by HttpClient to support CSRF attack protection. when application made any http request, interceptor reads the information about the token from the cookies and set HTTP header. The interceptor sends application cookies on all request such as POST etc. to the relative URL, but it does not send cookies with HEAD/GET request and request with absolute URL.

So, server need to set a token in JavaScript readable session cookie on first GET request or page load. With subsequent requests the server verify this token with request header cookies. In this way, server can sure that code running on same domain. This token must be unique for each user and verified by the server. CSRF protection also need to apply to server (our back-end service) as well. In angular application, we can use different names for XSRF token cookie or header. We can override the defaults value by using HttpClientXsrfModule.withOptions method.

imports: [
 HttpClientModule,
 HttpClientXsrfModule.withOptions({
 cookieName: 'my-Cookie',
 headerName: 'my-Header',
 }),
],

Prevent Cross-Site Script Inclusion (XSSI)

Cross-site script inclusion (CSSI) is also known as JSON vulnerability that allows the attacker to read data from JSON API. Attacker can override the native JavaScript object constructor and include an API URL using script tag. The attacker may be getting success if returned JSON is executable as JavaScript.We can prevent an attack by prefixing all JSON responses with well-known string ")]}', \n". This makes JSON to non-executable. Angular library (HttpClient) recognize the "\n" character and makes script is not executable.

Up-to-date Angular Libraries

There are continuous updates provided for bug fixes, security patches and feature enhancements at regular interval, so it is recommended to update the Angular libraries. It is possible that security-related issue fixed in newer release that prevent any security vulnerabilities injected by attacker.

Avoid Modifying the Angular Copy

It is recommended to avoid Modifying the Angular Copy because it creates hard link between our application and Angular libraries. As describe in above point, there are continuous updates provided for bug fixes, security patches and feature enhancements in Angular libraries, so it very difficult to upgrade to newer Angular versions.

Use Offline Template Compiler

It would be recommended to use offline template compiler to prevent security vulnerabilities called template injection. It recommended to use the offline template compiler in production deployment. Basically, Angular trusts on template code, so someone can add vulnerabilities to dynamically created template as a result malicious attack on DOM tree.

Validate user submitted data on server-side code

It would be good practice to validate all the submitted data on server-side code. This can help to prevent data related vulnerabilities. Some time, attacker can use XSS method and try to inject malicious data to our application. If we validate the data at server-side as well, we can prevent our application from this kind of attack.

Do not use components with Known Vulnerabilities

There are many third-party libraries component available and nowadays it just impossible to develop the application without such libraries. These libraries may have known vulnerabilities and that can be used by the attacker to inject malicious code or data to our application. These libraries can have security vulnerabilities such as CSRF, XSS, buffer overflows, etc.

Solution

  • Download the library from trusted source

  • Always use updated version of library (it may fix some critical security defect in latest version)

  • Monitor the library's Vulnerabilities from the source such as NVDhttps://nvd.nist.gov/vulnand CVE https://cve.mitre.org/

Summary

In this article, I have covered some top possible attacks on our Angular application and how to prevent our application from such attack.

Hands-on Learning
Free Interview Books
 
+