Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

AngularJS: How to Handle XSS Vulnerability Scenarios

DZone's Guide to

AngularJS: How to Handle XSS Vulnerability Scenarios

· Web Dev Zone ·
Free Resource

Classify programming languages: Build a model that predicts a code's programming language based on its text.  Content provided by IBM Developer. 

This article represents different scenarios related with XSS (cross-site scripting) and how to handle them appropriately using AngularJS features such as SCE ($sceProvider) and sanitize service ($SanitizeProvider). Please feel free to comment/suggest if I missed to mention one or more important points. Also, sorry for the typos.
Following are the key XSS-related scenarios described later in this article:
  • Escape HTML completely
  • Insert HTML in Secure Way while ignoring elements such as “script”. This is as well dangerous and could deface your website, if not taken care, especially with “img” tag.
  • Trust and insert entire HTML; This is dangerous and could easily end-up defacing your website

Escape HTML using ng-bind directive

In case you want to escape HTML in entireity, you may want to use ng-bind directive. All it does is escape the HTML elements and print it as it is. Following code demonstrates the ng-bind directive usage.

<div>
<form>
<h1>AngularJS XSS Demo Test</h1>
<hr/>
<div class="col-md-12">
<input type="text" ng-model="name" class="form-control col-md-12" ng-change="processHtmlCode()" placeholder="Enter Some HTML Text..."/>
</div>
</form>
</div>
<hr/>
<div style="padding:20px">
<span><strong>ng-bind directive: Note that HTML text is entered as it is.</strong></span><br/>
<span ng-bind="helloMessage">{{helloMessage}}</span>
</div>

Following diagram demonstrates the above. Pay attention to the HTML code entered in the text field. It is printed as it is, on to the HTML page.

ng_bind_taj_mahal

Insert HTML in Secure Way, while Ignoring Elements such as “script”, using ng-bind-html Directive

This is key to solving XSS attacks. That said, one should still take care of elements such as “img” ( included as part of white-list; void elements) as it could display any image (including illegal ones) on your webpage, thus, defacing your webpage. Using ng-bind-html directive, javascript script tag such as “script” could be ignored straight-away. ng-bind-html directive evaluates the expression and inserts the resulting HTML into the element in a secure way. For cases where user inputs could consist of HTML (such as comments), the inclusion of ng-bind-html directive would ensure that the text is sanitize against a white-list of safe HTML tokens. The whitelist of safe tokens is coded as part of $sanitize module and mentioned below. Following is included in the safe list (taken directly from the source code):

  • Void elements: area,br,col,hr,img,wbr. The details of same could be found at http://dev.w3.org/html5/spec/Overview.html#void-elements
  • Block element: address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4, h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul
  • Inline elements: a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby, rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var
  • End Tag Elements: colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr,rp,rt. The details of same could be found at http://dev.w3.org/html5/spec/Overview.html#optional-tags

Following are two elements which are escaped as it is in untrusted category. In case, you want to show it, you would have to use $sce service and call trustAsHtml method for Angular to execute below-mentioned elements.

  • script
  • style

Following represents code sample demonstrating the ng-bind-html directive usage.

<div>
<form>
<h1>AngularJS XSS Demo Test</h1>
<hr/>
<div class="col-md-12">
<input type="text" ng-model="name" class="form-control col-md-12" ng-change="processHtmlCode()" placeholder="Enter Some HTML Text..."/>
</div>
</form>
</div>
<hr/>
<div style="padding:20px">
<span>ng-bind-html directive: Note that image is displayed appropriately as a result of text entered in the text field.</span>
<span ng-bind-html="helloMessage"></span>
</div>

Following image demonstrates how it looks like when entering HTML code in textfield that is inserted into DOM in a secure way. Pay attention to “img” element which is a part of Void elements in above list. As the code is entered in the textfield, the image appeared as “img” is in trusted list (white-list)

ng_bind_html_taj_mahal

Trust and Insert entire HTML

Warning: This is dangerous and could easily end-up defacing your website. Only when you know and are doubly sure, you should use trustAsHtml. In case, you are confident that the text content could be trusted, you could use $sce service and call trustAsHtml method which then inserts entire HTML into the DOM. Pay attention to the HTML and javascript code snippet where $sce service is used to invoke trustAsHtml method to trust the HTML code. In that case, one code such as “<style>.hello{color:red}</style>” is inserted, it ended up painting already existing HTML element. This may not be healthy. One could change the background images with illegal images that way.

<script type="text/javascript">
angular.module('HelloApp', ["ngSanitize"])
.controller('HelloCtrl', ['$scope', '$sce', function($scope, $sce){
$scope.name="";
$scope.processHtmlCode=function() {
$scope.helloMessage = "<h1>" + $scope.name + "</h1>";
$scope.trustedMessage =  $sce.trustAsHtml( $scope.name );
}
}])

</script>
<!-- Pay attention to class hello which is coded in UI and as a result, element is painted in red-->
<div style="padding:20px">
<span class="hello"><strong>ng-bind directive: Note that HTML text is entered as it is.</strong></span><br/>
<span class="hello" ng-bind="helloMessage">{{helloMessage}}</span>
</div>
<hr/>
<div style="padding:20px">
<span>Note that script tag is executed as well.</span>
<span ng-bind-html="trustedMessage"></span>
</div>

Following image demonstrates how it looks like when entering HTML style code in textfield that is inserted into DOM. As a result, the other HTML element is painted in red as shown below. In scenarios where a hacker could insert an style element with background, this could show-up unwanted background and bring bad experience for the end users.

ng_bind_html_trust_html

Entire Code – Cut/Copy and Paste and Play

<html>
<head>
<title>Hello AngularJS</title>
<link rel="stylesheet" type="text/css" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular-sanitize.min.js"></script>
</head>
<body class="container" ng-app="HelloApp" ng-controller="HelloCtrl">
<div>
<form>
<h1>AngularJS XSS Demo Test</h1>
<hr/>
<div class="col-md-12">
<input type="text" ng-model="name" class="form-control col-md-12" ng-change="processHtmlCode()" placeholder="Enter Some HTML Text..."/>
</div>
</form>
<hr/>
</div>
<hr/>
<div style="padding:20px">
<span class="hello"><strong>ng-bind directive: Note that HTML text is entered as it is.</strong></span><br/>
<span class="hello" ng-bind="helloMessage">{{helloMessage}}</span>
</div>
<hr/>
<div style="padding:20px">
<span>Note that script tag is executed as well.</span>
<span ng-bind-html="trustedMessage"></span>
</div>
<hr/>
<div style="padding:20px">
<span>ng-bind-html directive: Note that image is displayed appropriately as a result of text entered in the text field.</span>
<span ng-bind-html="helloMessage"></span>
</div>
<hr/>
<script type="text/javascript">
angular.module('HelloApp', ["ngSanitize"])
.controller('HelloCtrl', ['$scope', '$sce', function($scope, $sce){
$scope.name="";
$scope.processHtmlCode=function() {
$scope.helloMessage = "<h1>" + $scope.name + "</h1>";
$scope.trustedMessage =  $sce.trustAsHtml( $scope.name );
}
}])

</script>
</body>
</html>

Start coding something amazing with our library of open source Cloud code patterns. Content provided by IBM.

Topics:
html5 ,javascript ,xss ,web dev ,angularjs ,security

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}