CET - Intel Control-flow Enforcement Technology

Allikas: Imre kasutab arvutit
Redaktsioon seisuga 20. mai 2026, kell 22:10 kasutajalt Imre (arutelu | kaastöö) (→‎Programmi töötamine)
Mine navigeerimisribaleMine otsikasti

Sissejuhatus

TODO

Mõisted

  • CET - control-flow enforcement technology
  • ROP - return oriented programming
  • SHSTK - shadow stack
  • IBT - TODO
  • LPE - local privilege escalation

Tööpõhimõte - ROP

Väited

  • ROP tehnika jaoks ei ole ausat kasutusjuhtumit, see on puhtalt eksploitimise eesmärgil kasutatav tehnika
  • ROP vältimiseks on erinevaid võimalusi, üks on CET riistvara toetatud
  • CET riistvara tugi leiab kasutust ka muudel eesmärkidel lisaks ROP vältimisele

Programmi töötamine

Väited

  • kui arvutis hakkab tööle järgmine programm, st tekib uus protsess, siis muude ressursside hulgas allokeeritakse mälu
  • mälu allokeeritakse erinevate maitsetega: 1. code, 2. data, 3. memory mapping segment, 4. heap, 5. stack
  • linux puhul on stack vaikimisi 8 MB suur
  • stack peal hoitakse järgmise funktsiooni väljakutsega seotud muutujaid st nende väärtusi, ja tagasipöördumise aadresse funktsiooni välja kutsunud programmi kohale vastavale mälu aadressile
  • kui programm töötab, siis ta saab mingitel hetkedel sisendit ja kutsub välja funktsioone, stack paisub ja aheneb, töö käib
  • protsessor töötab erinevates registrites olevate nö andmetega, assembler keeles
  • olemas on 'memory safe' keeled-kompilaatorid nt go ja rust - nad konstrueerivad sellises vormis assemblerit, mida ei saa rop vajadusteks ära kasutada
  • olemas on 'non-memory safe' keeled nt c - tavaline c kompilaator konstrueerub sellises vormis assemblerit, mida saab rop vajadusteks ära kasutada

Töötava protsessi mälu kasutuse hindamine

# grep -E 'Vm|Rss' /proc/921/status
VmPeak:	   21064 kB
VmSize:	   21064 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	    4564 kB
VmRSS:	    4564 kB
RssAnon:	    1408 kB
RssFile:	    3156 kB
RssShmem:	       0 kB
VmData:	    1132 kB
VmStk:	    8324 kB
VmExe:	     844 kB
VmLib:	    6800 kB
VmPTE:	      64 kB
VmSwap:	       0 kB

kus

  • VmStk -

Programmi töötamise eksploitimine

Väited

  • rop abil eksploitimine põhineb asjaolul et nö 'non-memory safe' keelest kompileeritud assemblerile vastavas stackis saab korraldada puhvrite (muutujate) kirjutamist üle ääre (spillover, overflow)
  • overflow puhul on võimalik praktiliselt kirjutada uue väärtuse sellisele asukohale mälus, mida arvuti käsitleb nt tagasipöördumise aadressina - ja oskuslikult ülekirjutust tehes on võimalik nt saavutada shell
  • reeglina iseenesest puhas rop ei esklaleeri õigusi, selleks rakendatakse järgmist eksploiti, nt lpe (local privilege escalation)
  • rop puhul on võimalik mitu järjestlikult suunatud jump'i korraldada
  • rop puhul ei ole vajalik arvuti mällu koodi lisada, tegeldakse olemasoleva koodi fragmentide sobiva ümberjärjestamisega, mille nö käivitamisel on meelepärane mõju
  • kuna dünaamiliselt lingitud programmi puhul on kasutada suur hulk süsteemseid teeke, siis mälus oleva koodi puudust ei ole
  • rop põhineb asjaolul, et programmi sisendit piisavalt ei kontrollita - kui programmi täitmine jõuab juba stack'i siis on see suhteliselt libraalne territoorium - kui seal old-school c progammile vastav assebler kirjutab, siis ka kirjutatake (sh toimub 'buffer overflow' ehk 'buffer spillover')
  • kui käivitub kontrollimatu funktsiooni rekursioon siis tõenäoliselt ammendub 8 MB stack maht ja toimub nn 'stack overflow' - kernel krahhib protsessi

Tööpõhimõte - Linux

CET algab protsessori toest, nt https://www.intel.com/content/www/us/en/products/sku/232391/intel-xeon-gold-6448h-processor-60m-cache-2-40-ghz/specifications.html puhul muu hulgas öeldakse

  • Intel® Control-Flow Enforcement Technology

ning töötava arvuti käest küsides, 'user_shstk' on näitaja

# lscpu | grep -i shstk
Flags:                                fpu vme de pse .. user_shstk ...

seejärel kerneli tugi, nt

# grep SHADOW /boot/config-6.17.0-23-generic
CONFIG_X86_USER_SHADOW_STACK=y
CONFIG_ARCH_HAS_USER_SHADOW_STACK=y
...

seejärel rakendustarkvara programmi tugi - rida 'Properties: x86 feature: IBT, SHSTK'

# readelf -n /usr/sbin/nginx

Displaying notes found in: .note.gnu.property
  Owner                Data size 	Description
  GNU                  0x00000020	NT_GNU_PROPERTY_TYPE_0
      Properties: x86 feature: IBT, SHSTK
	x86 ISA needed: x86-64-baseline

Displaying notes found in: .note.gnu.build-id
  Owner                Data size 	Description
  GNU                  0x00000014	NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 9d51609b493789d993848c98e203e9a13dba3157

Displaying notes found in: .note.ABI-tag
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_ABI_TAG (ABI version tag)
    OS: Linux, ABI: 3.2.0

kusjuures kerneli ja programmi vahele jäävad teegid peavad ka toetama

# cat hu.sh
for lib in $(ldd /usr/sbin/nginx | grep -o '/lib[^ ]*'); do
    echo -n "$lib: "
    readelf -n "$lib" 2>/dev/null | grep -q "SHSTK" && echo "READY" || echo "MISSING HARDENING"
done

# sh hu.sh
/lib/x86_64-linux-gnu/libcrypt.so.1: READY
/lib/x86_64-linux-gnu/libpcre2-8.so.0: READY
/lib/x86_64-linux-gnu/libssl.so.3: READY
/lib/x86_64-linux-gnu/libcrypto.so.3: READY
/lib/x86_64-linux-gnu/libz.so.1: READY
/lib/x86_64-linux-gnu/libc.so.6: READY
/lib64/ld-linux-x86-64.so.2: READY

ning kui töötava protsessi juures on shstk aktiivne, see paistab nii (vastasel juhul on : järel tühi)

# ps U www-data
    PID TTY      STAT   TIME COMMAND
    920 ?        S      0:00 nginx: worker process
    921 ?        S      0:00 nginx: worker process
...

# cat /proc/921/status | grep -i thread_fe
x86_Thread_features:	shstk
x86_Thread_features_locked:	shstk wrss

Väited

  • tänapäeval on keeruline leida uut intel või amd protsessoriga arvutit mis ei toetaks cet tehnoloogiat
  • Ubuntu 24.04 platvormil on vaikimisi kõik cet jaoks vajalik olemas v.a. rakenduse systemd service seadistusest sisselülitamine
  • 2026 aasta kevade seisuga virtualiseerimise platvorm Proxmox PVE v. 9 kasutab qemu v. 11 ja seal on füüsilise protsessori kasutamisel virtuaalse arvuti protsessorine (valik 'host') kasutada cet tehnoloogia

Kasulikud lisamaterjalid

Tööpõhimõte - muud operatsioonisüsteemid

Windows

Väited

CET riistvara põhine, ammu olemas (viimased kümme aastat)

MacOS

Väited

  • M1 jt platvormidel sisuliselt CET tulemus saavutatakse teiste võtetega - TODO

OpenBSD

Väited

Haavatavuse näide

Haavatavuse ilmestamise programm rop_lab.c, tõenäoliselt on see märkimisväärne lihtsustus, aga ta illustreerib rop haavatavuse põhimõtet ning haavatavuse ärahoidmist

$ cat rop_lab.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// This is our "Gadget". The program never calls this function honestly!
void malicious_gadget() {
    printf("\n⚡ [ATTACK SUCCESS] Control flow hijacked! Malicious code executing.\n");
    exit(0);
}

void vulnerable_function(char *str) {
    char buffer[16];

    // VULNERABILITY: strcpy does not check bounds.
    // It will overwrite the buffer, the frame pointer, and the Return Address!
    strcpy(buffer, str);

    printf("[CPU] Function executing normally inside buffer layout.\n");
}

int main() {
    // We are crafting a malicious payload payload manually.
    // 16 bytes to fill the buffer + 8 bytes to smash the saved frame pointer
    // + 8 bytes containing the exact memory address of malicious_gadget()
    char payload[32];

    // Fill the padding area with 'A's (0x41)
    memset(payload, 'A', 24);

    // Get the exact memory address of our target gadget
    unsigned long target = (unsigned long)malicious_gadget;

    // Append the target address onto the end of our overflow payload
    memcpy(payload + 24, &target, 8);

    printf("[Lab] Target Gadget Address is at: %p\n", (void*)target);
    printf("[Lab] Launching attack payload against vulnerable function...\n");

    vulnerable_function(payload);

    printf("[CPU] Returned safely to main. (This should not happen if hacked!)\n");
    return 0;
}

kus

  • malicious_gadget() on protsessi mälus olev nö ärakasutatav järgnevus - et ära kasutada, tuleb sattuda sobivale aadressile - võib olla see järgnevus pole üldse algselt programmeeritud isesesiva funktsioonina, aga ta nii praktiliselt toimib kui sobivalt pöörduda-kasutada
  • vulnerable_function - haavatav funktsioon - asutakse ära kasutama tema potensiaali kirjutada üle rohkem stack mälu sisu kui on ette kujutatud
  • main() - programmi töö algus, valmistatakse ette sobiva sisuga payload (mälu sisu) ja paigutatakse kohale
  • tulemusena funktsioonist vulnerable_function tagasi pöördudes ei saabuta main() 'printf ...' juurde, aga gadget juurde

Väljakutsuvalt liberaalse binary kompileerimiseks sobib öelda

$ gcc -fno-stack-protector -z execstack -fcf-protection=none rop_lab.c -o lab_unhardened

kus

  • -fno-stack-protector - ei moodustata nö tarkvarapõhist stack kaitset
  • -z execstack - lisaks lülitatakse sisse stack'is oleva koodi käivitamise võimalus
  • -fcf-protection=none - lülitatakse välja igasugune hardware-assisted st cet põhine stack kaitse

cet põhine kaitse

$ gcc -fno-stack-protector -fcf-protection=full rop_lab.c -o lab_hardened

kus

  • -fcf-protection=full - sisse on lülitatud maksimaalne võimalik hardware-assisted st cet põhine stack kaitse
  • -fno-stack-protector - ei moodustata nö tarkvarapõhist stack kaitset selleks, et katses pääseks mõjule cet põhine kaitse

Kui käivitada cet-võimestatud binary't nö tavalisel viisil ning cet riistvara toega arvutis, siis ta töötab haavatavalt

$ lscpu | grep shstk
Flags:               .. user_shstk ...

$ ./lab_hardened
[Lab] Target Gadget Address is at: 0x6552a7afc1c9
[Lab] Launching attack payload against vulnerable function...
[CPU] Function executing normally inside buffer layout.

⚡ [ATTACK SUCCESS] Control flow hijacked! Malicious code executing.

Kui lülitada sisse cet kaitse, siis hoiab kernel ära haavatavuse mõjulepääsu

$ export GLIBC_TUNABLES=glibc.cpu.hwcaps=SHSTK

$ ./lab_hardened
[Lab] Target Gadget Address is at: 0x59f889ed41c9
[Lab] Launching attack payload against vulnerable function...
[CPU] Function executing normally inside buffer layout.
Segmentation fault (core dumped)

Samal ajal kirjutatakse kerneli logisse

# dmesg -T | tail -n 1
[Wed May 20 20:31:35 2026] lab_hardened[2872] control protection ip:59f889ed421e sp:7ffe4f9f7648 ssp:76edde5fffe0 error:1(near ret) in lab_hardened[121e,59f889ed4000+1000]

kus

  • sp - stack pointer väärtus
  • ssp - shadow stack pointer väärtus
  • nad ei klapi

Kasutamine - Ubuntu 24.04 ja zabbix agent2

Näiteks zabbix agent kaudu haavatavuse esilekutsumine ja haavatavuse vältimine. Moodustada UserParameters abil kontroll

# cat /etc/zabbix/zabbix_agent2.d/misc.conf
UserParameter=rop_hardened,/home/imre/20260520/lab_hardened 1>>/home/tmp/rop_hardened.log 2>&1

# systemctl restart zabbix-agent2

# zabbix_get -k rop_hardened -s 127.0.0.1

Tulemusena programmi ja seal sisalduva nö eksploidi käivitamine

# tail -n 5 /home/tmp/rop_hardened.log
[Lab] Target Gadget Address is at: 0x616af0eed1c9
[Lab] Launching attack payload against vulnerable function...
[CPU] Function executing normally inside buffer layout.

⚡ [ATTACK SUCCESS] Control flow hijacked! Malicious code executing.

Programmis sisalduva eksploidi töötamise takistamiseks sobib kasutada zabbix agent2 systemd service unit seadistustes GLIB_TUNABLES abil

# systemctl edit zabbix-agent2

[Service]
Environment="GLIBC_TUNABLES=glibc.cpu.hwcaps=SHSTK"

# systemctl restart zabbix-agent2

Tulemusena ütleb kernel segmentation fault rikkumise avastamisel

# tail -n 6 /home/tmp/rop_hardened.log
[Lab] Target Gadget Address is at: 0x616af0eed1c9
[Lab] Launching attack payload against vulnerable function...
[CPU] Function executing normally inside buffer layout.

⚡ [ATTACK SUCCESS] Control flow hijacked! Malicious code executing.
Segmentation fault (core dumped)

# dmesg -T | tail -n 1
[Wed May 20 20:50:28 2026] lab_hardened[3417] control protection ip:62ee74e0421e sp:7ffeadc19f28 ssp:7e27011fffe0 error:1(near ret) in lab_hardened[121e,62ee74e04000+1000]

coredump

süsteemi logisse kirjutatakse

2026-05-20T20:50:28.063977+03:00 zabbix-pub-01 kernel: lab_hardened[3417] control protection ip:62ee74e0421e sp:7ffeadc19f28 ssp:7e27011fffe0 error:1(near ret) in lab_hardened[121e,62ee74e04000+1000]
2026-05-20T20:50:28.073376+03:00 zabbix-pub-01 systemd[1]: Started systemd-coredump@11-3418-0.service - Process Core Dump (PID 3418/UID 0).
2026-05-20T20:50:28.134245+03:00 zabbix-pub-01 systemd-coredump[3420]: Process 3417 (lab_hardened) of user 111 dumped core.#012#012Stack trace of thread 3417:#012#0  0x000062ee74e0421e n/a (/home/imre/20260520/lab_hardened + 0x121e)#012ELF object binary architecture: AMD x86-64
2026-05-20T20:50:28.136589+03:00 zabbix-pub-01 systemd[1]: systemd-coredump@11-3418-0.service: Deactivated successfully.
2026-05-20T20:50:28.139121+03:00 zabbix-pub-01 systemd[1]: systemd-coredump@11-3418-0.service: Triggering OnSuccess= dependencies.
2026-05-20T20:50:28.145170+03:00 zabbix-pub-01 systemd[1]: Starting apport-coredump-hook@11-3418-0.service...
2026-05-20T20:50:28.274024+03:00 zabbix-pub-01 systemd[1]: apport-coredump-hook@11-3418-0.service: Deactivated successfully.
2026-05-20T20:50:28.274268+03:00 zabbix-pub-01 systemd[1]: Finished apport-coredump-hook@11-3418-0.service.
2026-05-20T20:52:17.413974+03:00 zabbix-pub-01 kernel: NOTICE: Automounting of tracing to debugfs is deprecated and will be removed in 2030

ning

# coredumpctl list lab_hardened
TIME                          PID  UID  GID SIG     COREFILE EXE                               SIZE
Wed 2026-05-20 15:08:59 EEST 1080 1000 1000 SIGSEGV present  /home/imre/20260520/lab_hardened 18.5K
Wed 2026-05-20 15:09:26 EEST 1165 1000 1000 SIGSEGV present  /home/imre/20260520/lab_hardened 18.5K
Wed 2026-05-20 15:45:00 EEST 1677  111  112 SIGSEGV present  /home/imre/20260520/lab_hardened 18.0K
Wed 2026-05-20 15:45:01 EEST 1696  111  112 SIGSEGV present  /home/imre/20260520/lab_hardened 18.0K
Wed 2026-05-20 15:45:55 EEST 1811  111  112 SIGSEGV present  /home/imre/20260520/lab_hardened 18.0K
Wed 2026-05-20 15:45:57 EEST 1827  111  112 SIGSEGV present  /home/imre/20260520/lab_hardened 18.0K
Wed 2026-05-20 15:51:15 EEST 1908  111  112 SIGSEGV present  /home/imre/20260520/lab_hardened 18.0K
Wed 2026-05-20 15:52:54 EEST 1939 1000 1000 SIGSEGV present  /home/imre/20260520/lab_hardened 18.5K
Wed 2026-05-20 20:31:35 EEST 2872 1000 1000 SIGSEGV present  /home/imre/20260520/lab_hardened 18.5K
Wed 2026-05-20 20:43:23 EEST 2976  111  112 SIGSEGV present  /home/imre/20260520/lab_hardened 18.0K
Wed 2026-05-20 20:43:31 EEST 2994  111  112 SIGSEGV present  /home/imre/20260520/lab_hardened 18.0K
Wed 2026-05-20 20:50:28 EEST 3417  111  112 SIGSEGV present  /home/imre/20260520/lab_hardened 18.0K

# coredumpctl dump lab_hardened --output=lab_crash.core
           PID: 3417 (lab_hardened)
           UID: 111 (zabbix)
           GID: 112 (zabbix)
        Signal: 11 (SEGV)
     Timestamp: Wed 2026-05-20 20:50:28 EEST (8min ago)
  Command Line: /home/imre/20260520/lab_hardened
    Executable: /home/imre/20260520/lab_hardened
 Control Group: /system.slice/zabbix-agent2.service
          Unit: zabbix-agent2.service
         Slice: system.slice
       Boot ID: 3c8da9f759024317bf94b1831190ee44
    Machine ID: b5cb741b1516242b193018946930aed8
      Hostname: zabbix-pub-01
       Storage: /var/lib/systemd/coredump/core.lab_hardened.111.3c8da9f759024317bf94b1831190ee44.3417.1779299428000000.zst (present)
  Size on Disk: 18.0K
       Message: Process 3417 (lab_hardened) of user 111 dumped core.

                Stack trace of thread 3417:
                #0  0x000062ee74e0421e n/a (/home/imre/20260520/lab_hardened + 0x121e)
                ELF object binary architecture: AMD x86-64
More than one entry matches, ignoring rest.

# ls -ld /var/lib/systemd/coredump/*
-rw-r-----+ 1 root root 19024 May 20 15:08 /var/lib/systemd/coredump/core.lab_hardened.1000.3c8da9f759024317bf94b1831190ee44.1080.1779278939000000.zst
-rw-r-----+ 1 root root 19025 May 20 15:09 /var/lib/systemd/coredump/core.lab_hardened.1000.3c8da9f759024317bf94b1831190ee44.1165.1779278966000000.zst
-rw-r-----+ 1 root root 19016 May 20 15:52 /var/lib/systemd/coredump/core.lab_hardened.1000.3c8da9f759024317bf94b1831190ee44.1939.1779281573000000.zst
-rw-r-----+ 1 root root 19014 May 20 20:31 /var/lib/systemd/coredump/core.lab_hardened.1000.3c8da9f759024317bf94b1831190ee44.2872.1779298295000000.zst
-rw-r-----  1 root root 18468 May 20 15:45 /var/lib/systemd/coredump/core.lab_hardened.111.3c8da9f759024317bf94b1831190ee44.1677.1779281100000000.zst
...

core uurimiseks sobib öelda

# gdb ./lab_hardened lab_crash.core
GNU gdb (Ubuntu 15.1-1ubuntu1~24.04.1) 15.1
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
./lab_hardened: No such file or directory.
[New LWP 3417]

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) y
Debuginfod has been enabled.
To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.
Downloading executable for /root/lab_crash.core
...

(gdb) info registers
rax            0x38                56
rbx            0x7ffeadc1a088      140731813568648
rcx            0x0                 0
rdx            0x0                 0
rsi            0x62ee74e05050      108776302596176
rdi            0x7e2701405710      138705989818128
rbp            0x4141414141414141  0x4141414141414141
rsp            0x7ffeadc19f28      0x7ffeadc19f28
r8             0x7e2701403b20      138705989810976
r9             0x0                 0
r10            0x1                 1
r11            0x3                 3
r12            0x1                 1
r13            0x0                 0
r14            0x62ee74e06da0      108776302603680
r15            0x7e2701611000      138705991962624
rip            0x62ee74e0421e      0x62ee74e0421e
eflags         0x10202             [ IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
fs_base        0x7e27015c5740      138705991653184
gs_base        0x0                 0
(gdb)

kus

  • TODO

Kasulikud lisamaterjalid

  • teksti koostamisel on kasutatud ohtralt gemini google abi