Sdílet prostřednictvím


Ochrana toku řízení pro zabezpečení platformy

Co je ochrana toku řízení?

Control Flow Guard (CFG) je vysoce optimalizovaná funkce zabezpečení platformy, která byla vytvořena pro boj proti chybám poškození paměti. Nasazením přísných omezení na to, odkud může aplikace spouštět kód, se výrazně ztíží vykonávání libovolného kódu prostřednictvím zranitelností, jako jsou přetečení vyrovnávací paměti. CFG rozšiřuje předchozí technologie zmírňující zneužití, jako jsou /GS (kontrola zabezpečení vyrovnávací paměti), prevence spouštění dat (DEP)a randomizace rozložení adresního prostoru (ASLR).

Použití CFG může pomoct:

  • Zabraňte útokům na poškození paměti a ransomwaru.
  • Omezte možnosti serveru jenom na to, co je potřeba v určitém okamžiku, aby se snížil prostor pro útoky.
  • Znesnadnit zneužití libovolného kódu prostřednictvím zranitelností, jako jsou přetečení vyrovnávací paměti.

Tato funkce je k dispozici v sadě Microsoft Visual Studio a běží na CFG-Aware verzích systému Windows; Windows 10 a Windows 11 na straně klienta a Windows Server 2019 a novější na straně serveru.

Vývojářům důrazně doporučujeme povolit cfG pro své aplikace. CfG nemusíte povolovat pro každou část kódu, protože kombinace kódu s povoleným cfG a kódem, který není povolený cfG, bude fungovat správně. Nepovolit cfG pro všechny kódy ale může otevřít mezery v ochraně. Kód s podporou CFG funguje správně na verzích Windows, které nezohledňují CFG, a proto je s nimi plně kompatibilní.

Jak můžu povolit CFG?

Ve většině případů není nutné měnit zdrojový kód. Stačí přidat do projektu sady Visual Studio možnost a kompilátor a linker povolí CFG.

Nejjednodušší metodou je přejít na Project | Vlastnosti | Vlastnosti konfigurace | C/C++ | Generování kódu a volba Ano (/guard:cf) pro ochranu toku řízení.

snímek obrazovky s vlastností Control Flow Guard v konfiguraci sestavení generování kódu v sadě Visual Studio.

Alternativně přidejte /guard:cf do projektu | Vlastnosti | Vlastnosti konfigurace | C/C++ | Příkazový řádek | Další možnosti (pro kompilátor) a /guard:cf k projektu | Vlastnosti | Vlastnosti konfigurace | Linker | Příkazový řádek | Další možnosti (pro linker).

Snímek obrazovky konfigurace sestavení s dalšími možnostmi příkazového řádku C/C++ v sadě Visual Studio s vlastností nastavenou na /guard:cf

snímek obrazovky s konfigurací sestavení Další možnosti příkazového řádku linkeru v sadě Visual Studio s vlastností nastavenou na /guard:cf

Další informace najdete v tématu /guard (povolení ochrany toku řízení).

Pokud projekt vytváříte z příkazového řádku, můžete přidat stejné možnosti. Pokud například kompilujete projekt s názvem test.cpp, použijte cl /guard:cf test.cpp /link /guard:cf.

Máte také možnost dynamicky řídit sadu cílových adres icall, které jsou považovány za platné CFG pomocí SetProcessValidCallTargets z rozhraní API pro správu paměti. Stejné rozhraní API lze použít k určení, zda jsou stránky neplatné nebo platné cíle pro CFG. Funkce VirtualProtect a VirtualAlloc budou ve výchozím nastavení považovat konkrétní oblast spustitelných a potvrzených stránek za platné cíle nepřímého volání. Toto chování je možné přepsat, například při implementaci kompilátoru za běhu, zadáním PAGE_TARGETS_INVALID při volání VirtualAlloc nebo PAGE_TARGETS_NO_UPDATE při volání VirtualProtect, jak je podrobně popsáno v části Konstanty ochrany paměti.

Jak zjistím, že binární soubor je v rámci ochrany toku řízení?

Spusťte nástroj dumpbin (zahrnutý v instalaci sady Visual Studio) z příkazového řádku sady Visual Studio s možnostmi /headers a /loadconfig: dumpbin /headers /loadconfig test.exe. Výstup binárního souboru pod CFG by měl ukázat, že hodnoty hlaviček zahrnují "Guard" a že hodnoty načítací konfigurace zahrnují "CF Instrumented" a "FID table present".

snímek obrazovky s výstupem z příkazu dumpbin /headers

snímek obrazovky s výstupem příkazu dumpbin /loadconfig

Jak CFG skutečně funguje?

Ohrožení zabezpečení softwaru se často využívají tím, že do spuštěného programu poskytují nepravděpodobná, neobvyklá nebo extrémní data. Útočník může například zneužít zranitelnost přetečení vyrovnávací paměti tím, že poskytne více vstupu do programu, než se čekalo, a tím přeteče oblast vyhrazenou programem pro uložení odpovědi. To může poškodit sousední paměť, která může obsahovat ukazatel funkce. Když program volá tuto funkci, může přejít na nezamýšlené umístění určené útočníkem.

Silná kombinace podpory kompilace a běhu z CFG však implementuje integritu toku řízení, která úzce omezuje, kde se můžou provádět nepřímé instrukce volání.

Kompilátor provede následující:

  1. Přidá do zkompilovaného kódu odlehčené kontroly zabezpečení.
  2. Identifikuje sadu funkcí v aplikaci, které jsou platnými cíli pro nepřímá volání.

Podpora modulu runtime poskytovaná jádrem Windows:

  1. Efektivně udržuje stav, který identifikuje platné cíle nepřímých volání.
  2. Implementuje logiku, která ověřuje platnost cíle nepřímého volání.

Ilustrace:

diagram znázorňující kontroly CFG vložené kompilátorem

Když kontrola CFG selže během běhu programu, systém Windows okamžitě ukončí program, čímž zamezí jakémukoli zneužití, které se pokusí nepřímo volat neplatnou adresu.

/guard (Povolit Ochranu Toku Řízení)

/OCHRANA (povolení kontrol ochrany)