# Angular ## The Checklist Checklist [from here](https://lsgeurope.com/post/angular-security-checklist). * [ ] Angular é considerado um framework do lado do cliente e não se espera que forneça proteção do lado do servidor * [ ] Sourcemap para scripts está desativado na configuração do projeto * [ ] A entrada do usuário não confiável é sempre interpolada ou sanitizada antes de ser usada em templates * [ ] O usuário não tem controle sobre templates do lado do servidor ou do lado do cliente * [ ] A entrada do usuário não confiável é sanitizada usando um contexto de segurança apropriado antes de ser confiada pela aplicação * [ ] Métodos `BypassSecurity*` não são usados com entrada não confiável * [ ] A entrada do usuário não confiável não é passada para classes Angular como `ElementRef`, `Renderer2` e `Document`, ou outros sinks JQuery/DOM ## What is Angular Angular é um **poderoso** e **open-source** framework front-end mantido pelo **Google**. Ele usa **TypeScript** para melhorar a legibilidade do código e a depuração. Com mecanismos de segurança robustos, Angular previne vulnerabilidades comuns do lado do cliente, como **XSS** e **redirecionamentos abertos**. Ele também pode ser usado do **lado do servidor**, tornando as considerações de segurança importantes de **ambos os lados**. ## Framework architecture Para entender melhor os conceitos básicos do Angular, vamos passar por seus conceitos essenciais. Um projeto Angular comum geralmente se parece com: ```bash my-workspace/ ├── ... #workspace-wide configuration files ├── src │ ├── app │ │ ├── app.module.ts #defines the root module, that tells Angular how to assemble the application │ │ ├── app.component.ts #defines the logic for the application's root component │ │ ├── app.component.html #defines the HTML template associated with the root component │ │ ├── app.component.css #defines the base CSS stylesheet for the root component │ │ ├── app.component.spec.ts #defines a unit test for the root component │ │ └── app-routing.module.ts #provides routing capability for the application │ ├── lib │ │ └── src #library-specific configuration files │ ├── index.html #main HTML page, where the component will be rendered in │ └── ... #application-specific configuration files ├── angular.json #provides workspace-wide and project-specific configuration defaults └── tsconfig.json #provides the base TypeScript configuration for projects in the workspace ``` De acordo com a documentação, toda aplicação Angular possui pelo menos um componente, o componente raiz (`AppComponent`) que conecta uma hierarquia de componentes com o DOM. Cada componente define uma classe que contém dados e lógica da aplicação, e está associada a um template HTML que define uma visualização a ser exibida em um ambiente alvo. O decorador `@Component()` identifica a classe imediatamente abaixo dele como um componente e fornece o template e os metadados específicos do componente relacionados. O `AppComponent` é definido no arquivo `app.component.ts`. Os NgModules do Angular declaram um contexto de compilação para um conjunto de componentes que é dedicado a um domínio de aplicação, um fluxo de trabalho ou um conjunto de capacidades intimamente relacionadas. Toda aplicação Angular possui um módulo raiz, convencionalmente chamado de `AppModule`, que fornece o mecanismo de bootstrap que inicia a aplicação. Uma aplicação normalmente contém muitos módulos funcionais. O `AppModule` é definido no arquivo `app.module.ts`. O NgModule `Router` do Angular fornece um serviço que permite definir um caminho de navegação entre os diferentes estados da aplicação e hierarquias de visualização em sua aplicação. O `RouterModule` é definido no arquivo `app-routing.module.ts`. Para dados ou lógica que não estão associados a uma visualização específica e que você deseja compartilhar entre componentes, você cria uma classe de serviço. A definição da classe de serviço é imediatamente precedida pelo decorador `@Injectable()`. O decorador fornece os metadados que permitem que outros provedores sejam injetados como dependências em sua classe. A injeção de dependência (DI) permite que você mantenha suas classes de componente enxutas e eficientes. Elas não buscam dados do servidor, não validam a entrada do usuário e não registram diretamente no console; elas delegam tais tarefas a serviços. ## Configuração do sourcemap O framework Angular traduz arquivos TypeScript em código JavaScript seguindo as opções de `tsconfig.json` e, em seguida, constrói um projeto com a configuração de `angular.json`. Ao olhar para o arquivo `angular.json`, observamos uma opção para habilitar ou desabilitar um sourcemap. De acordo com a documentação do Angular, a configuração padrão tem um arquivo sourcemap habilitado para scripts e não está oculto por padrão: ```json "sourceMap": { "scripts": true, "styles": true, "vendor": false, "hidden": false } ``` Geralmente, arquivos sourcemap são utilizados para fins de depuração, pois mapeiam arquivos gerados para seus arquivos originais. Portanto, não é recomendado usá-los em um ambiente de produção. Se os sourcemaps estiverem habilitados, isso melhora a legibilidade e ajuda na análise de arquivos, replicando o estado original do projeto Angular. No entanto, se estiverem desabilitados, um revisor ainda pode analisar um arquivo JavaScript compilado manualmente, procurando por padrões anti-segurança. Além disso, um arquivo JavaScript compilado com um projeto Angular pode ser encontrado nas ferramentas de desenvolvedor do navegador → Fontes (ou Depurador e Fontes) → \[id].main.js. Dependendo das opções habilitadas, este arquivo pode conter a seguinte linha no final `//# sourceMappingURL=[id].main.js.map` ou pode não conter, se a opção **hidden** estiver definida como **true**. No entanto, se o sourcemap estiver desabilitado para **scripts**, o teste se torna mais complexo e não podemos obter o arquivo. Além disso, o sourcemap pode ser habilitado durante a construção do projeto, como `ng build --source-map`. ## Data binding Binding refere-se ao processo de comunicação entre um componente e sua respectiva visualização. É utilizado para transferir dados para dentro e para fora do framework Angular. Os dados podem ser passados por vários meios, como através de eventos, interpolação, propriedades ou através do mecanismo de binding bidirecional. Além disso, os dados também podem ser compartilhados entre componentes relacionados (relação pai-filho) e entre dois componentes não relacionados usando o recurso Service. Podemos classificar o binding pelo fluxo de dados: * Fonte de dados para alvo de visualização (inclui _interpolação_, _propriedades_, _atributos_, _classes_ e _estilos_); pode ser aplicado usando `[]` ou `{{}}` no template; * Alvo de visualização para fonte de dados (inclui _eventos_); pode ser aplicado usando `()` no template; * Bidirecional; pode ser aplicado usando `[()]` no template. O binding pode ser chamado em propriedades, eventos e atributos, bem como em qualquer membro público de uma diretiva de origem: | TIPO | ALVO | EXEMPLOS | | --------- | ------------------------------------------------------ | -------------------------------------------------------------------- | | Propriedade | Propriedade de elemento, Propriedade de componente, Propriedade de diretiva | \ | | Evento | Evento de elemento, Evento de componente, Evento de diretiva | \ ``` * Para definir a propriedade de um elemento DOM, você pode usar o método `Renderer2.setProperty()` e acionar um ataque XSS: ```tsx //app.component.ts import {Component, Renderer2, ElementRef, ViewChild, AfterViewInit } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { public constructor ( private renderer2: Renderer2 ){} @ViewChild("img") img!: ElementRef; setProperty(){ this.renderer2.setProperty(this.img.nativeElement, 'innerHTML', ''); } } //app.component.html ``` Durante nossa pesquisa, também examinamos o comportamento de outros métodos `Renderer2`, como `setStyle()`, `createComment()` e `setValue()`, em relação a injeções XSS e CSS. No entanto, não conseguimos encontrar vetores de ataque válidos para esses métodos devido às suas limitações funcionais. #### jQuery jQuery é uma biblioteca JavaScript rápida, pequena e rica em recursos que pode ser usada no projeto Angular para ajudar na manipulação dos objetos DOM HTML. No entanto, como é sabido, os métodos dessa biblioteca podem ser explorados para alcançar uma vulnerabilidade XSS. Para discutir como alguns métodos vulneráveis do jQuery podem ser explorados em projetos Angular, adicionamos esta subseção. * O método `html()` obtém o conteúdo HTML do primeiro elemento no conjunto de elementos correspondentes ou define o conteúdo HTML de cada elemento correspondente. No entanto, por design, qualquer construtor ou método jQuery que aceita uma string HTML pode potencialmente executar código. Isso pode ocorrer pela injeção de tags `"); }); } } //app.component.html

some text here

``` * O método `jQuery.parseHTML()` usa métodos nativos para converter a string em um conjunto de nós DOM, que podem ser inseridos no documento. ```tsx jQuery.parseHTML(data [, context ] [, keepScripts ]) ``` Como mencionado anteriormente, a maioria das APIs jQuery que aceitam strings HTML executará scripts que estão incluídos no HTML. O método `jQuery.parseHTML()` não executa scripts no HTML analisado, a menos que `keepScripts` seja explicitamente `true`. No entanto, ainda é possível na maioria dos ambientes executar scripts indiretamente; por exemplo, via o atributo ``. ```tsx //app.component.ts import { Component, OnInit } from '@angular/core'; import * as $ from 'jquery'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { ngOnInit() { $("button").on("click", function() { var $palias = $("#palias"), str = "", html = $.parseHTML(str), nodeNames = []; $palias.append(html); }); } } //app.component.html

some text

``` ### Redirecionamentos abertos #### Interfaces DOM De acordo com a documentação do W3C, os objetos `window.location` e `document.location` são tratados como aliases em navegadores modernos. É por isso que eles têm implementações semelhantes de alguns métodos e propriedades, o que pode causar um redirecionamento aberto e XSS DOM com ataques de esquema `javascript://`, conforme mencionado abaixo. * `window.location.href`(e `document.location.href`) A maneira canônica de obter o objeto de localização DOM atual é usando `window.location`. Ele também pode ser usado para redirecionar o navegador para uma nova página. Como resultado, ter controle sobre este objeto nos permite explorar uma vulnerabilidade de redirecionamento aberto. ```tsx //app.component.ts ... export class AppComponent { goToUrl(): void { window.location.href = "https://google.com/about" } } //app.component.html ``` O processo de exploração é idêntico para os seguintes cenários. * `window.location.assign()`(e `document.location.assign()`) Este método faz com que a janela carregue e exiba o documento na URL especificada. Se tivermos controle sobre este método, ele pode ser um ponto de entrada para um ataque de redirecionamento aberto. ```tsx //app.component.ts ... export class AppComponent { goToUrl(): void { window.location.assign("https://google.com/about") } } ``` * `window.location.replace()`(e `document.location.replace()`) Este método substitui o recurso atual pelo que está na URL fornecida. Isso difere do método `assign()` porque, após usar `window.location.replace()`, a página atual não será salva no histórico da sessão. No entanto, também é possível explorar uma vulnerabilidade de redirecionamento aberto quando temos controle sobre este método. ```tsx //app.component.ts ... export class AppComponent { goToUrl(): void { window.location.replace("http://google.com/about") } } ``` * `window.open()` O método `window.open()` recebe uma URL e carrega o recurso que identifica em uma nova aba ou janela existente. Ter controle sobre este método também pode ser uma oportunidade para acionar uma vulnerabilidade XSS ou de redirecionamento aberto. ```tsx //app.component.ts ... export class AppComponent { goToUrl(): void { window.open("https://google.com/about", "_blank") } } ``` #### Classes do Angular * De acordo com a documentação do Angular, o `Document` do Angular é o mesmo que o documento DOM, o que significa que é possível usar vetores comuns para o documento DOM para explorar vulnerabilidades do lado do cliente no Angular. As propriedades e métodos `Document.location` podem ser pontos de entrada para ataques de redirecionamento aberto, como mostrado no exemplo: ```tsx //app.component.ts import { Component, Inject } from '@angular/core'; import { DOCUMENT } from '@angular/common'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(@Inject(DOCUMENT) private document: Document) { } goToUrl(): void { this.document.location.href = 'https://google.com/about'; } } //app.component.html ``` * Durante a fase de pesquisa, também revisamos a classe `Location` do Angular em busca de vulnerabilidades de redirecionamento aberto, mas nenhum vetor válido foi encontrado. `Location` é um serviço do Angular que os aplicativos podem usar para interagir com a URL atual do navegador. Este serviço possui vários métodos para manipular a URL dada - `go()`, `replaceState()` e `prepareExternalUrl()`. No entanto, não podemos usá-los para redirecionar para um domínio externo. Por exemplo: ```tsx //app.component.ts import { Component, Inject } from '@angular/core'; import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [Location, {provide: LocationStrategy, useClass: PathLocationStrategy}], }) export class AppComponent { location: Location; constructor(location: Location) { this.location = location; } goToUrl(): void { console.log(this.location.go("http://google.com/about")); } } ``` Resultado: `http://localhost:4200/http://google.com/about` * A classe `Router` do Angular é usada principalmente para navegação dentro do mesmo domínio e não introduz vulnerabilidades adicionais ao aplicativo: ```jsx //app-routing.module.ts const routes: Routes = [ { path: '', redirectTo: 'https://google.com', pathMatch: 'full' }] ``` Resultado: `http://localhost:4200/https:` Os seguintes métodos também navegam dentro do escopo do domínio: ```jsx const routes: Routes = [ { path: '', redirectTo: 'ROUTE', pathMatch: 'prefix' } ] this.router.navigate(['PATH']) this.router.navigateByUrl('URL') ``` ## Referências * [Angular](https://angular.io/) * [Angular Security: The Definitive Guide (Part 1)](https://lsgeurope.com/post/angular-security-the-definitive-guide-part-1) * [Angular Security: The Definitive Guide (Part 2)](https://lsgeurope.com/post/angular-security-the-definitive-guide-part-2) * [Angular Security: The Definitive Guide (Part 3)](https://lsgeurope.com/post/angular-security-the-definitive-guide-part-3) * [Angular Security: Checklist](https://lsgeurope.com/post/angular-security-checklist) * [Workspace and project file structure](https://angular.io/guide/file-structure) * [Introduction to components and templates](https://angular.io/guide/architecture-components) * [Source map configuration](https://angular.io/guide/workspace-config#source-map-configuration) * [Binding syntax](https://angular.io/guide/binding-syntax) * [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) * [GitHub - angular/dom\_security\_schema.ts](https://github.com/angular/angular/blob/main/packages/compiler/src/schema/dom\_security\_schema.ts) * [XSS in Angular and AngularJS](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/XSS%20in%20Angular.md) * [Angular Universal](https://angular.io/guide/universal) * [DOM XSS](https://book.hacktricks.xyz/pentesting-web/xss-cross-site-scripting/dom-xss) * [Angular ElementRef](https://angular.io/api/core/ElementRef) * [Angular Renderer2](https://angular.io/api/core/Renderer2) * [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) * [Angular Document](https://angular.io/api/common/DOCUMENT) * [Angular Location](https://angular.io/api/common/Location) * [Angular Router](https://angular.io/api/router/Router)