インターネット上の誰かが間違っている
遅くとも 5 日前に、「Apple M1 に M1RACLES の脆弱性が見つかりました - アプリケーション間の高速の非表示データ転送が可能です」という見出しの下にニュースが Habré に掲載されました。 Apple M1 で、誰でも非特権モードから読み書きできるレジスタを見つけました。これは、OS によって提供されるプロセス間通信メカニズムをバイパスしてデータを交換するために使用できることを意味します。ただし、説明のコメントに次のように書いているように、作者自身はこの機能を重大な脆弱性とは考えていません。
それで、このウェブサイトのポイントは何ですか?
最近、情報セキュリティのクリックベイトの脆弱性の報告がいかにばかげているかをからかう派手な Web サイトがあるからといって、ニュースになったからといって、気にする必要はありません。
ここまで読んだらおめでとう!あなたは、ページ タイトルに基づいてリツイートするだけではない珍しい人の一人です :-)
しかし、ジャーナリストはどのバグが悪いか、そうでないかをどのように判断する必要がありますか?
人に話します。特に、バグを発見した人以外の人に相談してください。後者は、実際の影響について正直かもしれないし、正直でないかもしれません。
「隠蔽通信路」という言葉を聞いたら、おそらく誇張されていると思います。これらのほとんどは、実質的なセキュリティへの影響がほぼゼロで、同じ概念を無限にリサイクルしている製紙工場からのものです。タイトルは通常、クリックベイトであり、時には実に欺的です。
この出版物へのコメントでは、発見の状況について適度に活発な議論が解き放たれました: それは深刻な脆弱性か、それとも些細なことですか? @SergeyMaxと@wataruとともに、クライアント ソフトウェアまたは仮想マシンを実行するハードウェアが共有環境であり、状態の適切な変調によって任意のデータが作成されるため、とにかく秘密の交換のチャネルが十分にあるという事実に注目しました。基盤となる OS またはハイパーバイザーの不変条件に関係なく、交換が可能です。尊敬される紳士@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 , .