脆弱性サマリー:Cista v0.15 における逆シリアライizationメモリアドレスの漏洩 脆弱性概要 Cista v0.15 およびそれ以前のバージョンでは、安全でない逆シリアライゼーションの問題が存在します。信頼できない入力データを逆シリアライズする際、 シリアライザが十分な検証チェックを行わないため、メモリアドレスが漏洩する可能性があります。攻撃者はオフセット(例えば -8 から 0 へ)を変更することでポインタを自身を指すようにし、印刷処理の際に自身のアドレスを漏洩させることができます。 影響範囲 影響を受けるバージョン:Cista v0.15 およびそれ以下 潜在的なリスク: - スタックアドレスまたはヒープアドレスの漏洩 - ASLR や PIE などのセキュリティ保護機構の回避 - 後の攻撃への道を開く 修正策 1. 「既知の」アドレスのハッシュマップを維持する: - が同一メモリ領域を二度参照することを防止する - タイプの混入(Type Confusion)を捕捉する(各領域は単一の型としてのみ解釈されるべきである) - 注意:この戦略は、バッファのサイズと容量を表すために2つの u64 を使用するコンテナ(例:vector)には無効な可能性があります 2. 自己参照ポインタを回避する: - オフセット=0 の自己参照ポインタを使用する POC コード サンプル 1:ポインタが自身を指す場合 サンプル 2:ポインタがペイロード内の任意のアドレスを指す場合 サンプル 3:vector が自身を指す場合 サンプル 4:unique_ptr がペイロード内の任意のアドレスを指す場合 サンプル 5:スタック上に宣言されたバッファ ```cpp // Minimal Reproducible Example 5 - buffer declared on stack #include #include #include #include #include "cista.h" namespace data = cista::raw; struct A { data::vector v; }; int main(int argc, char** argv) { std::vector buf; { A data; data.v = data::vector({1, 2, 3}); buf = cista::serialize(cista::mode::DEEP_CHECK std::cout << "v.size(): " << data.v.size() << std::endl; for (int i = 0; i < data.v.size(); i++) { std::cout << "v[" << i << "]: " << data.v[i] << std::endl; } } std::cout << "out:\n"; for (int i = 0; i < buf.size(); i++) { for (int j = 0; j < 16 && i < buf.size(); i++, j++) { std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (uint16_t)buf[i] << ((i+1) % 8 ? " " : " "); } std::cout << std