Spectre¶
Bir victim'i, architecturally çalıştırmayacağı instruction'ları transiently yürütmeye yönlendir, secret'ı microarchitectural state'e encode et ve onu bir covert channel üzerinden kurtar.
Mechanism¶
Note
Modern CPU'lar speculate eder. Branch-resolution ve bellek latency'sini gizlemek için branch'lerin sonucunu (yön ve target) öngörür ve ileri koşar; instruction'ları transiently — program sırasının dışında ve kontrol eden koşul bilinmeden önce — yürütür. Tahmin yanlışsa CPU architectural sonuçları (register'lar, flag'ler, bellek) atar ve doğru path'e yeniden yönlenir. Spectre'nin suistimal ettiği invariant: rollback yalnızca architectural'dır. Transiently yürütülen instruction'lar yine de squash'tan sağ çıkan microarchitectural yan etkiler — en ünlüsü cache'e çekilen bir line — bırakır.
Kocher et al. saldırıyı, "a victim to speculatively perform operations that would not occur during correct execution" yönlendirmek ve confidential bilgiyi "via a side channel to the adversary" sızdırmak olarak tanımlar. Bu yüzden attacker (1) bir predictor'ı eğitir/poison'lar ki victim seçilen bir path'e mis-speculate etsin, (2) transient path'in secret-dependent bir bellek erişimi yapmasını ayarlar ve (3) secret'ı microarchitectural footprint'ten FLUSH+RELOAD gibi bir covert channel üzerinden kurtarır. Meltdown'un aksine Spectre bir faulting instruction'a dayanmaz — victim'in kendi kodunun doğru speculation'ını suistimal eder.
Walkthrough¶
Kocher et al.'den kanonik disclosure gadget'ı (Spectre Variant 1, PHT/bounds-check bypass):
// array1_size, array1, array2 are in the victim. x is attacker-influenced.
if (x < array1_size) {
y = array2[array1[x] * 4096]; // transiently runs for out-of-bounds x
}
-
Predictor'ı eğit. Gadget'ı in-bounds
xile tekrar tekrar çağır ki branch predictor bounds check'in "taken" (true) olduğunu öğrensin. -
Mistrain + tetikle. Out-of-bounds bir
xver. Hâlâ "true" öngören CPU, gövdeyi transiently yürütür: secret bytearray1[x]'i okur, onu distinct cache line'lara yaymak için page boyutuyla (4096) çarpar vearray2'yi indexlemek için kullanır. Bu load,array2'nin secret-dependent bir line'ını cache'e getirir. -
Covert channel ile kurtar. Misspeculation squash edildikten sonra,
array2boyunca erişimleri zamanla (FLUSH+RELOAD). Tek hızlı (cache'lenmiş) line secret byte'ı ortaya koyar.
flush(array2); // evict all probe lines
victim_function(malicious_x); // transient secret-dependent load happens here
for (i = 0; i < 256; i++) // reload-and-time each candidate line
if (reload_time(&array2[i * 4096]) < THRESHOLD)
recovered = i; // cached line == leaked byte value
Spectre ailesinin kavramsal yapısı
Tüm varyantlar arasındaki ortak invariant: bir microarchitectural predictor yönlendirilir, bir transient secret-dependent erişim gerçekleşir ve bir covert channel sonucu exfiltrate eder. Varyantlar yalnızca hangi predictor'ın suistimal edildiğinde farklılaşır.Detection¶
Temiz bir architectural iz yoktur — tasarımı gereği transient path geri alınır. Hardware performance counter'ları (branch misprediction'ları, cache miss'leri) gürültülü vekillerdir ve kolayca atlatılır; pratik savunma detective değil, preventive'dir.
Mitigation¶
Mitigation'lar varyant başınadır ve software ile hardware/microcode'u birleştirir:
serialize eden barrier'lar (lfence), PHT için Speculative Load Hardening /
branchless bounds masking ve BTB için indirect-branch kontrolleri (retpoline,
IBRS/eIBRS, IBPB, STIBP). Indirect-branch'e özel savunmalar için BTB notlarına
bak. Canella et al.'ye göre, deploy edilmiş tek bir savunma her varyantı kapsamaz.
Ayrıca bkz.: Spectre-BTB, FLUSH+RELOAD, PRIME+PROBE.