
Artefatti di ricerca per attacchi side-channel basati sulle notifiche dei file su Linux, Windows e macOS, che dimostrano la fuga di informazioni tramite inotify/FSEvents, il timing dei tasti e il fingerprinting dei siti web.
Questo repository contiene gli artefatti (ancora in revisione!) per il paper "File Notification Attacks: Templating and Exploiting Side-Channel Leakage from the File-Notification Systems on Linux, Windows, and macOS", accettato a CCS '26.
Visita il sito web con le demo su: https://inoti.fyi/
Leggi il paper su: https://snee.la/pdf/pubs/file-notification-attacks.pdf o http://inoti.fyi/pubs/file-notification-attacks.pdf
Come parte della valutazione degli artefatti a CCS'26 (ancora in corso!), abbiamo fornito una VM Debian 13 + KDE Plasma 6 con un kernel pre-patchato. Questa VM non è stata utilizzata per produrre i risultati di valutazione del paper e non è pensata per riprodurne l'esatta magnitudine. Questo repository potrebbe essere aggiornato per incorporare le revisioni e i feedback dei nostri valutatori di artefatti. Renderemo la VM pubblicamente accessibile quando la nostra valutazione degli artefatti sarà completata.
Abbiamo impiegato Claude (Opus 4.8) per incapsulare il nostro codice in artefatti decentemente documentati e ad alte prestazioni (ad esempio, quello per Windows era un po' lento). Tuttavia, il codice, gli script e i makefile generati erano basati su
Le istruzioni per testare il codice Linux di seguito sono specifiche per
l'esecuzione di comandi nella VM. Si prega invece di guardare il codice in
Linux/.
La VM esiste puramente per comodità, in modo che il montaggio di ogni attacco non richieda una configurazione dell'ambiente da zero o un downgrade del kernel. Il meccanismo sottostante dimostrato nella VM è identico a quello descritto nel paper, ma si noti che non abbiamo utilizzato la VM per produrre i numeri riportati nel paper. I tempi assoluti possono differire a causa dell'ambiente virtualizzato e dell'hardware sottostante.
I risultati sono riprodotti all'interno di una VM Debian 13 (linux-vm/),
installata dall'ISO live ufficiale di Debian con KDE Plasma 6 (Wayland)
installato con un kernel precedente alla correzione di
fsnotify.
Sono installati inotify-tools, gli header di sviluppo Qt6 e pkexec. Nient'altro
viene aggiornato e il kernel non viene mai toccato dopo l'installazione. Si
prega di NON eseguire apt upgrade o tentare di aggiornare il kernel.
Questa immagine della VM è deliberatamente vecchia, non è aggiornata e non
dispone delle ultime patch di sicurezza. Questa immagine della VM è pensata
solo per una rapida validazione e test!
Il codice, gli attacchi e le dimostrazioni presenti all'interno della VM sono
rispecchiati in Linux/.
Nota: Indichiamo come quale utente eseguire i comandi all'inizio di ogni
blocco di comandi. C'è [host], che è la macchina host che esegue la VM,
[user] che è la vittima degli attacchi nella VM, e [spyuser] che richiede
di essere configurato e sarà l'attaccante nella maggior parte degli attacchi
Linux.
L'immagine del disco è fornita come linux-vm-upload.qcow2, compressa con zstd.
Rinominarla in linux-vm.qcow2 prima di eseguire run.sh (che si aspetta quel
nome di file):
# Run As: [host]
cd linux-vm/
mv linux-vm-upload.qcow2 linux-vm.qcow2
./run.sh
La lettura di un qcow2 compresso con zstd richiede qemu-img/qemu-system-x86_64
versione 5.2 o successiva (2020+), verificare con qemu-img --version. Se si
utilizza una versione precedente di QEMU e questa non riesce ad aprire
l'immagine, decomprimerla prima in un qcow2 flat:
qemu-img convert -O qcow2 linux-vm-upload.qcow2 linux-vm.qcow2
4 core, 4GB di RAM, display GUI. Le credenziali di accesso sono:
root, password password,user, password password,spyuser, password password (non effettuare il login come spyuser!)La VM fornita esegue già un kernel vulnerabile e pre-patchato
(6.12.43+deb13-amd64), quindi non è necessario alcun downgrade per
utilizzarla. Sarà necessario QEMU per eseguire questa immagine (che ha una GUI).
L'artefatto si trova in /home/user/Linux-File-Notification-Attacks all'interno
della VM.
Un singolo comando configura tutto da zero nella VM: (i) un account spyuser
non privilegiato (non-sudo), (ii) la propria copia della directory degli
artefatti (un account non privilegiato separato non può altrimenti accedere
alla home directory di user), (iii) e ogni script reso eseguibile in entrambe
le copie.
# In the VM, Run As: [user]
sudo bash ~/Linux-File-Notification-Attacks/setup_attacks.sh
Ogni attacco di seguito viene eseguito come spyuser (su - spyuser, password
password), tranne auth-ui-redress, che viene eseguito come user (spiegato
di seguito).
Dimostra che le notifiche delle operazioni sui file vengono consegnate per file che non possono essere letti direttamente, purché la loro directory genitore sia leggibile.
# Run As: [spyuser]
# To switch to spyuser, in a new terminal type `su - spyuser`. The password
# is `password`.
cd ~/Linux-File-Notification-Attacks/unreadable-file-bypass
./watch-syslog.sh
Lasciarlo in esecuzione, poi generare una riga di log da un altro terminale
come user:
# Run As: [user]
logger "hello"
Questa immagine Debian 13 non ha rsyslog, quindi non esiste un file
/var/log/syslog come mostrato nel paper. Lo script ripiega sul monitoraggio
di /var/log/journal/<machine-id>/. È la stessa idea, poiché i file .journal
monitorati sono di proprietà di root (utente) e systemd-journal (gruppo),
nessuno dei quali è spyuser.
Misura il ritardo di notifica di inotify.
# Run As: [user], ensure numpy is installed (or pip3)
sudo apt install python3-numpy
# Run As: [spyuser]
cd ~/Linux-File-Notification-Attacks/temporal-resolution
./run.sh
watcher apre un watch inotify su un file di test e registra il timestamp di
ogni IN_ACCESS che riceve. accessor legge lo stesso file 1000 volte con un
ritardo casuale di 5-10ms tra le letture, registrando il timestamp di ogni
lettura stessa. stats.py confronta le due registrazioni di timestamp e stampa
il ritardo medio/deviazione standard/minimo tra il verificarsi della lettura e
l'arrivo della notifica, ovvero la risoluzione temporale di inotify.
Non è l'attacco completo del paper, ma solo la primitiva di proof-of-concept del
filtraggio su cui si basa l'attacco: per ogni tasto premuto ovunque sul sistema,
stampa una notifica con timestamp, senza mai leggere direttamente /dev/input.
# Run As: [spyuser]
cd ~/Linux-File-Notification-Attacks/inter-keystroke-timing
make
./find-keyboard.sh
Digitare in qualsiasi finestra (magari un nuovo terminale come user). Ogni
pressione di tasto stampa una riga KEYPRESS. La finestra di soppressione (che
abbiamo scelto euristicamente per questa dimostrazione è di 130ms) unisce
diversi eventi IN_ACCESS generati da una singola pressione fisica di un tasto.
In pratica, abbiamo notato che questa finestra è diversa per hardware diversi
(ad esempio, tastiere meccaniche, stili di digitazione).
Se il rilevamento automatico seleziona il dispositivo sbagliato (o nessuno),
controllare /proc/bus/input/devices ed eseguirlo direttamente con
./build/keystroke-notify /dev/input event4.
Dimostriamo la capacità di rilevare quando viene eseguito
(pkexec)[https://polkit.pages.freedesktop.org/polkit/], e di disegnare
ulteriormente una finestra falsa sopra di essa. Come mostrato nella Sezione
4.4.3, questo 'attacco di auth UI redress' è possibile su KDE Plasma 5 e 6 con
Wayland. Eseguiamo questo attacco nel modello di minaccia dell'attaccante
stesso-utente: il socket Wayland è limitato alla sessione connessa, e un account
non privilegiato separato non può disegnarci sopra.
Su un'installazione KDE standard pkexec viene incluso dal desktop, ma questa
ISO live è un'immagine più snella, e quindi non lo ha installato. Pertanto,
l'abbiamo installato manualmente mentre (cercavamo di) mantenere piccola
l'immagine della VM.
# Run As: [user]
cd ~/Linux-File-Notification-Attacks/auth-ui-redress
make
./inotify-watcher-with-gui
Lasciarlo in esecuzione in un terminale. Da un altro terminale (la directory non
ha importanza), attivare un vero prompt pkexec, ad esempio pkexec ls. Il
watcher vede l'accesso a /usr/bin/pkexec e disegna una falsa finestra di
dialogo "Authentication Required" (window-launcher) sullo schermo sopra
quella reale. Digitando nella finestra falsa e premendo Authenticate, il testo
inserito viene stampato sul terminale del watcher, che poi si chiude. Si noti
che la finestra falsa è deliberatamente diversa da quella reale per un facile
confronto.
Monitorare le directory dei font mentre una pagina si carica rivela quali file di font ha toccato. Siti diversi richiamano font diversi, quindi l'insieme dei percorsi stampati durante il caricamento di una pagina è già un'impronta digitale, senza bisogno di timing o classificatori per questa versione minimale.
Per prima cosa, come utente, aprire Firefox (cliccarlo tramite l'icona nel dock
del task manager in fondo allo schermo) e assicurarsi che nessun sito web sia
aperto. Poi, in un terminale come spyuser:
# Run As: [spyuser]
cd ~/Linux-File-Notification-Attacks/website-fingerprinting-fonts
./compare-fonts.sh
Questo compila font-spy che inizia a monitorare le directory dei font
utilizzate da Firefox. Lo script compare-fonts ti invita a visitare due siti
web.
Per prima cosa, visita un sito web (magari wikipedia.com) e attendi qualche secondo che si carichi, apri una nuova scheda, chiudi la vecchia scheda (con il sito web), e poi premi INVIO nel terminale.
Secondo, fai lo stesso con un altro sito web (magari reddit.com): visita il sito web e attendi qualche secondo che si carichi, apri una nuova scheda, chiudi la vecchia scheda, e poi premi INVIO nel terminale.
Lo script dovrebbe stampare la differenza nei font acceduti per sito web. Si noti che nel paper abbiamo anche utilizzato le informazioni temporali, ovvero, quando il font è stato acceduto. Per un semplice proof-of-concept, ignoriamo questa informazione e stampiamo semplicemente la differenza tra i due insiemi di accessi ai font. Sebbene l'insieme esatto degli accessi ai font possa differire tra le esecuzioni, ci sono alcuni file di font che sono sempre e unicamente acceduti da un sito web.
Si noti che i siti web possono cambiare nel tempo, e quindi gli accessi ai file
di font possono differire. Al momento della stesura di questo artefatto, notiamo
che Wikipedia accede sempre a
/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf e Reddit accede
sempre a /usr/share/fonts/truetype/vlgothic/VL-Gothic-Regular.ttf.
Un dispositivo fisico o emulatore che esegue una versione di Android il cui
modello di Scoped Storage consente ancora di registrare un FileObserver (il
wrapper a livello Java attorno a inotify) sulle directory dei media condivisi
di WhatsApp, e un secondo dispositivo/account per agire come mittente del
messaggio. Compilare il sorgente fornito (Android/source/) o installare
direttamente l'APK fornito (Android/app-release.apk).
Android espone la stessa primitiva inotify utilizzata in tutti i risultati
Linux tramite android.os.FileObserver. La Sezione 5.4.3 mostra che un'app non
privilegiata e senza permessi può registrare un tale observer sulle directory
dei media di WhatsApp e, puramente dal flusso risultante di eventi
open/close/access, inferire che un media privato è stato ricevuto, senza
possedere alcun permesso che le consenta di leggerne il contenuto stesso.
Avviare l'app e attivare l'azione di aggiornamento; il servizio observer si
collega e inizia a emettere periodiche voci di liveness. Scorrere fino in fondo
alla vista del log e continuare ad aggiornare finché non compaiono ripetute
voci ObserverService: Still Running, confermando che il watch è attivo e
stabile.
Da un secondo account, inviare un'immagine o un documento alla conversazione
osservata e, se non già in cache, scaricarlo sul dispositivo osservato. Questo
produce una raffica di righe di log di eventi sui file; immediatamente dopo
l'ultima voce ObserverService: Still Running prima della raffica, il log
dovrebbe mostrare eventi open/close/access i cui percorsi corrispondono al file
ricevuto, dimostrando che il suo arrivo è osservabile puramente dai metadati
delle notifiche del file system.
Forniamo il codice sorgente che può essere compilato con msys2. In alternativa, si può anche usare il file exe (Windows/firefox-fingerprint/monitor.exe).
Una macchina Windows (o VM) con MSYS2 installato, e la
toolchain MinGW-w64 g++ (pacman -S mingw-w64-ucrt-x86_64-gcc, eseguito da
una shell MSYS2). Firefox installato.
Questo proof of concept utilizza
ReadDirectoryChangesW
per monitorare ricorsivamente tutto C:\, e stampa solo gli eventi il cui
percorso contiene http (directory di archiviazione per-origin che Firefox
nomina secondo lo schema/host del sito, ad esempio sotto le sue cartelle
cache/IndexedDB). Non sono richiesti privilegi di amministratore per monitorare
una directory che si può elencare. Questa archiviazione per-origin viene scritta
a ogni caricamento di pagina, quindi monitorare dall'esterno del processo del
browser rivela comunque quale sito è stato appena visitato.
Usare l'exe che forniamo (Windows/firefox-fingerprint/monitor.exe) o compilare da una shell MSYS2 UCRT64:
# Run in an MSYS2 UCRT64 shell
cd Windows/firefox-fingerprint
g++ -municode -static -O2 -o monitor.exe monitor.cpp
Usare g++, non gcc. Inoltre eseguire monitor.exe da un terminale (non
facendo doppio clic su di esso), altrimenti non c'è alcuna console collegata su
cui stampare.
Il watcher viene eseguito come secondo account locale non privilegiato, separato da quello che naviga. Per prima cosa, creare quell'account tramite Impostazioni:
attacker, e una password, poi
Avanti.Questo crea un account locale (non legato a un account Microsoft, nessun accesso di rete), con privilegi standard (non-admin) per impostazione predefinita.
Successivamente, mettere monitor.exe da qualche parte dove il nuovo account
possa effettivamente leggerlo ed eseguirlo. Copiare invece il binario compilato
nella directory pubblica, leggibile da tutti:
copy monitor.exe C:\Users\Public\monitor.exe
Ora, dal tuo account principale (vittima), avviarlo sotto l'account attacker
senza cambiare desktop o disconnettersi, usando runas:
runas /user:attacker "cmd /k C:\Users\Public\monitor.exe"
Inserire la password di attacker quando richiesto. cmd /k (piuttosto che
eseguire direttamente monitor.exe) mantiene aperta la finestra della console
in modo da poter osservare il suo output, mentre semplicemente
runas /user:attacker C:\Users\Public\monitor.exe funziona comunque, ma la sua
finestra si chiude nell'istante in cui il processo termina. Questo è puramente
per comodità.
Lasciare in esecuzione la finestra di monitor.exe, poi, tornando al tuo
account principale, aprire Firefox e visitare un paio di siti web diversi, ad
esempio, arstechnica.com e
reddit.com. Ogni riga stampata è una creazione/modifica/
rinomina di file sotto un percorso di archiviazione che corrisponde a http.
Siti diversi ottengono directory di origin diverse, e quindi l'insieme dei
percorsi toccati durante il caricamento di una pagina è già un'impronta
digitale.
Per semplicità, utilizziamo fswatch,
uno strumento CLI esistente, minimale e ampiamente utilizzato che incapsula
l'API nativa FSEvents. Un attaccante può utilizzare l'API FSEvents anche senza
questo strumento.
Installare fswatch, o compilare dal sorgente:
brew install fswatch
Monitorare /Applications ricorsivamente, come utente non privilegiato:
fswatch -xr /Applications
Lasciarlo in esecuzione, poi, dal Finder o da un browser, scaricare e installare
Zoom (o qualsiasi altra applicazione), quindi disinstallarla (potrebbe essere
necessario svuotare anche il cestino). fswatch stampa ogni percorso segnalato
da FSEvents sotto /Applications man mano che accade. Per una rapida
valutazione, lo stesso utente può monitorare la directory. Altrimenti, è
possibile configurare un nuovo utente e utilizzare fswatch come quell'utente.
Rilasciato sotto la Licenza MIT.