Angular
The Checklist
Checklist da qui.
What is Angular
Angular è un framework front-end potente e open-source mantenuto da Google. Utilizza TypeScript per migliorare la leggibilità del codice e il debugging. Con forti meccanismi di sicurezza, Angular previene vulnerabilità comuni lato client come XSS e open redirects. Può essere utilizzato anche lato server, rendendo importanti le considerazioni sulla sicurezza da entrambi i lati.
Framework architecture
Per comprendere meglio le basi di Angular, esaminiamo i suoi concetti essenziali.
Un progetto Angular comune di solito appare così:
Secondo la documentazione, ogni applicazione Angular ha almeno un componente, il componente radice (AppComponent
) che collega una gerarchia di componenti con il DOM. Ogni componente definisce una classe che contiene dati e logica dell'applicazione ed è associato a un modello HTML che definisce una vista da visualizzare in un ambiente target. Il decoratore @Component()
identifica la classe immediatamente sottostante come un componente e fornisce il modello e i metadati specifici del componente correlati. L'AppComponent
è definito nel file app.component.ts
.
Gli NgModule di Angular dichiarano un contesto di compilazione per un insieme di componenti dedicato a un dominio dell'applicazione, a un flusso di lavoro o a un insieme di capacità strettamente correlate. Ogni applicazione Angular ha un modulo radice, convenzionalmente chiamato AppModule
, che fornisce il meccanismo di avvio che lancia l'applicazione. Un'applicazione contiene tipicamente molti moduli funzionali. L'AppModule
è definito nel file app.module.ts
.
Il NgModule Router
di Angular fornisce un servizio che consente di definire un percorso di navigazione tra i diversi stati dell'applicazione e le gerarchie di vista nella tua applicazione. Il RouterModule
è definito nel file app-routing.module.ts
.
Per dati o logica che non sono associati a una vista specifica e che desideri condividere tra i componenti, crei una classe di servizio. La definizione di una classe di servizio è immediatamente preceduta dal decoratore @Injectable()
. Il decoratore fornisce i metadati che consentono ad altri provider di essere iniettati come dipendenze nella tua classe. L'iniezione delle dipendenze (DI) ti consente di mantenere le classi dei componenti snelle ed efficienti. Non recuperano dati dal server, non convalidano l'input dell'utente e non registrano direttamente sulla console; delegano tali compiti ai servizi.
Configurazione del sourcemap
Il framework Angular traduce i file TypeScript in codice JavaScript seguendo le opzioni di tsconfig.json
e poi costruisce un progetto con la configurazione di angular.json
. Guardando il file angular.json
, abbiamo osservato un'opzione per abilitare o disabilitare un sourcemap. Secondo la documentazione di Angular, la configurazione predefinita ha un file sourcemap abilitato per gli script e non è nascosto per impostazione predefinita:
In generale, i file sourcemap sono utilizzati per scopi di debug in quanto mappano i file generati ai loro file originali. Pertanto, non è consigliabile utilizzarli in un ambiente di produzione. Se i sourcemap sono abilitati, migliorano la leggibilità e aiutano nell'analisi dei file replicando lo stato originale del progetto Angular. Tuttavia, se sono disabilitati, un revisore può comunque analizzare manualmente un file JavaScript compilato cercando schemi anti-sicurezza.
Inoltre, un file JavaScript compilato con un progetto Angular può essere trovato negli strumenti per sviluppatori del browser → Fonti (o Debugger e Fonti) → [id].main.js. A seconda delle opzioni abilitate, questo file può contenere la seguente riga alla fine //# sourceMappingURL=[id].main.js.map
oppure potrebbe non contenerla, se l'opzione hidden è impostata su true. Tuttavia, se il sourcemap è disabilitato per scripts, il testing diventa più complesso e non possiamo ottenere il file. Inoltre, il sourcemap può essere abilitato durante la costruzione del progetto come ng build --source-map
.
Data binding
Il binding si riferisce al processo di comunicazione tra un componente e la sua vista corrispondente. Viene utilizzato per trasferire dati da e verso il framework Angular. I dati possono essere passati attraverso vari mezzi, come eventi, interpolazione, proprietà o attraverso il meccanismo di binding bidirezionale. Inoltre, i dati possono essere condivisi tra componenti correlati (relazione genitore-figlio) e tra due componenti non correlati utilizzando la funzionalità Service.
Possiamo classificare il binding in base al flusso di dati:
Fonte dati a obiettivo vista (include interpolazione, proprietà, attributi, classi e stili); può essere applicato utilizzando
[]
o{{}}
nel template;Obiettivo vista a fonte dati (include eventi); può essere applicato utilizzando
()
nel template;Bidirezionale; può essere applicato utilizzando
[()]
nel template.
Il binding può essere chiamato su proprietà, eventi e attributi, così come su qualsiasi membro pubblico di una direttiva sorgente:
Property
Proprietà dell'elemento, Proprietà del componente, Proprietà della direttiva
<img [alt]="hero.name" [src]="heroImageUrl">
Event
Evento dell'elemento, Evento del componente, Evento della direttiva
<button type="button" (click)="onSave()">Salva
Two-way
Evento e proprietà
<input [(ngModel)]="name">
Attribute
Attributo (l'eccezione)
<button type="button" [attr.aria-label]="help">aiuto
Class
Proprietà di classe
<div [class.special]="isSpecial">Special
Style
Proprietà di stile
<button type="button" [style.color]="isSpecial ? 'red' : 'green'">
Modello di sicurezza di Angular
Il design di Angular include la codifica o la sanitizzazione di tutti i dati per impostazione predefinita, rendendo sempre più difficile scoprire e sfruttare le vulnerabilità XSS nei progetti Angular. Ci sono due scenari distinti per la gestione dei dati:
Interpolazione o
{{user_input}}
- esegue la codifica sensibile al contesto e interpreta l'input dell'utente come testo;
Risultato: <script>alert(1)</script><h1>test</h1>
2. Binding a proprietà, attributi, classi e stili o [attribute]="user_input"
- esegue la sanitizzazione in base al contesto di sicurezza fornito.
Risultato: <div><h1>test</h1></div>
Ci sono 6 tipi di SecurityContext
:
None
;HTML
viene utilizzato quando si interpreta il valore come HTML;STYLE
viene utilizzato quando si collega il CSS alla proprietàstyle
;URL
viene utilizzato per le proprietà URL, come<a href>
;SCRIPT
viene utilizzato per il codice JavaScript;RESOURCE_URL
come un URL che viene caricato ed eseguito come codice, ad esempio, in<script src>
.
Vulnerabilità
Bypass dei metodi di sicurezza Trust
Angular introduce un elenco di metodi per bypassare il suo processo di sanitizzazione predefinito e per indicare che un valore può essere utilizzato in modo sicuro in un contesto specifico, come nei seguenti cinque esempi:
bypassSecurityTrustUrl
viene utilizzato per indicare che il valore fornito è un URL di stile sicuro:
bypassSecurityTrustResourceUrl
viene utilizzato per indicare che il valore fornito è un URL di risorsa sicuro:
bypassSecurityTrustHtml
viene utilizzato per indicare che il valore fornito è HTML sicuro. Si noti che l'inserimento di elementiscript
nell'albero DOM in questo modo non causerà l'esecuzione del codice JavaScript racchiuso, a causa di come questi elementi vengono aggiunti all'albero DOM.
bypassSecurityTrustScript
viene utilizzato per indicare che il valore fornito è JavaScript sicuro. Tuttavia, abbiamo riscontrato che il suo comportamento è imprevedibile, poiché non siamo riusciti a eseguire codice JS nei template utilizzando questo metodo.
bypassSecurityTrustStyle
viene utilizzato per indicare che il valore fornito è CSS sicuro. Il seguente esempio illustra l'iniezione di CSS:
Angular fornisce un metodo sanitize
per sanitizzare i dati prima di visualizzarli nelle viste. Questo metodo utilizza il contesto di sicurezza fornito e purifica l'input di conseguenza. È, tuttavia, cruciale utilizzare il contesto di sicurezza corretto per i dati e il contesto specifici. Ad esempio, applicare un sanitizzatore con SecurityContext.URL
su contenuti HTML non fornisce protezione contro valori HTML pericolosi. In tali scenari, un uso improprio del contesto di sicurezza potrebbe portare a vulnerabilità XSS.
Iniezione HTML
Questa vulnerabilità si verifica quando l'input dell'utente è legato a una delle tre proprietà: innerHTML
, outerHTML
o iframe
srcdoc
. Mentre il binding a questi attributi interpreta l'HTML così com'è, l'input viene sanitizzato utilizzando SecurityContext.HTML
. Pertanto, è possibile l'iniezione di HTML, ma non il cross-site scripting (XSS).
Esempio di utilizzo di innerHTML
:
Il risultato è <div><h1>test</h1></div>
.
Iniezione di template
Rendering lato client (CSR)
Angular sfrutta i template per costruire pagine dinamicamente. L'approccio prevede di racchiudere le espressioni del template che Angular deve valutare all'interno di doppie parentesi graffe ({{}}
). In questo modo, il framework offre funzionalità aggiuntive. Ad esempio, un template come {{1+1}}
verrebbe visualizzato come 2.
Tipicamente, Angular esegue l'escape dell'input dell'utente che può essere confuso con le espressioni del template (ad es., caratteri come `< > ' " ``). Ciò significa che sono necessari ulteriori passaggi per eludere questa restrizione, come utilizzare funzioni che generano oggetti stringa JavaScript per evitare di utilizzare caratteri nella lista nera. Tuttavia, per ottenere ciò, dobbiamo considerare il contesto di Angular, le sue proprietà e variabili. Pertanto, un attacco di iniezione di template potrebbe apparire come segue:
Come mostrato sopra: constructor
si riferisce all'ambito della proprietà Object constructor
, consentendoci di invocare il costruttore String ed eseguire un codice arbitrario.
Rendering lato server (SSR)
A differenza del CSR, che si verifica nel DOM del browser, Angular Universal è responsabile per l'SSR dei file di template. Questi file vengono poi consegnati all'utente. Nonostante questa distinzione, Angular Universal applica gli stessi meccanismi di sanitizzazione utilizzati nel CSR per migliorare la sicurezza dell'SSR. Una vulnerabilità di iniezione di template nell'SSR può essere individuata nello stesso modo dell'SSR, poiché il linguaggio di template utilizzato è lo stesso.
Naturalmente, c'è anche la possibilità di introdurre nuove vulnerabilità di iniezione di template quando si utilizzano motori di template di terze parti come Pug e Handlebars.
XSS
Interfacce DOM
Come già affermato, possiamo accedere direttamente al DOM utilizzando l'interfaccia Document. Se l'input dell'utente non viene convalidato in anticipo, può portare a vulnerabilità di cross-site scripting (XSS).
Abbiamo utilizzato i metodi document.write()
e document.createElement()
negli esempi seguenti:
Classi Angular
Ci sono alcune classi che possono essere utilizzate per lavorare con gli elementi DOM in Angular: ElementRef
, Renderer2
, Location
e Document
. Una descrizione dettagliata delle ultime due classi è fornita nella sezione Open redirects. La principale differenza tra le prime due è che l'API Renderer2
fornisce uno strato di astrazione tra l'elemento DOM e il codice del componente, mentre ElementRef
tiene semplicemente un riferimento all'elemento. Pertanto, secondo la documentazione di Angular, l'API ElementRef
dovrebbe essere utilizzata solo come ultima risorsa quando è necessario un accesso diretto al DOM.
ElementRef
contiene la proprietànativeElement
, che può essere utilizzata per manipolare gli elementi DOM. Tuttavia, un uso improprio dinativeElement
può comportare una vulnerabilità di iniezione XSS, come mostrato di seguito:
Nonostante il fatto che
Renderer2
fornisca un'API che può essere utilizzata in modo sicuro anche quando l'accesso diretto agli elementi nativi non è supportato, presenta comunque alcune vulnerabilità di sicurezza. ConRenderer2
, è possibile impostare attributi su un elemento HTML utilizzando il metodosetAttribute()
, che non ha meccanismi di prevenzione XSS.
Per impostare la proprietà di un elemento DOM, puoi utilizzare il metodo
Renderer2.setProperty()
e innescare un attacco XSS:
Durante la nostra ricerca, abbiamo anche esaminato il comportamento di altri metodi Renderer2
, come setStyle()
, createComment()
, e setValue()
, in relazione a iniezioni XSS e CSS. Tuttavia, non siamo riusciti a trovare vettori di attacco validi per questi metodi a causa delle loro limitazioni funzionali.
jQuery
jQuery è una libreria JavaScript veloce, leggera e ricca di funzionalità che può essere utilizzata nel progetto Angular per aiutare nella manipolazione degli oggetti DOM HTML. Tuttavia, come è noto, i metodi di questa libreria possono essere sfruttati per ottenere una vulnerabilità XSS. Per discutere di come alcuni metodi vulnerabili di jQuery possano essere sfruttati nei progetti Angular, abbiamo aggiunto questa sottosezione.
Il metodo
html()
ottiene i contenuti HTML del primo elemento nel set di elementi corrispondenti o imposta i contenuti HTML di ogni elemento corrispondente. Tuttavia, per design, qualsiasi costruttore o metodo jQuery che accetta una stringa HTML può potenzialmente eseguire codice. Questo può verificarsi mediante l'iniezione di tag<script>
o l'uso di attributi HTML che eseguono codice, come mostrato nell'esempio.
Il metodo
jQuery.parseHTML()
utilizza metodi nativi per convertire la stringa in un insieme di nodi DOM, che possono poi essere inseriti nel documento.
Come accennato in precedenza, la maggior parte delle API jQuery che accettano stringhe HTML eseguiranno script inclusi nell'HTML. Il metodo jQuery.parseHTML()
non esegue script nell'HTML analizzato a meno che keepScripts
non sia esplicitamente true
. Tuttavia, è ancora possibile in molti ambienti eseguire script indirettamente; ad esempio, tramite l'attributo <img onerror>
.
Open redirects
Interfacce DOM
Secondo la documentazione W3C, gli oggetti window.location
e document.location
sono trattati come alias nei browser moderni. Ecco perché hanno implementazioni simili di alcuni metodi e proprietà, che potrebbero causare un open redirect e XSS DOM con attacchi di schema javascript://
come menzionato di seguito.
window.location.href
(edocument.location.href
)
Il modo canonico per ottenere l'oggetto posizione DOM corrente è utilizzare window.location
. Può anche essere utilizzato per reindirizzare il browser a una nuova pagina. Di conseguenza, avere il controllo su questo oggetto ci consente di sfruttare una vulnerabilità di open redirect.
Il processo di sfruttamento è identico per i seguenti scenari.
window.location.assign()
(edocument.location.assign()
)
Questo metodo fa sì che la finestra carichi e visualizzi il documento all'URL specificato. Se abbiamo il controllo su questo metodo, potrebbe essere un sink per un attacco di open redirect.
window.location.replace()
(edocument.location.replace()
)
Questo metodo sostituisce la risorsa corrente con quella all'URL fornito.
Ciò che differisce dal metodo assign()
è che dopo aver utilizzato window.location.replace()
, la pagina corrente non verrà salvata nella cronologia di sessione. Tuttavia, è anche possibile sfruttare una vulnerabilità di open redirect quando abbiamo il controllo su questo metodo.
window.open()
Il metodo window.open()
prende un URL e carica la risorsa che identifica in una nuova scheda o finestra esistente. Avere il controllo su questo metodo potrebbe anche essere un'opportunità per innescare una vulnerabilità XSS o open redirect.
Classi Angular
Secondo la documentazione di Angular, Angular
Document
è lo stesso del documento DOM, il che significa che è possibile utilizzare vettori comuni per il documento DOM per sfruttare vulnerabilità lato client in Angular. Le proprietà e i metodiDocument.location
potrebbero essere sink per attacchi di open redirect riusciti, come mostrato nell'esempio:
Durante la fase di ricerca, abbiamo anche esaminato la classe
Location
di Angular per vulnerabilità di open redirect, ma non sono stati trovati vettori validi.Location
è un servizio Angular che le applicazioni possono utilizzare per interagire con l'URL corrente del browser. Questo servizio ha diversi metodi per manipolare l'URL fornito -go()
,replaceState()
, eprepareExternalUrl()
. Tuttavia, non possiamo usarli per il reindirizzamento a un dominio esterno. Ad esempio:
Risultato: http://localhost:4200/http://google.com/about
La classe
Router
di Angular è principalmente utilizzata per la navigazione all'interno dello stesso dominio e non introduce vulnerabilità aggiuntive all'applicazione:
Risultato: http://localhost:4200/https:
I seguenti metodi navigano anche all'interno dell'ambito del dominio:
Riferimenti
Last updated