Seseorang di internet salah
Paling lambat lima hari yang lalu, berita muncul di Habré di bawah judul " Kerentanan M1RACLES ditemukan di Apple M1 - transfer data tersembunyi cepat antar aplikasi dimungkinkan ." Dalam satu kalimat, esensinya dirumuskan sebagai berikut: di Apple M1 mereka menemukan register yang dapat dibaca dan ditulis siapa pun dari mode non-istimewa. Ini berarti dapat digunakan untuk bertukar data melewati mekanisme komunikasi antarproses yang disediakan oleh OS. Namun, penulis sendiri tidak menganggap fitur ini sebagai kerentanan yang signifikan, seperti yang ia tulis di komentar penjelasan:
Jadi apa gunanya situs web ini?
Mengolok-olok betapa konyolnya pelaporan kerentanan clickbait infosec akhir-akhir ini. Hanya karena memiliki situs web yang mencolok atau membuat berita tidak berarti Anda perlu peduli.
Jika Anda sudah membaca sampai ke sini, selamat! Anda adalah salah satu orang langka yang tidak hanya me-retweet berdasarkan judul halaman :-)
Tapi bagaimana wartawan bisa tahu bug mana yang buruk dan bug mana yang tidak?
Bicaralah dengan orang-orang. Secara khusus, bicaralah dengan orang lain selain orang yang menemukan bug tersebut. Yang terakhir mungkin atau mungkin tidak jujur tentang dampak nyata.
Jika Anda mendengar kata-kata “saluran rahasia”… mungkin terlalu berlebihan. Sebagian besar berasal dari pabrik kertas yang tanpa henti mendaur ulang konsep yang sama dengan dampak keamanan praktis yang hampir nol. Judul biasanya clickbait, dan terkadang benar-benar menipu.
: - ? @SergeyMax @wataru , , , . @creker @adjachenko, , M1RACLES.
. PoC ~500 C++, . , , M1RACLES .
, .
: , , , . , MMU, , , .
M1RACLES, Apple . , . ; PoC, , , , RAM ( ), ..
, :
void drivePHY(const bool level, const std::chrono::nanoseconds duration)
{
static auto deadline = std::chrono::steady_clock::now();
deadline += duration; //
if (level) //
{
std::atomic<bool> finish = false;
const auto loop = [&finish]() {
while (!finish) { }
};
static const auto thread_count = std::max<unsigned>(1, std::thread::hardware_concurrency());
std::vector<std::thread> pool;
for (auto i = 0U; i < (thread_count - 1); i++)
{
pool.emplace_back(loop);
}
while (std::chrono::steady_clock::now() < deadline) { }
finish = true;
for (auto& t : pool)
{
t.join();
}
}
else // --
{
std::this_thread::sleep_for(deadline - std::chrono::steady_clock::now());
}
}
, . , API CPU core affinity (macOS, , ), , . , API affinity , , :
#include <pthread.h> // -lpthread
cpu_set_t cpuset{};
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
, :
constexpr std::chrono::nanoseconds ChipPeriod{16'000'000}; // . 1...100
std::bitset<CDMACodeLength> CDMACode("..."); //
void emitBit(const bool value)
{
for (auto i = 0U; i < CDMACode.size(); i++)
{
const bool bit = value ^ !CDMACode[i];
drivePHY(bit, ChipPeriod);
}
}
( ) , , ( ):
void emitByte(const std::uint8_t data)
{
emitBit(1); //
auto i = 8U; //
while (i --> 0)
{
emitBit((static_cast<std::uintmax_t>(data) & (1ULL << i)) != 0U);
}
}
void emitFrameDelimiter()
{
for (auto i = 0U; i < 20; i++) // 9
{
emitBit(0);
}
}
CRC-16-CCITT:
void emitPacket(const std::vector<std::uint8_t>& data)
{
emitFrameDelimiter();
std::uint16_t crc = CRCInitial;
for (auto v : data)
{
emitByte(v);
crc = crcAdd(crc, v);
}
emitByte(static_cast<std::uint8_t>(crc >> 8U));
emitByte(static_cast<std::uint8_t>(crc >> 0U));
emitFrameDelimiter();
}
- , — .
, - . , . , ( ) :
bool readPHY()
{
static auto deadline = std::chrono::steady_clock::now(); // .
deadline += SampleDuration;
const auto started_at = std::chrono::steady_clock::now();
std::vector<std::int64_t> counters;
const auto loop = [&counters](std::uint32_t index) {
auto& cnt = counters.at(index);
while (std::chrono::steady_clock::now() < deadline)
{
cnt++;
}
};
static const auto thread_count = std::max<unsigned>(1, std::thread::hardware_concurrency());
if (thread_count > 1)
{
counters.resize(thread_count, 0);
std::vector<std::thread> pool;
for (auto i = 0U; i < thread_count; i++)
{
pool.emplace_back(loop, i);
}
for (auto& t : pool)
{
t.join();
}
}
else
{
counters.push_back(0);
loop(0);
}
const double elapsed_ns =
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - started_at).count();
const double rate = double(std::accumulate(std::begin(counters), std::end(counters), 0)) / elapsed_ns;
static double rate_average = rate;
rate_average += (rate - rate_average) / PHYAveragingFactor;
return rate < rate_average; //
}
, , , , . (.., ) , .
, . , . () , .
CDMA , :
. , . ; , , . , .
: , . , .
. . , ; , , .
. , , , .
, , , , , . - LDPC , .
, , . , :
https://github.com/pavel-kirienko/cpu-load-side-channel
:
, ffmpeg ( 4K ), ~30 , . () , .
: , 16 , 1023 , .., 16 , 0.06 . CRC . - ?
M1RACLES ( 8 Mb/s), . - ( 0 b/s), .
, . , . , , ChipPeriod
CDMACodeLength
PoC ( Manjaro 5.4 Intel Core i7 990X @ 4 GHz).
( ) -, . , , , ; , . .
(airgapped networks), Mordechai Guri . , , , , , .
/r/netsec , Hector Martin, M1RACLES. : ; M1RACLES , , . , -, ; , "" .
, , . Hector Martin , , , . , , , M1RACLES , - . :
We already know all systems are vulnerable to certain side-channel attacks. In particular, all systems with shared resources have side channels. Those side channels are easy to turn into covert channels, as you did. The bandwidth, and the severity, is proportional to how closely coupled the security domains are (as you found out, where the VM boundary reduces your performance). As the severity gets higher, you go from 1 bit per second covert channels, to megabytes per second covert channels, to actually being able to steal data from noncooperative entities (actual dangerous side channels) under increasingly less demanding circumstances.
[...]
So M1RACLES is interesting because it is not a side channel - so it poses no danger of leaking data from unwitting processes - but it is a highly efficient covert channel, which does matter under a very small but not nonexistent set of attack scenarios. Does it add covert channel capability where none existed prior? No. But that doesn't mean it's not a vulnerability; as I said, we don't qualify systems on some kind of absolute "vulnerable/not vulnerable" scale. We look at individual issues and then figure out how they affect the overall security of the system under certain attack scenarios.
Mordechai Guri, . , , . , .
:
.
, .
M1RACLES , .