コンパイラはあなたのセキュリティチェックを無効化する
Compiler Can Undo Your Security Checks

安全なCコードを書いても、コンパイラの最適化がセキュリティ保護を削除し、脆弱性を生み出すことがある。Black HatでChris Domas氏が、C抽象マシンの仕様によりコンパイラがコードを劇的に変換できる仕組みを解説。データサイズが17バイトや33バイトでは安全でも、近いサイズでは脆弱になる例や、AIで5億行のコードを分析し300の危険パターンを発見した話も。開発者向けに警告の有効化、サニタイザの使用、最適化ビルドの分析、出荷するバイナリそのもののテストを推奨。
CPUはあなたのソースコードを実行しない。コンパイラが生成したものを実行するのだ。
HNでの議論
67- omoikane
コンパイラがmemsetを削除することについて言えば、最適化で消されないことが保証されているメモリゼロ化関数が複数あります:
https://cppreference.com/c/string/byte/memset (memset_s)
https://cppreference.com/cpp/string/byte/memset (memset_explicit)
また、memset_sが標準になる前に人々が使っていた他の様々な関数についてはnotesセクションも参照してください。
- johnbender
重要な問題は、コンパイルが暗黙の(コンパイラ作者の頭の片隅にある)正しさの概念に基づいて動作することです。それはごく大まかに言えば「観測可能な振る舞いの保存」であり、ここで「観測可能」とはシステムコールの列とその戻り値のことです。つまり、コンパイラの最終出力は、新たな観測可能な振る舞いの列を決して追加してはならないのです。
一方、セキュリティ特性は非常に多くの場合、これらの列の間の関係に関するものです。たとえば、外部の観測者/攻撃者が外部からの観測によって内部状態を区別できない(機密性)と言いたいとき、それは同じ開始観測状態から出発した、異なる隠れた値を持つ2つの観測可能なトレースが異なる観測を持たないことを要求します。
LTSに詳しい人なら、この違いをトレース特性対ハイパー特性として知っているでしょう。コンパイラは前者を保存しようとしますが、後者は保存しません。
別に、「何が観測可能か?」という問題もあります。たとえば、観測可能な振る舞いにタイミングを含めると、観測を保存できるコンパイラパスの種類は急速にゼロに近づく傾向があります。
- Narishma
タイトルは「あなたのCコンパイラはセキュリティチェックを無効化できる」であるべきだ。
- bmandale
変なサイトだな。どうやらHNからの訪問者が嫌いらしく、コンソールを開かせたくないようだ。自分が歓迎されていないことは分かる。
- Hizonner
コンパイラは、結果が元のコードと全く同じように外界と相互作用することを証明できれば、コードを変換することが許されているのだろう?何もXを変更できなかったことを証明できれば、「Xの値はすでにチェックした」という前提で最適化できる。
まあ、多くのコンパイラが、外界が何に影響を与えたり観測したりできるかについて、正当化されない仮定を置いているように思える。仕様に促されてかもしれないし、そうでないかもしれない。