Chrome Geliştirici Araçları'nda İGP ve Trusted Types hata ayıklamasını uygulama

Kateryna Prokopenko
Kateryna Prokopenko
Alfonso Castaño
Alfonso Castaño

Bu blog yayınında, yakın zamanda kullanıma sunulan Sorunlar sekmesinin yardımıyla İçerik Güvenliği Politikası (İGP) sorunlarını ayıklamak için Geliştirici Araçları desteğinin uygulanması ele alınmaktadır.

Uygulama çalışması 2 staj kapsamında yapıldı: 1. İlk aşamada genel raporlama çerçevesini oluşturduk ve 3 CSP ihlali sorunu için sorun mesajlarını tasarladık. 2. İkinci aşamada, Güvenilir Türler ile ilgili sorunların yanı sıra Güvenilir Türler'de hata ayıklama için bazı özel Geliştirici Araçları özellikleri ekledik.

İçerik Güvenliği Politikası nedir?

İçerik Güvenliği Politikası (İGP), güvenliği artırmak için bir web sitesindeki belirli davranışları kısıtlamaya olanak tanır. Örneğin, CSP satır içi komut dosyalarını veya eval'yi devre dışı bırakmak için kullanılabilir. Bu iki yöntem de siteler arası komut dosyası çalıştırma (XSS) saldırılarının saldırı yüzeyini azaltır. CSP hakkında ayrıntılı bilgi için bu makaleyi okuyun.

Özellikle yeni bir CSP, web sitelerindeki büyük bir ekleme saldırısı sınıfını sistematik olarak önleyebilen dinamik bir analiz sağlayan Güvenilir Türler(TT) politikasıdır. Bunu başarmak için TT, bir web sitesinin JavaScript kodunu denetleyerek yalnızca belirli türdeki öğelerin innerHTML gibi DOM havuzlarına atanmasına izin verir.

Web siteleri, belirli bir HTTP başlığı ekleyerek içerik güvenliği politikasını etkinleştirebilir. Örneğin, başlık content-security-policy: require-trusted-types-for 'script'; trusted-types default bir sayfa için TT politikasını etkinleştirir.

Her politika aşağıdaki modlardan birinde çalışabilir:

  • Zorunlu mod: Her politika ihlalinin hata olarak kabul edildiği mod.
  • Yalnızca raporlama modu: Hata mesajını uyarı olarak bildirir ancak web sayfasında hataya neden olmaz.

Sorunlar sekmesinde İçerik Güvenliği Politikası sorunlarını uygulama

Bu çalışmanın amacı, İGP sorunlarıyla ilgili hata ayıklama deneyimini iyileştirmekti. Geliştirici Araçları ekibi, yeni sorunları değerlendirirken kabaca şu süreci izler:

  1. Kullanıcı hikayelerini tanımlama. Geliştirici Araçları ön ucunda, bir web geliştiricisinin sorunu nasıl araştırması gerektiğini kapsayan bir dizi kullanıcı hikayesi belirleyin.
  2. Ön uç uygulaması. Kullanıcı hikayelerine dayanarak, ön uçtaki sorunun araştırılması için hangi bilgilerin gerekli olduğunu belirleyin (ör.ilgili bir istek, bir çerezin adı, bir komut dosyasındaki veya html dosyasındaki bir satır vb.).
  3. Sorun algılama. Tarayıcıda, sorunun Chrome'da tespit edilebileceği yerleri belirleyin ve (2). adımdaki ilgili bilgileri içeren bir sorunu bildirmek için bu yeri kullanın.
  4. Sorunları kaydedip görüntüleyin. Sorunları uygun bir yerde saklayın ve Geliştirici Araçları açıldığında kullanılabilir hale getirin.
  5. Sayı metnini tasarlama. Web geliştiricisinin sorunu anlamasına ve daha da önemlisi düzeltmesine yardımcı olacak açıklayıcı bir metin oluşturun.

1. adım: CSP sorunları için kullanıcı hikayeleri tanımlama

Uygulama çalışmalarımıza başlamadan önce, yapmamız gerekenleri daha iyi anlamak için kullanıcı hikayeleri içeren bir tasarım dokümanı oluşturduk. Örneğin, aşağıdaki kullanıcı hikayesini yazdık:


Web sitemin bazı bölümlerinin engellendiğini yeni fark eden bir geliştirici olarak şunları yapmak istiyorum:- ...Web sitemdeki engellenen iframe'lerin / resimlerin nedeninin İGP olup olmadığını öğrenmek - ...Belirli bir kaynağın engellenmesine hangi İGP yönergesinin neden olduğunu öğrenmek - ...Şu anda engellenen kaynakların gösterilmesine / şu anda engellenen js'nin yürütülmesine izin vermek için web sitemin İGP'sini nasıl değiştireceğimi öğrenmek.


Bu kullanıcı hikayesini incelemek için ilgilendiğimiz CSP ihlallerini gösteren bazı basit örnek web sayfaları oluşturduk ve süreci öğrenmek için örnek sayfaları inceledik. Örnek web sayfalarından bazıları şunlardır (demoyu Sorunlar sekmesi açıkken açın):

Bu süreçte, CSP sorunlarını ayıklamak için en önemli bilgi parçasının kaynak konum olduğunu öğrendik. Ayrıca, bir kaynağın engellenmesi durumunda ilişkili iframe'i ve isteği hızlıca bulmanın faydalı olduğunu ve DevTools'un Öğeler panelindeki HTML öğesine doğrudan bağlantı vermenin de yararlı olabileceğini fark ettik.

2. adım: Ön uç uygulaması

Bu analizden yola çıkarak Chrome Geliştirici Araçları Protokolü (CDP) aracılığıyla Geliştirici Araçları'nda kullanıma sunmak istediğimiz bilgilerin ilk taslağını oluşturduk:

Aşağıda, third_party/blink/public/devtools_protocol/browser_protocol.pdl dosyasından bir alıntı verilmiştir.

 type ContentSecurityPolicyIssueDetails extends object
   properties
     # The url not included in allowed sources.
     optional string blockedURL
     # Specific directive that is violated, causing the CSP issue.
     string violatedDirective
     boolean isReportOnly
     ContentSecurityPolicyViolationType contentSecurityPolicyViolationType
     optional AffectedFrame frameAncestor
     optional SourceCodeLocation sourceCodeLocation
     optional DOM.BackendNodeId violatingNodeId

Yukarıdaki tanım, esasen bir JSON veri yapısını kodlar. PDL (protokol veri dili) adı verilen basit bir dilde yazılır. PDL iki amaçla kullanılır. İlk olarak, Geliştirici Araçları ön ucunun kullandığı TypeScript tanımlarını oluşturmak için PDL'yi kullanırız. Örneğin, yukarıdaki PDL tanımı aşağıdaki TypeScript arayüzünü oluşturur:

export interface ContentSecurityPolicyIssueDetails {
  /**
  * The url not included in allowed sources.
  */
  blockedURL?: string;
  /**
  * Specific directive that is violated, causing the CSP issue.
  */
  violatedDirective: string;
  isReportOnly: boolean;
  contentSecurityPolicyViolationType: ContentSecurityPolicyViolationType;
  frameAncestor?: AffectedFrame;
  sourceCodeLocation?: SourceCodeLocation;
  violatingNodeId?: DOM.BackendNodeId;
}

İkinci olarak, daha da önemlisi, bu veri yapılarının C++ Chromium arka ucundan DevTools ön ucuna oluşturulmasını ve gönderilmesini sağlayan tanımdan bir C++ kitaplığı oluştururuz. Bu kitaplığı kullanarak aşağıdaki C++ koduyla bir ContentSecurityPolicyIssueDetails nesnesi oluşturulabilir:

protocol::Audits::ContentSecurityPolicyIssueDetails::create()
  .setViolatedDirective(d->violated_directive)
  .setIsReportOnly(d->is_report_only)
  .setContentSecurityPolicyViolationType(BuildViolationType(
      d->content_security_policy_violation_type)))
  .build();

Kullanıma sunmak istediğimiz bilgilere karar verdikten sonra, bu bilgileri Chromium'dan nereden alacağımızı araştırmamız gerekiyordu.

3. adım: Sorun tespiti

Bilgileri son bölümde açıklanan biçimde Chrome Geliştirici Araçları Protokolü'ne (CDP) sunmak için bilgilerin arka uçta nerede bulunduğunu bulmamız gerekiyordu. Neyse ki CSP kodunda, yalnızca raporlama modu için kullanılan ve bağlanabileceğimiz bir darboğaz vardı: ContentSecurityPolicy::ReportViolation, sorunları CSP HTTP üstbilgisinde yapılandırılabilen (isteğe bağlı) bir raporlama uç noktasına bildirir. Raporlamak istediğimiz bilgilerin çoğu zaten mevcuttu. Bu nedenle, ölçümümüzün çalışması için arka uçta büyük değişiklikler yapılması gerekmedi.

4. adım: Sorunları kaydedin ve görüntüleyin

Küçük bir sorun, Geliştirici Araçları açılmadan önce meydana gelen sorunları da bildirmek istememizdi. Bu, konsol mesajlarının işlenme şekline benzer. Bu, sorunları doğrudan ön uca bildirmediğimiz, bunun yerine DevTools'un açık olup olmadığından bağımsız olarak sorunlarla doldurulan bir depolama alanı kullandığımız anlamına gelir. Geliştirici Araçları açıldıktan (veya başka bir CDP istemcisi bağlandıktan) sonra, daha önce kaydedilen tüm sorunlar depolama alanından tekrar oynatılabilir.

Böylece arka uç çalışması tamamlandı ve artık sorunu ön uçta nasıl göstereceğimize odaklanmamız gerekiyordu.

5. adım: Sorun metnini tasarlama

Sorun metnini tasarlamak, bizim ekibimizin yanı sıra birkaç ekibi daha içeren bir süreçtir. Örneğin, genellikle bir özelliği uygulayan ekibin (bu durumda CSP ekibi) ve tabii ki web geliştiricilerin belirli bir sorun türüyle nasıl başa çıkması gerektiğini tasarlayan DevRel ekibinin görüşlerinden yararlanırız. Sorun metni genellikle tamamlanana kadar bazı düzenlemelerden geçer.

Geliştirici Araçları ekibi genellikle hayal ettikleri şeyin kaba bir taslağıyla başlar:


## Header
Content Security Policy: include all sources of your resources in content security policy header to improve the functioning of your site

## General information
Even though some sources are included in the content security policy header, some resources accessed by your site like images, stylesheets or scripts originate from sources not included in content security policy directives.

Usage of content from not included sources is restricted to strengthen the security of your entire site.

## Specific information

### VIOLATED DIRECTIVES
`img-src 'self'`

### BLOCKED URLs
https://imgur.com/JuXCo1p.jpg

## Specific information
https://web.dev/strict-csp/

Yinelemenin ardından şu sonuca ulaştık:

ALT_TEXT_HERE

Gördüğünüz gibi, özellik ekibini ve DevRel'i dahil etmek, açıklamanın çok daha net ve kesin olmasını sağlıyor.

Sayfanızdaki CSP sorunları, özellikle CSP ihlallerine ayrılmış sekmede de bulunabilir.

Güvenilir Türler ile ilgili sorunları giderme

Doğru geliştirici araçları olmadan TT ile büyük ölçekte çalışmak zor olabilir.

İyileştirilmiş konsol yazdırma

Güvenilir Nesneler ile çalışırken en azından güvenilir olmayan muadiliyle aynı miktarda bilgi göstermek isteriz. Maalesef şu anda güvenilir nesne gösterilirken sarmalanmış nesneyle ilgili bilgi gösterilmiyor.

Bunun nedeni, konsolda gösterilen değerin varsayılan olarak nesne üzerinde .valueOf() çağrılmasından alınmasıdır. Ancak Güvenilir Tür söz konusu olduğunda döndürülen değer pek kullanışlı değildir. Bunun yerine, .toString() yöntemini çağırdığınızda elde ettiğiniz sonuca benzer bir sonuç elde etmek istiyoruz. Bunu başarmak için V8 ve Blink'i değiştirerek güvenilir tür nesneleri için özel işleme eklememiz gerekir.

Geçmişten gelen nedenlerle bu özel işleme V8'de yapılmış olsa da bu yaklaşımın önemli dezavantajları vardır. Özel görüntüleme gerektiren ancak JS düzeyinde türü aynı olan birçok nesne vardır. V8 saf JS olduğundan, Güvenilir Tür gibi bir Web API'sine karşılık gelen kavramları ayırt edemez. Bu nedenle V8, bunları ayırt etmek için yerleştiricisinden (Blink) yardım istemek zorundadır.

Bu nedenle, kodun bu bölümünü Blink'e veya herhangi bir yerleştiriciye taşımak mantıklı bir seçim gibi görünüyor. Açığa çıkan sorunun yanı sıra başka birçok avantajı da vardır:

  • Her yerleştiricinin kendi açıklama oluşturma özelliği olabilir.
  • Açıklamayı Blink API üzerinden oluşturmak çok daha kolaydır.
  • Blink, nesnenin orijinal tanımına erişebilir. Bu nedenle, açıklamayı oluşturmak için .toString() kullanırsak .toString() öğesinin yeniden tanımlanma riski olmaz.

İhlal durumunda engelleme (yalnızca raporlama modunda)

Şu anda TT ihlallerinde hata ayıklamanın tek yolu, JS istisnalarında kesme noktaları ayarlamaktır. Zorunlu kılınan TT ihlalleri bir istisnayı tetikleyeceğinden bu özellik bir şekilde faydalı olabilir. Ancak gerçek hayattaki senaryolarda, TT ihlalleri üzerinde daha ayrıntılı bir kontrole ihtiyacınız vardır. Özellikle yalnızca TT ihlallerinde (diğer istisnalarda değil) kesinti yapmak, yalnızca raporlama modunda da kesinti yapmak ve farklı TT ihlali türlerini ayırt etmek istiyoruz.

Geliştirici Araçları, çok çeşitli kesme noktalarını desteklediğinden mimari oldukça genişletilebilir. Yeni bir kesme noktası türü eklemek için arka uçta (Blink), CDP'de ve ön uçta değişiklik yapılması gerekir. Yeni bir CDP komutu eklemeliyiz. Bu komuta setBreakOnTTViolation diyelim. Bu komut, ön uç tarafından arka uca hangi tür TT ihlallerinde durması gerektiğini bildirmek için kullanılır. Arka uç, özellikle InspectorDOMDebuggerAgent, her TT ihlali gerçekleştiğinde çağrılacak bir "araştırma" onTTViolation() sağlar. Ardından InspectorDOMDebuggerAgent, bu ihlalin bir kesme noktası tetiklemesi gerekip gerekmediğini kontrol eder ve gerekirse yürütmeyi duraklatmak için ön uca bir mesaj gönderir.

Neler yapıldı ve sırada ne var?

Burada açıklanan sorunlar ortaya çıktığından beri Sorunlar sekmesinde oldukça fazla değişiklik yapıldı:

İlerleyen dönemlerde, daha fazla sorunu göstermek için Sorunlar sekmesini kullanmayı planlıyoruz. Bu sayede, uzun vadede okunamaz hata mesajı akışını Console'dan kaldırmak mümkün olacak.

Önizleme kanallarını indirme

Varsayılan geliştirme tarayıcınız olarak Chrome Canary, Dev veya Beta'yı kullanabilirsiniz. Bu önizleme kanalları, en yeni Geliştirici Araçları özelliklerine erişmenizi sağlar, en yeni web platformu API'lerini test etmenize olanak tanır ve sitenizdeki sorunları kullanıcılarınızdan önce bulmanıza yardımcı olur.

Chrome Geliştirici Araçları Ekibi ile iletişime geçme

Yeni özellikler, güncellemeler veya Geliştirici Araçları ile ilgili diğer konuları tartışmak için aşağıdaki seçenekleri kullanın.