
Table des Matières
Les systèmes informatiques modernes intègrent souvent facilement CPU et GPU avec des ressources de mémoire et microarchitecturales partagées. Bien que cette intégration offre d'énormes avantages de performance, elle apporte également des risques significatifs sous la forme de canaux cachés et de canaux couverts. Ceux-ci permettent aux attaquants d'exfiltrer des informations inter-composants, contournant l'isolation traditionnelle des processus.
Cet article offre une revue technique approfondie des canaux couverts inter-composants sur des CPU intégrés, en se concentrant particulièrement sur ceux qui exploitent des composants microarchitecturaux partagés—caches, prédicteurs de branche, et autres. Nous explorerons les fondements théoriques, la faisabilité en monde réel, les démonstrations de code, et les stratégies d'atténuation actuelles. Que vous soyez un débutant en sécurité ou un chercheur avancé, ce guide couvre les modèles de menace, les preuves de concept pratiques, et les meilleures pratiques de défense.
Un canal couvert est un chemin de communication qui n'a pas été conçu pour le transfert d'informations. En informatique, le terme fait souvent référence à des scénarios où un processus (l'émetteur, ou processus "haut") transmet délibérément des informations à un autre processus (le récepteur, ou processus "bas") de manière interdite par la politique de sécurité.
Les canaux couverts ne se limitent pas au trafic réseau. Beaucoup existent à des couches système inférieures, y compris les canaux de stockage (utilisant des fichiers, des temps de mémoire, etc.) et les canaux temporels (différences de disponibilité des ressources).
Les CPU et GPU modernes utilisent des ressources partagées pour des raisons d'efficacité :
Lorsque deux processus partagent ceux-ci, ils peuvent signaler des informations en utilisant les changements d'état ou de temps du matériel partagé, même lorsqu'aucune communication directe n'est autorisée.
Les canaux couverts les plus notoires sont basés sur le cache :
Les deux attaques exploitent la nature partagée des caches CPU multiniveaux, en particulier le cache de dernier niveau (LLC).
Les CPU modernes utilisent des prédicteurs de branche pour accélérer l'exécution. Ces prédicteurs sont partagés entre les processus et parfois entre les cœurs. Si un émetteur entraîne le prédicteur, le récepteur peut sonder et observer les changements de prédiction, permettant la transmission de données.
Voir : "Canaux couverts à travers les prédicteurs de branche : une étude de faisabilité"
Les systèmes intégrés CPU-GPU partagent la DRAM et parfois même des composants plus fins (par exemple, LLC, bus système). Ce partage de ressources inter-composants ouvre de nouvelles surfaces d'attaque, en grande partie inexplorées :
La recherche académique examine les attaques où le CPU et le GPU, ou différents processus s'exécutant sur l'un ou l'autre, forment un canal couvert à travers des lignes de cache ou une largeur de mémoire partagée (Leaky Buddies).
clflush).Point Clé: Les différences de temps révèlent les actions de l'émetteur.
Utilisé principalement dans les environnements cloud, où la mémoire partagée peut ne pas exister.
Voir "Canaux couverts à travers les prédicteurs de branche : une étude de faisabilité" pour la démonstration de l'attaque.
Commencez par recueillir les informations sur le cache CPU et le prédicteur de branche.
# Liste des détails du cache CPU
lscpu | grep -i cache
# Avancé : analyser directement les tailles de cache CPU
cat /proc/cpuinfo | grep -E 'cache size|model name'
# Liste des bibliothèques partagées mmapées par un processus
pidof firefox # Par exemple
cat /proc/<pid>/maps | grep r-xp | grep 'lib'
# Python : Analyser pour rechercher des régions d'objets partagés
import os
pid = <your_pid>
with open(f"/proc/{pid}/maps") as f:
for line in f:
if 'lib' in line and 'r-xp' in line:
print(line.strip())
// gcc -O2 -o flush_reload flush_reload.c
#include <stdio.h>
#include <stdint.h>
#include <x86intrin.h>
uint64_t measure_access_time(volatile char *addr) {
uint64_t start = __rdtscp(&start);
*(volatile char *)addr;
uint64_t end = __rdtscp(&end);
return end - start;
}
int main() {
char *ptr = ...; // map vers un objet partagé
while (1) {
_mm_clflush(ptr); // Émetteur : ou saut pour le Récepteur
uint64_t t = measure_access_time(ptr);
printf("Access time: %lu\n", t);
}
}
import ctypes
import time
# Mappage d'une bibliothèque/fichier partagé, par exemple via mmap
libc = ctypes.CDLL("libc.so.6")
address = ctypes.c_void_p(...)
def measure_access_time(addr):
t1 = time.perf_counter_ns()
dummy = ctypes.c_char.from_address(addr.value)
val = dummy.value
t2 = time.perf_counter_ns()
return t2 - t1
while True:
t = measure_access_time(address)
print(f"Access time: {t}ns")
// Pseudocode pour l'émetteur et le récepteur dans l'attaque par prédicteur de branche
// Bit de données à communiquer : 0 ou 1
// Émetteur : "entraîner" le prédicteur de branche
if (bit_to_send == 1) {
for (int i = 0; i < 1000; i++) { if (cond) foo(); }
} else {
for (int i = 0; i < 1000; i++) { if (!cond) foo(); }
}
// Récepteur : mesurer le temps de mésinterprétation de branche
uint64_t t1 = rdtscp();
if (cond) foo();
uint64_t t2 = rdtscp();
uint64_t elapsed = t2 - t1;
if (elapsed > THRESHOLD) decode as bit 1 else 0;
Note : Aucune atténuation n'est parfaite—les compromis impliquent performance/sécurité.
Celles-ci représentent un sur-ensemble de canaux cachés/couverts, exploitant l'exécution spéculative (Spectre, Meltdown) et d'autres instructions exécutées transitoirement pour fuir l'état via des canaux microarchitecturaux :
Voir la série de conférences "Canaux Cachés et Exécution Transitoire" pour des analyses visuelles/temporelles.
perf stat ...)# Surveille les cache miss et mésprévisions de branche
sudo perf stat -e cache-misses,branch-misses ./your_app
import psutil
# Surveille l'utilisation du cache et du CPU de chaque processus au fil du temps
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent']):
print(proc.info)
Les canaux couverts inter-composants mettent en évidence un risque critique et persistant dans la sécurité microarchitecturale. À mesure que les CPU et GPU deviennent plus intégrés, la frontière sur laquelle les données secrètes peuvent fuir s'élargit, allant des caches CPU partagés aux prédicteurs de branche sophistiqués et aux ressources cross-CPU-GPU.
Les défenses nécessitent des efforts coordonnés matériel, OS, et logiciel—et viennent toujours avec des coûts de performance. Plus l'attaque est profonde, plus le choix est difficile.
Pour les chercheurs, continuer à énumérer, modéliser, et atténuer les nouvelles techniques de canaux couverts inter-composants est un processus continu. Pour les organisations, la modélisation des menaces et la prise de conscience de la situation sont vitales.
Pour les dernières recherches et divulgations de vulnérabilités, surveillez fréquemment les sites académiques/congressions de confiance et les avis CVE.
Si vous avez trouvé ce contenu utile, imaginez ce que vous pourriez accomplir avec notre programme de formation élite complet de 47 semaines. Rejoignez plus de 1 200 étudiants qui ont transformé leur carrière grâce aux techniques de l'Unité 8200.