
Índice
Sistemas de computação modernos frequentemente apresentam componentes de CPU e GPU perfeitamente integrados com memória compartilhada e recursos microarquiteturais. Embora essa integração ofereça imensos benefícios de desempenho, ela também traz riscos significativos na forma de canais laterais e canais ocultos. Estes permitem que atacantes exfiltrem informações entre componentes, contornando o isolamento tradicional de processos.
Este post oferece uma revisão técnica aprofundada dos canais ocultos entre componentes em CPUs integradas, especialmente focando naqueles que exploram componentes microarquiteturais compartilhados—caches, preditores de ramificação e outros. Exploraremos fundamentos teóricos, viabilidade no mundo real, demonstrações de código e estratégias atuais de mitigação. Seja você um iniciante em segurança ou um pesquisador avançado, este guia cobrirá modelos de ameaça, PoCs práticos e melhores práticas de defesa.
Um canal oculto é um caminho de comunicação que não foi projetado para transferência de informações. Em computação, o termo frequentemente se refere a cenários onde um processo (o remetente, ou processo "alto") deliberadamente transmite informações a outro processo (o receptor, ou processo "baixo") de maneira proibida pela política de segurança.
Os canais ocultos não se limitam ao tráfego de rede. Muitos existem em camadas de sistema mais baixas, incluindo canais de armazenamento (usando arquivos, sincronismo de memória, etc.) e canais de tempo (diferenças na disponibilidade de recursos).
CPUs e GPUs modernas usam recursos compartilhados por eficiência:
Quando dois processos compartilham esses recursos, eles podem sinalizar informações usando alterações no estado ou no tempo de hardware compartilhado, mesmo quando nenhuma comunicação direta é permitida.
Os canais ocultos mais notórios são baseados em cache:
Ambos os ataques exploram a natureza compartilhada dos caches multinível da CPU, especialmente o cache de último nível (LLC).
CPUs modernas usam preditores de ramificação para acelerar a execução. Esses preditores são compartilhados entre processos e às vezes entre núcleos. Se um remetente treina o preditor, o receptor pode sondar e observar mudanças na predição, permitindo a transmissão de dados.
Veja: "Canais ocultos através de preditores de ramificação: um estudo de viabilidade"
Sistemas integrados CPU-GPU compartilham DRAM e, às vezes, até componentes mais finos (por exemplo, LLC, barramentos do sistema). Este compartilhamento de recursos entre componentes abre novas superfícies de ataque, em grande parte inexploradas:
Pesquisas acadêmicas examinam ataques onde a CPU e a GPU, ou diferentes processos em execução em cada um, formam um canal oculto através de linhas de cache ou largura de banda de memória compartilhadas (Leaky Buddies).
clflush).Ponto-chave: Diferenças de tempo revelam as ações do remetente.
Usado principalmente em ambientes em nuvem, onde a memória compartilhada pode não existir.
Veja "Canais ocultos através de preditores de ramificação: um estudo de viabilidade" para demonstração do ataque.
Comece reunindo informações sobre caches da CPU e preditores de ramificação.
# Lista detalhes do cache da CPU
lscpu | grep -i cache
# Avançado: analise tamanhos de caches da CPU diretamente
cat /proc/cpuinfo | grep -E 'cache size|model name'
# Lista bibliotecas compartilhadas mmapadas por um processo
pidof firefox # Por exemplo
cat /proc/<pid>/maps | grep r-xp | grep 'lib'
# Python: Analisar para procurar regiões de objetos compartilhados
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 = ...; // mapear para objeto compartilhado
while (1) {
_mm_clflush(ptr); // Remetente: ou pule para Receptor
uint64_t t = measure_access_time(ptr);
printf("Tempo de acesso: %lu\n", t);
}
}
import ctypes
import time
# Mapear uma biblioteca/arquivo compartilhado, por exemplo, 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"Tempo de acesso: {t}ns")
// Pseudocódigo para remetente e receptor em ataque de preditor de ramificação
// Bit de dados para comunicar: 0 ou 1
// Remetente: "treina" preditor de ramificação
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(); }
}
// Receptor: mede tempo de erro de predição de ramificação
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;
Nota: Nenhuma mitigação é perfeita—os trade-offs envolvem performance/segurança.
Estes representam um superconjunto de canais laterais/ocultos, explorando execução especulativa (Spectre, Meltdown) e outras instruções executadas transitoriamente para vazar estado via canais microarquiteturais:
Veja a série de aulas "Canais Laterais e Execução Transitória" para uma análise visual/temporal.
perf stat ...)# Monitorar falhas de cache e predições de ramificação
sudo perf stat -e cache-misses,branch-misses ./seu_app
import psutil
# Monitore o uso de cache e CPU de todo processo ao longo do tempo
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent']):
print(proc.info)
Os canais ocultos entre componentes destacam um risco crítico e persistente na segurança microarquitetural. À medida que CPUs e GPUs se tornam mais integradas, a fronteira sobre a qual dados secretos podem vazar se amplia, desde caches compartilhados da CPU até preditores de ramificação sofisticados e recursos entre CPU-GPU.
As defesas exigem esforços coordenados de hardware, SO e software—e sempre vêm com custos de desempenho. Quanto mais profundo o ataque, mais difícil a escolha.
Para pesquisadores, continuar a enumerar, modelar e mitigar novas técnicas de canais ocultos entre componentes é um processo contínuo. Para organizações, a modelagem de ameaças e a conscientização situacional são vitais.
Para pesquisas mais recentes e divulgações de vulnerabilidades, monitore frequentemente sites acadêmicos/conferências confiáveis e avisos de CVE.
Se você achou este conteúdo valioso, imagine o que você poderia alcançar com nosso programa de treinamento de elite abrangente de 47 semanas. Junte-se a mais de 1.200 alunos que transformaram suas carreiras com as técnicas da Unidade 8200.