Testing
AngularJS
SecurityJosé Manuel Ortega
@jmortegac
iNDEX
• Authenticate users API
• Securing Admin pages
• CSRF,XSS Prevention
• Sanitize Module
• Security Audit Tools
• OWASP
Authenticate users API
POST /register
POST /login
POST /logout
GET /status # returns 401 or the authenticated user
Login controller
Session service
Represent the user’s session
Session service
Session management global config
$rootScope.$on('Auth:Required', function() {
$location.path('/login');
});
$rootScope.$on('Auth:Login', function() {
$location.path('/');
});
$rootScope.$on('Auth:Logout', function() {
StorageService.clear(); // clear user info
$rootScope.$broadcast('Auth:Required');});
Authentication Interceptor config
factory('AuthInterceptor', ['$q', '$rootScope', function($q, $rootScope) {
return {
'responseError': function(rejection) {
if (rejection.status === 401) {
$rootScope.$broadcast('Auth:Required');
}
return $q.reject(rejection);
}
}
}])
Authentication controller
Auth Service
Securing admin pages
.service("AuthService", function() {
var data = {};
data.checkAuth = function() {return true;}
return data;
})
.when("/admin", {
templateUrl: “admin.html",
controller: “adminController",
resolve: {
checkAuth: function(AuthService){
return AuthService.checkAuth();
}
}
})
Securing admin pages
controller(“adminController", function ($scope, checkAuth) {
$scope.isAuthenticated = checkAuth;
});
Browser risks
• Cross Site Scripting(XSS)
• Cross-Site Request Forgery(CSRF)
CSRF Prevention
• XSRF token
• Inject in HTTP Forms
• Protected from Cross-Site Request Forgery attack
• XSRF-TOKEN → HTTP HEADER X-XSRF-TOKEN
• Set a domain cookie in the request
• Validate the header with the content the cookie
• Used for authorize requests from the user
CSRF Prevention
XSRF Token
XSRF Token
• When using $http ,Angular automatically look for
a cookie called XSRF-TOKEN
• If this cookie is found,when make a request add
this information in the request-header
• This header is sent to the server,at the token can
be validated
• The API can verify that the token is correct for the
current user
• Server sends success or failure
Module CSURF
app.js
var csrf = require("csurf"); //require package
app.use(csrf()); //initialize
//middleware for every http request
app.use(function(req, res, next) {
res.cookie("XSRF-TOKEN", req.csrfToken());
next();});
CSRF Interceptor
'responseError': function(rejection) {
var statusCode = rejection.status;
var config = rejection.config;
// Check if XSRF token is invalid
if (statusCode === 403 && rejection.data === 'XsrfToken.Invalid') {
// Handle invalid token
}
return $q.reject(rejection);
}
}
Http Interceptor - Handle invalid token responses
CSRF Interceptor
var deferred = $q.defer();
var req = {config: config, deferred: deferred}
if (angular.isUndefined($rootScope.pendingRequests)) {
$rootScope.pendingRequests = [];
}
$rootScope.pendingRequests.push(req);
// Raise an event
$rootScope.$broadcast('XsrfToken:Invalid');
return deferred.promise;
Store the original request and the promise
CSRF Interceptor
$rootScope.$on('XsrfToken:Invalid', function() {
Security.status().then(function() {
$rootScope.$broadcast('XsrfToken:Valid');
});
});
Store the original request and the promise
CSRF Interceptor
$rootScope.$on('XsrfToken:Valid', function() {
var i, requests = $rootScope.pendingRequests ?
$rootScope.pendingRequests : [];
for (i = 0; i < requests.length; i++) {
retry(requests.pop());
}
function retry(req) {
$http(req.config).then(function(response) {
req.deferred.resolve(response);
});
}
});
Resume the pending requests
XSS Protection
For XSS protection, AngularJS uses Strict Contextual Escaping (SCE). We
need to include $sce service to the code. SCE defines a trust in different
context.
Since 1.3, the HTML compiler will escape all {{}} & ngbind by
default
https://www.ng-book.com/p/Security
http://java.dzone.com/articles/angularjs-how-handle-xss
Sanitize
• The ngSanitize module provides functionality to sanitize
HTML.
• Avoid Cross Site Scripting(XSS) attacks
• Requires angular-sanitize.js
• Provides ng-bind-html directive for sanitize HTML filtering
the javascript code
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular-
sanitize.js"></script>
ngSanitize && SCE
• The input is sanitized by parsing the HTML into tokens.
• All safe tokens are then serialized back to properly
escaped html string
• SCE(Strict Contextual Escaping) is a mode in wich
AngularJS requires binding in certain contexts to result
in a value that is marked as safe to use for that context.
Strict Contextual Escaping Service
Strict Contextual Escaping Service
var data ='<b onmouseover="alert(\'over\')">trust
me</b>:<script>alert("XSS");</script> <xss>XSS</xss>';
$scope.untrusted = data;
$scope.sanitized = $sanitize(data);
$scope.trusted = $sce.trustAsHtml(data);
{{ untrusted }}
<span ng-bind-html="sanitized"></span>
<span ng-bind-html="trusted"></span>
ng-bind-html .vs. ng-bind
<div ng-bind-html="to_trusted(msg)">
</div>
• ng-bind-htmlAutomatically uses $sanitize
• <p ng-bind="msg"></p> Hello, <b>World</b>!
• <p ng-bind-html="msg"></p> Hello, World!
Retire.js
• Detecting components and JavaScript libraries with
known vulnerabilities
• https://raw.githubusercontent.com/RetireJS/retire.js/m
aster/repository/jsrepository.json
• Retire.js has these parts:• A command line scanner
• A grunt plugin
• A Chrome plugin
• A Firefox plugin
• Burp and OWASP Zap plugin
Build a secure HTTPS Server
var https = require('https');
var privateKey =
fs.readFileSync('cert/privatekey.pem').toString();
var certificate =
fs.readFileSync('cert/certificate.pem').toString();
var credentials = {key: privateKey, cert: certificate};
var secureServer = https.createServer(credentials, app);
secureServer.listen(config.server.securePort); //443
Build a secure HTTPS Server
https-redirect-server
https://www.npmjs.com/package/https-redirect-server
A node module to redirect all traffic to https and a
secure port.
Security Audit Tools
Securing Headers
Security Audit Tools
Security Audit Tools
Security Audit Tools
JWT
• JSON Web Token
• Avoid CSRF and XSS
• angular-jwt
JWT
• Store the token from service response
• Sending the token at each request with interceptor
$http(...).then(function(response) {
currentToken.jwt =response.data.access_token;
}
angular.module('myApp')
.config(function ($httpProvider,jwtInterceptorProvider) {
jwtInterceptorProvider.tokenGetter=['currentToken',function(current
Token) {return currentToken.jwt;}];
$httpProvider.interceptors.push('jwtInterceptor');
});
OWASP
• Open Web Application Security Project
• Online community dedicated to web application security
• Identify Vulnerabilities
• Document Best Practices
• Repository with use cases
• https://github.com/hakanson/ng-owasp
Recommendations
• Access control input validation and security decisions
must be made on the server.
• Handle untrusted data with care
• Use contextual encoding and avoid building code from
strings.
• Protect your services
• Learn how to use security HTTP headers
Conclusions
• Angular is a purely client side framework
• There are risks in the client that are discret to the
network and server
• The client and the network are not in your control!
• Protect the server!
Links & References
https://docs.angularjs.org/api/ng/service/$sce
https://docs.angularjs.org/guide/security
https://docs.angularjs.org/api/ngSanitize
https://code.google.com/p/mustache-security/wiki/AngularJS.wiki
https://www.ng-book.com/p/Security
https://github.com/fnakstad/angular-client-side-auth
https://github.com/auth0/angular-jwt
http://retirejs.github.io/retire.js
https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project
Youtube videos
Security in the world of JS frameworks
https://www.youtube.com/watch?v=4Qs5mqa4ioU
Top 10 Security Risks for AngularJS Applications
https://www.youtube.com/watch?v=6uloYE87pkk
JS Security - A Pentesters Perspective
https://www.youtube.com/watch?v=LVamMYljS4Q
Top Related