Angular is a powerful front-end framework that is widely used for building dynamic web applications. It is open-source and maintained by Google. One of the key features of Angular is its use of TypeScript, a typed superset of JavaScript that makes code easier to read, maintain, and debug.
Angular's security mechanisms are designed to prevent common client-side vulnerabilities, including cross-site scripting (XSS) and open redirects. However, Angular can also be used on the server-side to generate static pages. Thus, the security of Angular should be considered from both sides.
├── angular.json #provides workspace-wide and project-specific configuration defaults
└── tsconfig.json #provides the base TypeScript configuration for projects in the workspace
```
According to the documentation, every Angular application has at least one component, the root component (`AppComponent`) that connects a component hierarchy with the DOM. Each component defines a class that contains application data and logic, and is associated with an HTML template that defines a view to be displayed in a target environment. The `@Component()` decorator identifies the class immediately below it as a component, and provides the template and related component-specific metadata. The `AppComponent` is defined in the `app.component.ts` file.
Angular NgModules declare a compilation context for a set of components that is dedicated to an application domain, a workflow, or a closely related set of capabilities. Every Angular application has a root module, conventionally named `AppModule`, which provides the bootstrap mechanism that launches the application. An application typically contains many functional modules. The `AppModule` is defined in the `app.module.ts` file.
The Angular `Router` NgModule provides a service that lets you define a navigation path among the different application states and view hierarchies in your application. The `RouterModule`is defined in the `app-routing.module.ts` file.
For data or logic that isn't associated with a specific view, and that you want to share across components, you create a service class. A service class definition is immediately preceded by the `@Injectable()` decorator. The decorator provides the metadata that allows other providers to be injected as dependencies into your class. Dependency injection (DI) lets you keep your component classes lean and efficient. They don't fetch data from the server, validate user input, or log directly to the console; they delegate such tasks to services.
Angular framework translates TypeScript files into JavaScript code by following `tsconfig.json` options and then builds a project with `angular.json` configuration. Looking at `angular.json` file, we observed an option to enable or disable a sourcemap. According to the Angular documentation, the default configuration has a sourcemap file enabled for scripts and is not hidden by default:
```json
"sourceMap": {
"scripts": true,
"styles": true,
"vendor": false,
"hidden": false
}
```
Generally, sourcemap files are utilized for debugging purposes as they map generated files to their original files. Therefore, it is not recommended to use them in a production environment. If sourcemaps are enabled, it improves the readability and aids in file analysis by replicating the original state of the Angular project. However, if they are disabled, a reviewer can still analyze a compiled JavaScript file manually by searching for anti-security patterns.
Furthemore, a compiled JavaScript file with an Angular project can be found in the browser developer tools → Sources (or Debugger and Sources) → \[id].main.js. Depending on the enabled options, this file may contain the following row in the end `//# sourceMappingURL=[id].main.js.map` or it may not, if the **hidden** option is set to **true**. Nonetheless, if the sourcemap is disabled for **scripts**, testing becomes more complex, and we cannot obtain the file. In addition, sourcemap can be enabled during project build like `ng build --source-map`.
Binding refers to the process of communication between a component and its corresponding view. It is utilized for transferring data to and from the Angular framework. Data can be passed through various means, such as through events, interpolation, properties, or through the two-way binding mechanism. Moreover, data can also be shared between related components (parent-child relation) and between two unrelated components using the Service feature.
* Data source to view target (includes _interpolation_, _properties_, _attributes_, _classes_ and _styles_); can be applied by using `[]` or `{{}}` in template;
* View target to data source (includes _events_); can be applied by using `()` in template;
* Two-Way; can be applied by using `[()]` in template.
Angular's design includes encoding or sanitization of all data by default, making it increasingly difficult to discover and exploit XSS vulnerabilities in Angular projects. There are two distinct scenarios for data handling:
The Angular introduces a list of methods to bypass its default sanitization process and to indicate that a value can be used safely in a specific context, as in the following five examples:
3.`bypassSecurityTrustHtml` is used to indicate the given value is safe HTML. Note that inserting `script` elements into the DOM tree in this way will not cause them to execute the enclosed JavaScript code, because of how these elements are added to the DOM tree.
4.`bypassSecurityTrustScript` is used to indicate the given value is safe JavaScript. However, we found its behavior to be unpredictable, because we couldn’t to execute JS code in templates using this method.
Angular provides a `sanitize` method to sanitize data before displaying it in views. This method employs the security context provided and cleanses the input accordingly. It is, however, crucial to use the correct security context for the specific data and context. For instance, applying a sanitizer with `SecurityContext.URL` on HTML content does not provide protection against dangerous HTML values. In such scenarios, misuse of security context could lead to XSS vulnerabilities.
This vulnerability occurs when user input is bound to any of the three properties: `innerHTML`, `outerHTML`, or `iframe``srcdoc`. While binding to these attributes interprets HTML as it is, the input is sanitized using `SecurityContext.HTML`. Thus, HTML injection is possible, but cross-site scripting (XSS) is not.
Angular leverages templates to construct pages dynamically. The approach entails enclosing template expressions for Angular to evaluate within double curly brackets (`{{}}`). In this way, the framework offers additional functionality. For instance, a template such as `{{1+1}}` would display as 2.
Typically, Angular escapes user input that can be confused with template expressions (e.g., characters such as \`< > ' " \`\`). It means that additional steps are required to circumvent this restriction, such as utilizing functions that generate JavaScript string objects to avoid using blacklisted characters. However, to achieve this, we must consider the Angular context, its properties, and variables. Therefore, a template injection attack may appear as follows:
As shown above: `constructor`refers to the scope of the Object `constructor` property, enabling us to invoke the String constructor and execute an arbitrary code.
Unlike CSR, which occurs in the browser’s DOM, Angular Universal is responsible for SSR of template files. These files are then delivered to the user. Despite this distinction, Angular Universal applies the same sanitization mechanisms used in CSR to enhance SSR security. A template injection vulnerability in SSR can be spotted in the same way as in CSR, because the used template language is the same.
Of course, there also is a possibility of introducing new template injection vulnerabilities when employing third-party template engines such as Pug and Handlebars.
As previously stated, we can directly access the DOM using the _Document_ interface. If user input is not validated beforehand, it can lead to cross-site scripting (XSS) vulnerabilities.
There are some classes that can be used to work with DOM elements in Angular: `ElementRef`, `Renderer2`, `Location` and `Document`. A detailed description of the last two classes is given in the **Open redirects** section. The main difference between the first two is that the `Renderer2` API provides a layer of abstraction between the DOM element and the component code, whereas `ElementRef` just holds a reference to the element. Therefore, according to Angular documentation, `ElementRef` API should only be used as a last resort when direct access to the DOM is needed.
*`ElementRef` contains the property `nativeElement`, which can be used to manipulate the DOM elements. However, improper usage of `nativeElement` can result in an XSS injection vulnerability, as shown below:
* Despite the fact that `Renderer2` provides API that can safely be used even when direct access to native elements is not supported, it still has some security flaws. With `Renderer2`, it is possible to set attributes on an HTML element using the `setAttribute()` method, which has no XSS prevention mechanisms.
During our research, we also examined the behavior of other `Renderer2` methods, such as `setStyle()`, `createComment()`, and `setValue()`, in relation to XSS and CSS injections. However, we were unable to find any valid attack vectors for these methods due to their functional limitations.
jQuery is a fast, small, and feature-rich JavaScript library that can be used in the Angular project to help with manipulation the HTML DOM objects. However, as it is known, this library’s methods may be exploited to achieve an XSS vulnerability. In order to discuss how some vulnerable jQuery methods can be exploited in Angular projects, we added this subsection.
* The `html()` method gets the HTML contents of the first element in the set of matched elements or sets the HTML contents of every matched element. However, by design, any jQuery constructor or method that accepts an HTML string can potentially execute code. This can occur by injection of `<script>` tags or use of HTML attributes that execute code as shown in the example.
As mentioned before, most jQuery APIs that accept HTML strings will run scripts that are included in the HTML. The `jQuery.parseHTML()` method does not run scripts in the parsed HTML unless `keepScripts` is explicitly `true`. However, it is still possible in most environments to execute scripts indirectly; for example, via the `<img onerror>` attribute.
According to the W3C documentation, the `window.location` and `document.location` objects are treated as aliases in modern browsers. That is why they have similar implementation of some methods and properties, which might cause an open redirect and DOM XSS with `javascript://` schema attacks as mentioned below.
The canonical way to get the current DOM location object is using `window.location`. It can also be used to redirect the browser to a new page. As a result, having control over this object allows us to exploit an open redirect vulnerability.
This method causes the window to load and display the document at the URL specified. If we have control over this method, it might be a sink for an open redirect attack.
This method replaces the current resource with the one at the provided URL.
This differs from the `assign()` method is that after using `window.location.replace()`, the current page will not be saved in session History. However, it is also possible to exploit an open redirect vulnerability when we have control over this method.
The `window.open()` method takes a URL and loads the resource it identifies into a new or existing tab or window. Having control over this method might also be an opportunity to trigger an XSS or open redirect vulnerability.
* According to Angular documentation, Angular `Document` is the same as the DOM document, which means it is possible to use common vectors for the DOM document to exploit client-side vulnerabilities in the Angular. `Document.location` properties and methods might be sinks for successful open redirect attacks as shown in the example:
* During the research phase, we also reviewed Angular `Location` class for open redirect vulnerabilities, but no valid vectors were found. `Location` is an Angular service that applications can use to interact with a browser's current URL. This service has several methods to manipulate the given URL - `go()` , `replaceState()`, and `prepareExternalUrl()`. However, we cannot use them for redirection to the external domain. For example:
* The Angular `Router` class is primarily used for navigating within the same domain and does not introduce any additional vulnerabilities to the application:
* [Angular Context: Easy Data-Binding for Nested Component Trees and the Router Outlet](https://medium.com/angular-in-depth/angular-context-easy-data-binding-for-nested-component-trees-and-the-router-outlet-a977efacd48)
* [Sanitization and security contexts](https://angular.io/guide/security#sanitization-and-security-contexts)
* [Renderer2 Example: Manipulating DOM in Angular - TekTutorialsHub](https://www.tektutorialshub.com/angular/renderer2-angular/)
* [jQuery API Documentation](http://api.jquery.com/)
* [How To Use jQuery With Angular (When You Absolutely Have To)](https://blog.bitsrc.io/how-to-use-jquery-with-angular-when-you-absolutely-have-to-42c8b6a37ff9)