Skip to content

Block untrusted fonts

GDI'nin %windir%\Fonts dışında kurulu font'ları load etmesini durduran ve birçok EOP exploit'ini besleyen kernel-mode font-parsing attack surface'ini küçülten bir Windows process/system mitigation'ı.

Mechanism

Note

Font'lar karmaşık, attacker-etkilenebilir data structure'lardır (OpenType/TrueType tablolar; web sayfalarına, dökümanlara ve e-postalara embed edilirler). Tarihsel olarak GDI onları kernel mode'da (win32k.sys / font driver) parse ederdi, dolayısıyla tek bir bozuk glyph tablosu remote olarak erişilebilen bir elevation-of-privilege (EOP) primitive'i verebilirdi. Bu mitigation'ın enforce ettiği invariant şu: bir process yalnızca "system" font'larını — %windir%\Fonts içinde zaten kurulu olanları — load edebilir ve herhangi bir "untrusted" (non-system) font'u reddetmelidir. Dışarıdan sağlanan font dosyalarını parser'a hiç beslemeyi reddederek, bug sınıfı vaka vaka düzeltmek yerine input'tan mahrum bırakılır. Karar, GDI'den bir font realize etmesi istendiğinde enforce edilir ve hem file-based hem de memory-based (embedded) font'ları kapsar.

Process başına knob PROCESS_MITIGATION_FONT_DISABLE_POLICY'dir:

typedef struct _PROCESS_MITIGATION_FONT_DISABLE_POLICY {
  union {
    DWORD Flags;
    struct {
      DWORD DisableNonSystemFonts     : 1;   // <-- block untrusted fonts
      DWORD AuditNonSystemFontLoading : 1;   // log via ETW, do not block
      DWORD ReservedFlags             : 30;
    } DUMMYSTRUCTNAME;
  } DUMMYUNIONNAME;
} PROCESS_MITIGATION_FONT_DISABLE_POLICY, *PPROCESS_MITIGATION_FONT_DISABLE_POLICY;

DisableNonSystemFonts = 0x1 "process'in non-system font'ları load etmesini engeller"; AuditNonSystemFontLoading = 0x1 ise bloklamadan "process bir non-system font load etmeye çalıştığında bir ETW event log'lar."

Walkthrough

Process başına, programatik enforcement:

#include <windows.h>
#include <processthreadsapi.h>

int main(void) {
    PROCESS_MITIGATION_FONT_DISABLE_POLICY p = {0};
    p.DisableNonSystemFonts = 1;            // block fonts outside %windir%\Fonts

    BOOL ok = SetProcessMitigationPolicy(
        ProcessFontDisablePolicy, &p, sizeof(p));

    printf("SetProcessMitigationPolicy=%d gle=%lu\n", ok, GetLastError());
    return 0;
}
// Expected: SetProcessMitigationPolicy=1 gle=0

System-wide olarak, Microsoft aynı özelliği Untrusted Font Blocking olarak sunar. Session Manager key'i altında 64-bit bir MitigationOptions QWORD'üdür:

Key:   HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Kernel
Value: MitigationOptions   (REG_QWORD)

  Enable (block + log):   1000000000000
  Disable:                2000000000000
  Audit (log only):       3000000000000

Warning

Bunlar düz sayılar değil, hex nibble-field'lardır — mevcut MitigationOptions bit'lerini koru. Microsoft'un kendi örneği: mevcut değer 1000 ise, enabled değeri 1000000000000 değil 1000000001000 olur. Registry'yi düzenledikten sonra bir reboot gerekir.

Eşdeğer Group Policy, Block untrusted fonts and log events / Do not block untrusted fonts / Log events without blocking untrusted fonts üç durumuyla Computer Configuration → Administrative Templates → System → Mitigation Options → Untrusted Font Blocking'dir.

Per-app exclusion'ları (ihtiyaç duyulan bir uygulama memory font kullandığında) Image File Execution Options altına gider:

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<App.exe>
  MitigationOptions (REG_QWORD) = 2000000000000   (turn the block off for that app)

Detection

Audit modu (3000000000000 veya process başına AuditNonSystemFontLoading) her untrusted-font load'unu bloklamadan log'lar. İncele:

Event Viewer → Applications and Services Logs →
    Microsoft → Windows → Win32k → Operational
Event ID: 260

Event, ihlal eden process'i ve file-based font'lar için FontPath'i kaydeder; memory (embedded) font'lar path olmadan FontType: Memory gösterir. Enforcement altında bozulacak uygulamaları (Office embedded font'ları, printer graphics DLL'leri, Internet Explorer web font'ları) bulmak için önce audit çalıştır.

Mitigation

Mitigation budur. Kapsamı GDI'ye özeldir: modern DirectWrite ve font parsing'in kısıtlı bir user-mode AppContainer'a (fontdrvhost.exe) taşınması residual yüzeyi daha da azaltır; Microsoft'un global blocking switch'ini sonradan geri plana atmasının nedeni budur. Bypass etmek için bir saldırgan font'unu %windir%\Fonts içine kurdurmalı (privileged bir write) veya non-GDI/excluded bir path'i hedeflemelidir.

References