# Angular ## Ο Έλεγχος Έλεγχος [από εδώ](https://lsgeurope.com/post/angular-security-checklist). * [ ] Το Angular θεωρείται ένα πλαίσιο εργασίας που εκτελείται στην πλευρά του πελάτη και δεν προσφέρει προστασία στην πλευρά του διακομιστή * [ ] Το Sourcemap για τα scripts είναι απενεργοποιημένο στη διαμόρφωση του έργου * [ ] Το μη αξιόπιστο εισερχόμενο δεδομένο πάντα αναπτύσσεται ή απολυμαίνεται πριν χρησιμοποιηθεί στα πρότυπα * [ ] Ο χρήστης δεν έχει έλεγχο στα πρότυπα της πλευράς του διακομιστή ή της πλευράς του πελάτη * [ ] Το μη αξιόπιστο εισερχόμενο δεδομένο απολυμαίνεται χρησιμοποιώντας ένα κατάλληλο περιβάλλον ασφαλείας πριν εμπιστευτείται από την εφαρμογή * [ ] Οι μέθοδοι `BypassSecurity*` δεν χρησιμοποιούνται με μη αξιόπιστα δεδομένα * [ ] Το μη αξιόπιστο εισερχόμενο δεδομένο δεν περνά σε κλάσεις Angular όπως `ElementRef`, `Renderer2` και `Document`, ή άλλες πηγές JQuery/DOM ## Τι είναι το Angular Το Angular είναι ένα **ισχυρό** και **ανοιχτού κώδικα** πλαίσιο εργασίας προσκολλημένο από την **Google**. Χρησιμοποιεί την **TypeScript** για να βελτιώσει την αναγνωσιμότητα και την αποσφαλμάτωση του κώδικα. Με ισχυρούς μηχανισμούς ασφαλείας, το Angular αποτρέπει κοινές ευπάθειες στην πλευρά του πελάτη όπως **XSS** και **ανοιχτές ανακατευθύνσεις**. Μπορεί επίσης να χρησιμοποιηθεί και στην πλευρά του διακομιστή, καθιστώντας τις αναλύσεις ασφαλείας σημαντικές από **και τις δύο πλευρές**. ## Αρχιτεκτονική πλαισίου Για να κατανοήσουμε καλύτερα τα βασικά στοιχεία του Angular, ας δούμε τα ουσιώδη έννοια του. Ένα κοινό έργο Angular συνήθως φαίνεται όπως: ```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 ``` Σύμφωνα με την τεκμηρίωση, κάθε εφαρμογή Angular έχει τουλάχιστον έναν συστατικό, τον κύριο συστατικό (`AppComponent`) που συνδέει μια ιεραρχία συστατικών με το DOM. Κάθε συστατικό καθορίζει μια κλάση που περιέχει δεδομένα και λογική εφαρμογής και συσχετίζεται με ένα πρότυπο HTML που καθορίζει μια προβολή που θα εμφανίζεται σε έναν στόχο περιβάλλον. Ο διακοσμητής `@Component()` αναγνωρίζει την κλάση αμέσως κάτω από αυτόν ως συστατικό και παρέχει το πρότυπο και τα σχετικά με το συστατικό μεταδεδομένα. Ο `AppComponent` καθορίζεται στο αρχείο `app.component.ts`. Τα Angular NgModules δηλώνουν ένα περιβάλλον συλλογής για ένα σύνολο συστατικών που είναι αφιερωμένο σε έναν τομέα εφαρμογής, ένα ροή εργασίας ή ένα στενά συνδεδεμένο σύνολο δυνατοτήτων. Κάθε εφαρμογή Angular έχει ένα ριζικό module, συμβατικά με το όνομα `AppModule`, το οποίο παρέχει το μηχανισμό εκκίνησης που εκκινεί την εφαρμογή. Μια εφαρμογή συνήθως περιέχει πολλά λειτουργικά modules. Το `AppModule` καθορίζεται στο αρχείο `app.module.ts`. Το NgModule `Router` του Angular παρέχει έναν υπηρεσία που σας επιτρέπει να καθορίσετε ένα μονοπάτι πλοήγησης μεταξύ των διάφορων καταστάσεων εφαρμογής και ιεραρχιών προβολής στην εφαρμογή σας. Το `RouterModule` καθορίζεται στο αρχείο `app-routing.module.ts`. Για δεδομένα ή λογική που δεν συσχετίζονται με μια συγκεκριμένη προβολή και που θέλετε να κοινοποιήσετε σε όλα τα συστατικά, δημιουργείτε μια κλάση υπηρεσίας. Η ορισμένη κλάση υπηρεσίας προηγείται αμέσως από τον διακοσμητή `@Injectable()`. Ο διακοσμητής παρέχει τα μεταδεδομένα που επιτρέπουν την εισαγωγή άλλων παρόχων ως εξαρτήσεις στην κλάση σας. Η εισαγωγή εξαρτήσεων (DI) σας επιτρέπει να κρατήσετε τις κλάσεις συστατικών σας απλές και αποδοτικές. Δεν ανακτούν δεδομένα από τον διακομιστή, επικυρώνουν την είσοδο του χρήστη ή καταγράφουν απευθείας στην κονσόλα. Αναθέτουν τέτοιες εργασίες σε υπηρεσίες. ## Ρύθμιση του Sourcemap Το πλαίσιο Angular μεταφράζει τα αρχεία TypeScript σε κώδικα JavaScript ακολουθώντας τις επιλογές του `tsconfig.json` και στη συνέχεια κατασκευάζει ένα έργο με τη διαμόρφωση του `angular.json`. Κοιτώντας το αρχείο `angular.json`, παρατηρήσαμε μια επιλογή για ενεργοποίηση ή απενεργοποίηση ενός αρχείου sourcemap. Σύμφωνα με την τεκμηρίωση του Angular, η προεπιλεγμένη ρύθμιση έχει ενεργοποιημένο ένα αρχείο sourcemap για τα scripts και δεν είναι κρυφό από προεπιλογή: ```json "sourceMap": { "scripts": true, "styles": true, "vendor": false, "hidden": false } ``` Γενικά, τα αρχεία sourcemap χρησιμοποιούνται για σκοπούς αποσφαλμάτωσης καθώς αντιστοιχίζουν τα παραγόμενα αρχεία στα αρχικά τους αρχεία. Επομένως, δεν συνιστάται η χρήση τους σε ένα περιβάλλον παραγωγής. Εάν είναι ενεργοποιημένα τα sourcemaps, βελτιώνεται η αναγνωσιμότητα και βοηθά στην ανάλυση των αρχείων αναπαράγοντας την αρχική κατάσταση του έργου Angular. Ωστόσο, εάν είναι απενεργοποιημένα, ένας αναθεωρητής μπορεί ακόμα να αναλύσει ένα μεταγλωττισμένο αρχείο JavaScript χειροκίνητα αναζητώντας αντι-ασφαλείας πρότυπα. Επιπλέον, ένα μεταγλωττισμένο αρχείο JavaScript με ένα έργο Angular μπορεί να βρεθεί στα εργαλεία ανάπτυξης του προγράμματος περιήγησης → Πηγές (ή Αποσφαλμάτωση και Πηγές) → \[id].main.js. Ανάλογα με τις ενεργοποιημένες επιλογές, αυτό το αρχείο μπορεί να περιέχει την ακόλουθη γραμμή στο τέλος `//# sourceMappingURL=[id].main.js.map` ή μπορεί να μην την περιέχει, εάν η επιλογή **hidden** έχει τεθεί σε **true**. Ωστόσο, εάν το sourcemap είναι απενεργοποιημένο για τα **scripts**, η δοκιμή γίνεται πιο περίπλοκη και δεν μπορούμε να αποκτήσουμε το αρχείο. Επιπλέον, το sourcemap μπορεί να ενεργοποιηθεί κατά την δημιουργία του έργου όπως `ng build --source-map`. ## Δέσμευση δεδομένων Η δέσμευση αναφέρεται στη διαδικασία επικοινωνίας μεταξύ ενός στοιχείου και της αντίστοιχης προβολής του. Χρησιμοποιείται για τη μεταφορά δεδομένων προς και από το πλαίσιο Angular. Τα δεδομένα μπορούν να περάσουν μέσω διάφορων μέσων, όπως μέσω γεγονότων, αναπλήρωσης, ιδιοτήτων ή μέσω του μηχανισμού διπλής κατεύθυνσης. Επιπλέον, τα δεδομένα μπορούν επίσης να κοινοποιηθούν μεταξύ σχετικών στοιχείων (γονέας-παιδί) και μεταξύ δύο ασυνδετων στοιχείων χρησιμοποιώντας τη δυνατότητα Υπηρεσίας. Μπορούμε να κατηγοριοποιήσουμε τη δέσμευση ανά ροή δεδομένων: * Πηγή δεδομένων προς στόχο προβολής (περιλαμβάνει _αναπλήρωση_, _ιδιότητες_, _χαρακτηριστικά_, _κλάσεις_ και _στυλ_); μπορεί να εφαρμοστεί χρησιμοποιώντας `[]` ή `{{}}` στο πρότυπο; * Στόχος προβολής προς πηγή δεδομένων (περιλαμβάνει _γεγονότα_); μπορεί να εφαρμοστεί χρησιμοποιώντας `()` στο πρότυπο; * Διπλής κατεύθυνσης; μπορεί να εφαρμοστεί χρησιμοποιώντας `[()]` στο πρότυπο. Η δέσμευση μπορεί να γίνει σε ιδιότητες, γεγονότα και χαρακτηριστικά, καθώς και σε οποιοδήποτε δημόσιο μέλος ενός οδηγού πηγής: | ΤΥΠΟΣ | ΣΤΟΧΟΣ | ΠΑΡΑΔΕΙΓΜΑΤΑ | | --------- | -------------------------------------------------------- | -------------------------------------------------------------------- | | Ιδιότητα | Ιδιότητα στοιχείου, Ιδιότητα στοιχείου, Ιδιότητα οδηγού | \ | | Γεγονός | Γεγονός στοιχείου, Γεγονός στοιχείου, Γεγονός οδηγού | \ ``` * Για να ορίσετε το ιδιότητα ενός στοιχείου DOM, μπορείτε να χρησιμοποιήσετε τη μέθοδο `Renderer2.setProperty()` και να εκτελέσετε μια επίθεση 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 ``` Κατά τη διάρκεια της έρευνάς μας, εξέτασαμε επίσης τη συμπεριφορά άλλων μεθόδων της `Renderer2`, όπως οι `setStyle()`, `createComment()` και `setValue()`, σε σχέση με τις ενέσεις XSS και CSS. Ωστόσο, δεν καταφέραμε να βρούμε κανένα έγκυρο διάνυσμα επίθεσης για αυτές τις μεθόδους λόγω των λειτουργικών περιορισμών τους. #### jQuery Το jQuery είναι μια γρήγορη, μικρή και πλούσια σε δυνατότητες βιβλιοθήκη JavaScript που μπορεί να χρησιμοποιηθεί στο έργο Angular για να βοηθήσει στην επεξεργασία των αντικειμένων HTML DOM. Ωστόσο, όπως είναι γνωστό, οι μέθοδοι αυτής της βιβλιοθήκης μπορούν να εκμεταλλευτούνται για να προκαλέσουν μια ευπάθεια XSS. Για να συζητήσουμε πώς μερικές ευπάθειες μεθόδων του jQuery μπορούν να εκμεταλλευτούν σε έργα Angular, προσθέσαμε αυτήν την υποενότητα. * Η μέθοδος `html()` αποκτά το περιεχόμενο HTML του πρώτου στοιχείου στο σύνολο των ταιριαστών στοιχείων ή ορίζει το περιεχόμενο HTML κάθε ταιριαστού στοιχείου. Ωστόσο, κατά σχεδιασμό, οποιαδήποτε κατασκευή ή μέθοδος του jQuery που δέχεται μια συμβολοσειρά HTML μπορεί δυνητικά ν #### Κλάσεις Angular * Σύμφωνα με την τεκμηρίωση του Angular, η κλάση `Document` του Angular είναι ίδια με το DOM document, πράγμα που σημαίνει ότι είναι δυνατή η χρήση κοινών διανυσμάτων για το DOM document για την εκμετάλλευση ευπαθειών πελάτη στο Angular. Οι ιδιότητες και οι μέθοδοι του `Document.location` μπορεί να αποτελέσουν σημεία εισροής για επιτυχημένες επιθέσεις ανακατεύθυνσης όπως φαίνεται στο παράδειγμα: ```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 ``` * Κατά τη φάση της έρευνας, εξέτασαμε επίσης την κλάση `Location` του Angular για ευπάθειες ανοικτής ανακατεύθυνσης, αλλά δεν βρέθηκαν έγκυρα διανύσματα. Η `Location` είναι ένα υπηρεσία του Angular που οι εφαρμογές μπορούν να χρησιμοποιήσουν για να αλληλεπιδράσουν με τον τρέχοντα URL του προγράμματος περιήγησης. Αυτή η υπηρεσία έχει αρκετές μεθόδους για την επεξεργασία του δοθέντος URL - `go()`, `replaceState()`, και `prepareExternalUrl()`. Ωστόσο, δεν μπορούμε να τις χρησιμοποιήσουμε για ανακατεύθυνση σε εξωτερικό τομέα. Για παράδειγμα: ```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")); } } ``` Αποτέλεσμα: `http://localhost:4200/http://google.com/about` * Η κλάση `Router` του Angular χρησιμοποιείται κυρίως για την πλοήγηση εντός του ίδιου τομέα και δεν εισάγει καμία επιπλέον ευπάθεια στην εφαρμογή: ```jsx //app-routing.module.ts const routes: Routes = [ { path: '', redirectTo: 'https://google.com', pathMatch: 'full' }] ``` Αποτέλεσμα: `http://localhost:4200/https:` Οι παρακάτω μέθοδοι πλοήγησης επίσης λειτουργούν εντός του πεδίου του τομέα: ```jsx const routes: Routes = [ { path: '', redirectTo: 'ROUTE', pathMatch: 'prefix' } ] this.router.navigate(['PATH']) this.router.navigateByUrl('URL') ``` ## Αναφορές * [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)