Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
optee-qemu — Ambiente con kernel vulnerabile per lo sfruttamento del driver TEE (CVE-2021-44733) | Kitploit
Strumenti/GitHubGitHub/pjlantz/optee-qemu
Sicurezza Sistemi EmbeddedAnalisi delle VulnerabilitàExploitFuzzingApprendimento e FormazioneBinary ExploitationLab e Pratica
GitHubpjlantz/optee-qemu

optee-qemu

Ambiente con kernel vulnerabile per lo sfruttamento del driver TEE (CVE-2021-44733)

Vedi Repository
76114 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2021-44733: Fuzzing e sfruttamento di una use-after-free nel sottosistema TEE del kernel Linux

Recentemente è stata scoperta una vulnerabilità use-after-free nel sottosistema TEE del kernel Linux, fino alla versione 5.15.11 inclusa, alla quale è stato assegnato l'ID CVE-2021-44733 [1].

A prima vista non sembrava sfruttabile per diverse ragioni; tuttavia, dopo un'ulteriore analisi del percorso di codice vulnerabile e implementando un proof-of-concept grezzo, è stato possibile sovrascrivere un puntatore a funzione nel kernel. In questo post non viene presentato alcun payload per l'escalation dei privilegi, ma l'intero ambiente per eseguire OPTEE e l'exploit è disponibile per ulteriori test, si veda 'Configurazione dell'ambiente'.

Background

Un TEE (Trusted Execution Environment) è un sistema operativo fidato che gira in un ambiente sicuro, ad esempio TrustZone sulle CPU ARM. Un driver TEE gestisce i dettagli necessari per comunicare con il TEE. Alcuni dei compiti più importanti del driver sono fornire un'API generica verso il TEE basata sulla specifica Globalplatform TEE Client API [3], ma anche gestire la memoria condivisa tra Linux e il TEE. Questo sottosistema può essere abilitato configurando CONFIG_OPTEE nelle configurazioni del kernel per le architetture ARM.

Il mondo sicuro contiene il sistema operativo fidato denominato OP-TEE OS [4]. Sopra questo OS è possibile avere le cosiddette Trusted Applications (TA) in esecuzione, che possono svolgere alcune operazioni nell'ambiente isolato, si veda la Figura 1.

TEE overview
Figura 1: Panoramica del TEE - dalla presentazione di Linaro [5]

Il mondo normale (userspace/kernel Linux) può interagire con queste applicazioni usando client application (CA) e l'API esposta dal sottosistema TEE. Una CA può aprire una sessione verso una specifica TA e invocare funzioni implementate dalla TA. Il passaggio di qualsiasi argomento tra TA e CA avviene tramite memoria condivisa. L'interazione tra una CA e una TA utilizzando tutte le syscall rilevanti è descritta di seguito.

  1. Una CA apre /dev/tee[0-9] per comunicare con il driver. Si noti che, per l'uso convenzionale di queste API, ciò avviene implicitamente tramite libteec.

  2. La memoria condivisa può essere registrata dalla CA usando l'IOCTL TEE_IOC_SHM_ALLOC. Questo alloca memoria condivisa e restituisce un descrittore di file che lo spazio utente può usare come parte di mmap.

  3. Il passo successivo è stabilire una sessione usando l'IOCTL TEE_IOC_OPEN_SESSION e specificando lo uuid per una specifica TA. Questo uuid è hardcoded durante la compilazione della TA.

  4. Per invocare una qualsiasi funzione specifica nella TA, la CA la invoca specificando l'identificatore di una funzione insieme agli eventuali argomenti di input; questo viene fatto usando TEE_IOC_INVOKE.

  5. Quando la CA ha terminato tutte le richieste, la sessione può essere chiusa usando TEE_IOC_CLOSE_SESSION.

Session between CA and TA
Figura 2: Sessione tra CA e TA - dalla presentazione di Linaro [5]

Gran parte della comunicazione tra i client e il TEE è opaca per il driver. Il compito principale del driver è gestire il contesto, ricevere le richieste dai client, inoltrarle al TEE e rispedire i risultati [2].

Fuzzing del driver TEE

CVE-2021-44733 è stato scoperto utilizzando il fuzzing con syzkaller. Il file di descrizione usato per questo scopo è riportato di seguito. Si noti che ioctl$TEE_SHM_REGISTER_FD fa solo parte dell'albero del kernel di Linaro (manutentori) e non è presente in upstream. L'ambiente fornito in 'Configurazione dell'ambiente' può essere utilizzato per il fuzzing se configurato correttamente secondo la documentazione di syzkaller [6]``` #include <uapi/linux/tee.h>

resource fd_tee0[fd] resource session_resource[int32]

openat$tee0(fd const[AT_FDCWD], dev ptr[in, string["/dev/tee0"]], flags flags[open_flags], mode flags[open_mode]) fd_tee0 ioctl$TEE_OPEN_SESSION(fd fd_tee0, cmd const[0x8010a402], arg ptr[inout, tee_ioctl_buf_data_session]) ioctl$TEE_INVOKE(fd fd_tee0, cmd const[0x8010a403], arg ptr[inout, tee_ioctl_buf_data_invoke]) ioctl$TEE_CANCEL(fd fd_tee0, cmd const[0x8008a404], arg ptr[in, tee_ioctl_buf_data_cancel]) ioctl$TEE_CLOSE_SESSION(fd fd_tee0, cmd const[0x8004a405], arg ptr[in, tee_ioctl_buf_data_close]) ioctl$TEE_VERSION(fd fd_tee0, cmd const[0x800ca400], arg ptr[out, tee_ioctl_buf_data_version]) ioctl$TEE_SHM_ALLOC(fd fd_tee0, cmd const[0xc010a401], arg ptr[inout, tee_ioctl_buf_data_shm_alloc]) ioctl$TEE_SHM_REGISTER(fd fd_tee0, cmd const[0xc018a409], arg ptr[inout, tee_ioctl_buf_data_shm_register]) ioctl$TEE_SHM_REGISTER_FD(fd fd_tee0, cmd const[0xc018a408], arg ptr[inout, tee_ioctl_buf_data_shm_register_fd]) ioctl$TEE_SUPPL_RECV(fd fd_tee0, cmd const[0x8010a406], arg ptr[inout, tee_ioctl_buf_suppl_recv]) ioctl$TEE_SUPPL_SEND(fd fd_tee0, cmd const[0x8010a407], arg ptr[inout, tee_ioctl_buf_suppl_send])

COMMON

#=======================================================

define TEE_IOCTL_UUID_LEN 16

tee_ioctl_param_struct { attr flags[TEE_IOCTL_PARAM_ATTR_TYPE, int64] a int64 b int64 c int64 }

TEE_IOCTL_PARAM_ATTR_TYPE = 0, 1, 2, 3, 5, 6, 7 TEE_LOGIN = 0, 1, 2, 4, 5, 6

OPEN SESSION

#=======================================================

tee_ioctl_buf_data_session { buf_ptr ptr64[inout, tee_ioctl_open_session_struct] buf_len len[buf_ptr, int64] }

tee_ioctl_open_session_struct { uuid array[int8, TEE_IOCTL_UUID_LEN] (in) clnt_uuid array[int8, TEE_IOCTL_UUID_LEN] (in) clnt_login flags[TEE_LOGIN, int32] (in) cancel_id int32 (in) session session_resource (out) ret int32 (out) ret_origin int32 (out) num_params len[params, int32] (in) params array[tee_ioctl_param_struct] (in) }

INVOKE

#=======================================================

tee_ioctl_buf_data_invoke { buf_ptr ptr64[inout, tee_ioctl_invoke_struct] buf_len len[buf_ptr, int64] }

tee_ioctl_invoke_struct { func int32 (in) session session_resource (in) cancel_id int32 (in) ret int32 (out) ret_origin int32 (out) num_params len[params, int32] (in) params array[tee_ioctl_param_struct] (in) }

CANCEL SESSION

#=======================================================

tee_ioctl_buf_data_cancel { cancel_id int32 (in) session session_resource (in) }

CLOSE SESSION

#=======================================================

tee_ioctl_buf_data_close { session session_resource (in) }

VERSION

#=======================================================

tee_ioctl_buf_data_version { impl_id int32 (out) impl_caps int32 (out) gen_caps int32 (out) }

SHM ALLOC

#=======================================================

tee_ioctl_buf_data_shm_alloc { size int64 (inout) flags const[0, int32] (inout) id int32 (out) }

SHM REGISTER

#=======================================================

tee_ioctl_buf_data_shm_register { addr int64 (in) length int64 (inout) flags const[0, int32] (inout) id int32 (out) }

SHM REGISTER FD

#=======================================================

tee_ioctl_buf_data_shm_register_fd { fd int64 (in) size int64 (out) flags const[0, int32] (in) id int32 (out) } [align[8]]

SUPPLICANT RECV

#=======================================================

tee_ioctl_buf_suppl_recv { func int32 (in) num_params len[params, int32] (inout) params array[tee_ioctl_param_struct] (inout) }

SUPPLICANT SEND

#=======================================================

tee_ioctl_buf_suppl_send { ret int32 (out) num_params len[params, int32] (in) params array[tee_ioctl_param_struct] (in) }

root@kitploit:~
Durante il fuzzing, il crash che ha attirato l'attenzione era legato a un use-after-free di un oggetto task_struct mentre un mutex era detenuto:```
==================================================================
BUG: KASAN: use-after-free in __mutex_lock.constprop.0+0x118c/0x11c4
Read of size 4 at addr 863b0714 by task optee_example_r/244
 
CPU: 0 PID: 244 Comm: optee_example_r Tainted: G      D           5.14.0 #151
Hardware name: Generic DT based system
[<8012b204>] (unwind_backtrace) from [<8011f460>] (show_stack+0x20/0x24)
[<8011f460>] (show_stack) from [<81cf0108>] (dump_stack_lvl+0x5c/0x68)
[<81cf0108>] (dump_stack_lvl) from [<80650f04>] (print_address_description.constprop.0+0x38/0x304)
[<80650f04>] (print_address_description.constprop.0) from [<80651548>] (kasan_report+0x1c0/0x1dc)
[<80651548>] (kasan_report) from [<81d0a9b4>] (__mutex_lock.constprop.0+0x118c/0x11c4)
[<81d0a9b4>] (__mutex_lock.constprop.0) from [<81d0ada4>] (mutex_lock+0x128/0x13c)
[<81d0ada4>] (mutex_lock) from [<817424b0>] (tee_shm_release+0x4b0/0x6cc)
[<817424b0>] (tee_shm_release) from [<81303674>] (dma_buf_release+0x1b8/0x2f0)
[<81303674>] (dma_buf_release) from [<806d5ac0>] (__dentry_kill+0x4c4/0x678)
[<806d5ac0>] (__dentry_kill) from [<806d8a68>] (dput+0x630/0xba4)
[<806d8a68>] (dput) from [<8067d890>] (__fput+0x3b4/0x900)
[<8067d890>] (__fput) from [<801dd1d8>] (task_work_run+0x15c/0x230)
[<801dd1d8>] (task_work_run) from [<80172b70>] (do_exit+0x103c/0x3770)
[<80172b70>] (do_exit) from [<80179aec>] (do_group_exit+0x134/0x3ac)
[<80179aec>] (do_group_exit) from [<801a7658>] (get_signal+0x7d8/0x2f28)
[<801a7658>] (get_signal) from [<8011dea4>] (do_work_pending+0x984/0x154c)
[<8011dea4>] (do_work_pending) from [<801000d0>] (slow_work_pending+0xc/0x20)
Exception stack(0x85743fb0 to 0x85743ff8)
3fa0:                                     00023108 00000080 00000000 00000000
3fc0: 66bca2d0 66bca2d0 66bca2d0 000000f0 66bca2d0 66bca340 00000000 6ec00b0c
3fe0: 66bc9cc8 66bc9cb8 00011655 66c80c20 000e0130 00023108
 
Allocated by task 242:
 set_alloc_info+0x48/0x50
 __kasan_slab_alloc+0x48/0x58
 kmem_cache_alloc+0x14c/0x314
 copy_process+0x2014/0x7b18
 kernel_clone+0x244/0xfc8
 sys_clone+0xc8/0xec
 ret_fast_syscall+0x0/0x58
 0x6ec00a10
 
Freed by task 67:
 kasan_set_track+0x28/0x30
 kasan_set_free_info+0x20/0x34
 __kasan_slab_free+0xdc/0x108
 kmem_cache_free+0x80/0x394
 __put_task_struct+0x2b4/0x35c
 delayed_put_task_struct+0x104/0x384
 rcu_core+0x91c/0x2a68
 __do_softirq+0x2fc/0xfb8
 
Last potentially related work creation:
 kasan_record_aux_stack+0xb8/0xc0
 call_rcu+0x9c/0xfd0
 put_task_struct_rcu_user+0x9c/0xbc
 finish_task_switch+0x534/0xa10
 __schedule+0x934/0x1adc
 schedule_idle+0x9c/0x120
 do_idle+0x2ec/0x434
 cpu_startup_entry+0x18/0x1c
 start_kernel+0x3ec/0x430
 
The buggy address belongs to the object at 863b0700
 which belongs to the cache task_struct of size 1664
The buggy address is located 20 bytes inside of
 1664-byte region [863b0700, 863b0d80)
The buggy address belongs to the page:
page:f09c9565 refcount:1 mapcount:0 mapping:00000000 index:0x0 pfn:0x463b0
head:f09c9565 order:3 compound_mapcount:0 compound_pincount:0
flags: 0x10200(slab|head|zone=0)
raw: 00010200 00000000 00000122 82802e00 00000000 80120012 ffffffff 00000001
page dumped because: kasan: bad access detected
 
Memory state around the buggy address:
 863b0600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 863b0680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>863b0700: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                 ^
 863b0780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 863b0800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================

Questo è stato innescato chiudendo tutti i descrittori di file provenienti da TEE_IOC_SHM_ALLOC mentre un thread diverso apre una sessione verso, nel nostro caso, una TA inesistente. Syzkaller è riuscito a riprodurlo e, sperimentando con il codice del riproduttore e ritardando leggermente la chiamata a TEE_IOC_OPEN_SESSION, si è verificato un diverso UAF per un oggetto appartenente alla cache kmalloc-64:```

================================================================== BUG: KASAN: use-after-free in tee_shm_put+0x8c/0x98 Read of size 4 at addr 86467020 by task optee_example_h/216

CPU: 0 PID: 216 Comm: optee_example_h Not tainted 5.14.0 #21 Hardware name: Generic DT based system [<80122584>] (unwind_backtrace) from [<80117fd4>] (show_stack+0x10/0x14) [<80117fd4>] (show_stack) from [<819d57a0>] (dump_stack_lvl+0x40/0x4c) [<819d57a0>] (dump_stack_lvl) from [<819ced74>] (print_address_description.constprop.0+0x5c/0x2d8) [<819ced74>] (print_address_description.constprop.0) from [<805a12c4>] (kasan_report+0x1b4/0x1d0) [<805a12c4>] (kasan_report) from [<814cc6b0>] (tee_shm_put+0x8c/0x98) [<814cc6b0>] (tee_shm_put) from [<814c9b2c>] (tee_ioctl+0x1578/0x2e44) [<814c9b2c>] (tee_ioctl) from [<806038ec>] (sys_ioctl+0x918/0x1e70) [<806038ec>] (sys_ioctl) from [<80100060>] (ret_fast_syscall+0x0/0x58) Exception stack(0x86417fa8 to 0x86417ff0) 7fa0: 00000080 00000000 00000003 8010a402 200001c0 00000003 7fc0: 00000080 00000000 00423018 00000036 66c562d0 66c55e10 66c562d0 6ebebafc 7fe0: 66c55cb0 66c55ca0 004114bd 66cebd72

Allocated by task 216: tee_shm_alloc+0x15c/0x7e8 tee_ioctl+0x8d0/0x2e44 sys_ioctl+0x918/0x1e70 ret_fast_syscall+0x0/0x58 0x66c55ca0

Freed by task 215: kasan_set_free_info+0x20/0x34 __kasan_slab_free+0xdc/0x108 kfree+0x98/0x294 tee_shm_release+0x1dc/0x610 dma_buf_release+0x180/0x2a0 __dentry_kill+0x488/0x6ac __fput+0x2f0/0x7b4 task_work_run+0x178/0x230 do_work_pending+0xaf8/0x10a8 slow_work_pending+0xc/0x20 0x66d5bd16

The buggy address belongs to the object at 86467000 which belongs to the cache kmalloc-64 of size 64 The buggy address is located 32 bytes inside of 64-byte region [86467000, 86467040) The buggy address belongs to the page: page:(ptrval) refcount:1 mapcount:0 mapping:00000000 index:0x0 pfn:0x46467 flags: 0x200(slab|zone=0) raw: 00000200 00000000 00000122 82401200 00000000 00200020 ffffffff 00000001 page dumped because: kasan: bad access detected

Memory state around the buggy address: 86466f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86466f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

86467000: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc ^ 86467080: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc 86467100: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc ==================================================================

root@kitploit:~
Questa vulnerabilità è stata scoperta eseguendo fuzzing sul driver TEE senza che fosse stata stabilita alcuna sessione con una TA esistente in esecuzione sul sistema. Ciò potrebbe essere ulteriormente esteso con le cosiddette pseudo syscall in syzkaller per impostare e avviare una sessione verso una qualche TA.

## Analisi della causa principale

La conclusione è un problema di progettazione nel tracciamento del ciclo di vita di un oggetto `tee_shm:dmabuf`. Il driver è progettato per lasciare che lo spazio utente mantenga l'unico e solo contatore di riferimenti dopo una chiamata a `tee_ioctl_shm_alloc()`.

Si presume che se l'oggetto è ancora presente nell'oggetto IDR del driver, allora il riferimento al dmabuf sia ancora valido e il suo contatore di riferimenti possa essere incrementato. In realtà questo è solo parzialmente vero. La memoria del dmabuf è ancora di proprietà del driver dmabuf, ma potrebbe essere in procinto di essere distrutta e questo non può essere fermato riportando il contatore di riferimenti a un valore diverso da zero.

Lo scenario che innesca il problema è un'applicazione multi-thread in cui un thread chiude il descrittore di file del dmabuf nello stesso momento in cui un altro thread effettua una chiamata al comando IOCTL `TEE_IOC_OPEN_SESSION` o `TEE_IOC_INVOKE` facendo riferimento a quella memoria condivisa.

Tracciando la distruzione del dmabuf quando lo spazio utente chiude il fd, nel kernel verrà eseguito questo codice:

1. `fput()`

2. `fput_many()`  >> Il contatore dei riferimenti del file raggiunge lo zero. Si apre la finestra di race condition.

3. `[task_work gets scheduled]`

4. `__fput`

5. `dput`

6. `dma_buf_release`

7. `tee_shm_release`

     8. `mutex_lock(teedev->mutex)`

     9. `idr_remove(teedev->idr, shm->id)` >> Ora l'oggetto shm non può più essere referenziato dallo spazio utente. La finestra di race condition si chiude.

     10. `mutex_unlock()`
  
Questo significa che la tabella IDR  e il suo mutex non possono garantire che il dmabuf e il corrispondente `tee_shm` siano ancora vivi. Un processo che compete con `fput()` chiamando `tee_shm_get_from_id()` può ottenere un riferimento a uno shm che sta per essere distrutto.```
/**
 * tee_shm_get_from_id() - Find shared memory object and increase reference
 * count
 * @ctx:    Context owning the shared memory
 * @id:     Id of shared memory object
 * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure
 */
struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id)
{
    struct tee_device *teedev;
    struct tee_shm *shm;
 
    if (!ctx)
        return ERR_PTR(-EINVAL);
 
    teedev = ctx->teedev;
    mutex_lock(&teedev->mutex);
    shm = idr_find(&teedev->idr, id);
    if (!shm || shm->ctx != ctx)
        shm = ERR_PTR(-EINVAL);
    else if (shm->flags & TEE_SHM_DMA_BUF)
        get_dma_buf(shm->dmabuf);
    mutex_unlock(&teedev->mutex);
    return shm;
}

Sfruttamento della UAF

Per sfruttare questo problema, deve essere effettuata una riallocazione dopo che l'oggetto è stato liberato e prima di innescare la UAF. Dopo la chiamata a tee_shm_get_from_id(), viene chiamata la funzione tee_shm_put() (per cui si verifica il secondo crash UAF da syzkaller) che dereferenzia l'oggetto tee_shm:dmabuf usato come argomento di input per dma_buf_put().``` /**

  • tee_shm_put() - Decrease reference count on a shared memory handle
  • @shm: Shared memory handle */ void tee_shm_put(struct tee_shm *shm) { if (shm->flags & TEE_SHM_DMA_BUF) dma_buf_put(shm->dmabuf); } EXPORT_SYMBOL_GPL(tee_shm_put);
root@kitploit:~
L'oggetto `tee_shm` potrebbe essere riallocato prima della UAF poiché appartiene alla cache kmalloc-64. Dovrebbe essere riallocato con:

1. oggetti fittizi `tee_shm`, `tee_shm:dmabuf`, `dma_buf:file`
2. impostare `file->f_count = 1`
3. creare un oggetto `file:file_operations` che abbia il puntatore a funzione `fasync` impostato su un indirizzo arbitrario

Questa funzione viene poi invocata in `__fput()` dopo la chiamata a `dma_buf_put()` quando `file->f_count` raggiunge lo zero.

PAN (Privileged Access Never) mitiga questo aspetto poiché gli oggetti fittizi devono essere referenziati nella memoria dello spazio utente per poter impostare un puntatore a funzione arbitrario nella struttura `file:f_ops`. Pertanto, `CONFIG_CPU_SW_DOMAIN_PAN` deve essere disabilitato affinché funzioni, e lo è nell'ambiente fornito. Rimangono alcune domande aperte sulla possibilità di aggirare PAN in questa vulnerabilità, ad esempio usando ret2dir.

Inoltre, per effettuare con successo la riallocazione dell'oggetto shm deallocato, la chiamata IOCTL `TEE_IOC_OPEN_SESSION` o `TEE_IOC_INVOKE` deve essere soggetta a preemption da parte di un thread che esegue la chiusura del file descriptor e di un thread di heap spraying che riempie la cache kmalloc-64. Affinché ciò funzioni, il kernel deve essere configurato con `CONFIG_PREEMPT`. In questo PoC è stato utilizzato l'heap spray dal post del blog di Nicolas Fabretti [7], basato su `sendmsg()` bloccante.

Per riassumere, il problema per quanto riguarda lo sfruttamento è che sia la free che la UAF devono avvenire all'interno della stessa chiamata di sistema. Inoltre, la free è difficile da innescare perché richiede una race condition all'interno della syscall. Dopo la free, il tempo tra questa e l'effettiva UAF è una piccola finestra temporale in cui deve essere eseguito un heap spray per riallocare l'oggetto deallocato. La figura seguente mostra i thread coinvolti nel codice dell'exploit e il loro ruolo.

<p align="center">
  <img src="https://raw.githubusercontent.com/pjlantz/pjlantz.github.io/master/docs/assets/Threads.png?raw=true" alt="Threads involved" width="50%" height="50%"/>
       <br /><em>Figure 3: Threads involved in the exploit code</em>
</p>

  
Tre tipi di thread sono in esecuzione continua. Per preemptare il thread che effettua la chiamata di sistema, esso gira con la priorità più bassa possibile, `SCHED_IDLE`, mentre gli altri hanno la priorità impostata su `SCHED_OTHER`. Poiché stiamo usando `sendmsg()` bloccante, ogni tentativo di spray deve girare nel proprio thread e deve girare sullo stesso core CPU che innesca la UAF, dato che ogni core mantiene le proprie cache kmalloc. Ci sono anche diversi thread di freeing che chiudono il file descriptor dell'allocazione di memoria condivisa del passaggio 1b). Il codice sorgente completo per questo trigger di UAF e la sovrascrittura del puntatore a funzione si trova in [10].

## Setting up the new environment
Per riprodurre l'ambiente con un kernel vulnerabile e OPTEE, può essere clonato dal seguente repository e compilato usando:```
$ mkdir optee-qemu && cd optee-qemu
$ repo init -u https://github.com/pjlantz/optee-qemu.git
$ repo sync
$ cd build
$ make toolchains -j2
$ make run

After successful build, it will spawn three consoles, one for QEMU - press 'c' in the QEMU console in order to boot. A second console shows output from the secure world and the final one will boot into Linux. Login as root (no password).

Run the exploit code until the fasync function pointer of the file_operations structure is set to 0x22000000.``` until optee_exploit | grep "0x22000000" /var/log/messages; do sleep 0.01; done

root@kitploit:~
Questo si fermerà a causa del blocco dell'esecuzione Privileged execute-never (PXN) a `PC=0x22000000`. Da qui in poi, le strategie di sfruttamento possono variare a seconda della versione del kernel, ma potrebbe essere possibile eseguire una ROP nel kernel e fare stack pivoting, oppure rendere scrivibile l'area vDSO e collocare lì il payload. Potrebbe anche essere interessante, per lavori futuri, verificare se la PAN può essere aggirata usando ret2dir e un po' di physmap spraying. La PAN può essere abilitata nel kernel impostando `CONFIG_CPU_SW_DOMAIN_PAN=y` in `linux/.config`. Su hardware reale, è abilitata per impostazione predefinita su ARMv8.1 e AArch64; per ARMv7 e AArch32 è possibile avere una PAN emulata via software usando questa impostazione [8]. 

**Nota**: questo exploit non è molto ottimizzato e potrebbe occasionalmente bloccare il driver se riesce a liberare l'oggetto di memoria condivisa troppo presto; in questo caso PC sarà in `tee_shm_get_from_id()`. Se ciò accade, esegui un `system_reset` nella console QEMU per riavviare l'ambiente.

## Ringraziamenti
Grazie a Lars Persson di Axis Communications per l'aiuto con l'analisi della causa radice e a Jens Wiklander di Linaro, nonché maintainer del sottosistema TEE, per una comunicazione fluida e la rapida risoluzione di questo problema [9].

## Riferimenti 

[1] CVE-2021-44733 - https://nvd.nist.gov/vuln/detail/CVE-2021-44733

[2] TEE subsystem - https://www.kernel.org/doc/html/latest/staging/tee.html

[3] Globalplatform TEE API - https://globalplatform.org/specs-library/?filter-committee=tee

[4] OP-TEE OS - https://github.com/OP-TEE/optee_os

[5] BKK16-110: A Gentle Introduction to Trusted Execution and OP-TEE - https://connect.linaro.org/resources/bkk16/bkk16-110/

[6] Syzkaller - https://github.com/google/syzkaller 

[7] Lexfo's security blog, by Nicolas Fabretti: CVE-2017-11176: A step-by-step Linux Kernel exploitation - https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part3.html

[8] Linux Kernel Security Subsystem: Exploit Methods/Userspace data usage - http://kernsec.org/wiki/index.php/Exploit_Methods/Userspace_data_usage

[9] [PATCH v2] tee: handle lookup of shm with reference count 0 - https://lore.kernel.org/lkml/[email protected]/T/ 

[10] Proof of concept exploit - https://github.com/pjlantz/optee_examples/tree/master/exploit/host
Scarica lo strumento