Block untrusted fonts¶
GDI'nin
%windir%\Fontsdışı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.