ソースコード内の見えない脆弱性

脆弱性または悪意あるコードを埋め込み、手動による監査さえも迂回することが可能な「Trojan Source攻撃」とは。

ケンブリッジ大学のエキスパートにより、現代のほとんどのコンパイラに影響するとされる脆弱性に関するレポートが発表されました(英語資料)。この新たな攻撃手法は開発ツールの正規機能を利用するもので、ソースコードが示すものとはまったく異なるものがコンパイルされます。このようなことが起きるのは、Unicodeの制御文字が原因です。

並べ替え攻撃に関連するUnicodeの方向制御文字

並べ替え攻撃に関連するUnicodeの方向制御文字。出典

制御文字は、画面に表示されることはほとんどありませんが(表示するエディターもあります)、何らかの方法でテキストを修正します。例えば、このページ(英語)に記載されているUnicode Bidirectiona(BiDi)アルゴリズムのコードがあります。

ご存知のように、人間の言語には、左から右へ書かれるもの(英語など)と、右から左へ書かれるもの(アラビア語など)があります。コードに1つの言語しか含まれない場合は問題ありませんが、例えば1行に英語とアラビア語の単語が含まれているような場合には、BiDiコードでテキストの方向を指定します。

この研究では、例として、このようなコードを使ってPythonコードのコメント区切りを行の途中から最後に移動させました。具体的には、RLIコードを適用して数文字だけ移動させ、残りの文字は影響を受けないようにしています。

BiDiを使用した脆弱性のあるPythonコードの例

BiDiを使用した脆弱性のあるPythonコードの例。出典

右側は、プログラマーがソースコードをチェックするときに見えるコードです。左側は、そのコードがどのように実行されるかを示しています。ほとんどのコンパイラは制御文字を無視します。コードをチェックする人は、5行目を無害なコメントだと考えるでしょうが、実際には、その中に隠された早期リターンによって、このプログラムは銀行口座からの引き落とし操作をスキップすることになるのです。つまり、このプログラムの実行によってお金は引き出されますが口座の残高は減りません。

なぜこれが危険なのか

一見すると、この脆弱性はささいなものに見えます。見えない文字を挿入してソースコードを監査する人の目を欺こうなどと、誰が考えるでしょうか。それでもなお、この問題は、共通脆弱性識別子(CVE-2021-42574)の割り当てに値するほど深刻であると判断されました(リンク先は英語)。研究者たちは、この論文を発表するに当たり、パッチを準備する猶予期間を持たせるために主要なコンパイラの開発元へ事前に問題を知らせました。

このレポートでは、基本的な攻撃の可能性が概説されています。実行戦術は2つあり、一つはコメント内にコマンドを隠すこと、もう一つは、例えば画面に表示される行に何かを隠すことです。理論的には、この逆、つまりコマンドのように見えて実際にはコメントの一部であり、実行されることのないコードを作成することも可能です。このほかにも、さらに独創的な方法が存在することでしょう。

例えば、このトリックを使用することで、巧妙なサプライチェーン攻撃を仕掛けることが可能です。一見正しいように見えて実は意図どおりに機能しないコードを請負業者が提供し、最終生産物がリリースされ、その後に外部の人間がこの「オプション」を使って顧客を攻撃することができるようになる、といった具合です。

実際どれほど危険なのか

この論文が発表されて間もなく、プログラマーのラス・コックス(Russ Cox)氏は、この「Trojan Source」攻撃に対する批判を展開しました(英語記事)。彼は以下のように主張しています。

  • これは新しい攻撃でも何でもない。
  • 多くのコードエディタでは、シンタックスハイライトを使って「見えない」コードを表示している。
  • コンパイラにパッチを適用する必要はない。コードを注意深くチェックして、偶発的なバグまたは悪意あるバグを見つけ出せれば十分。

確かに、Unicode制御文字の問題は、例えば2017年に表面化しています(英語記事)。また、ホモグリフ(同じように見えてコードが異なる文字)関連の問題も、新しいものではない上に、無関係なコードが手動チェックの目に止まらないようにすることが可能です。

ただし、コックス氏の批判的分析は、この問題の存在を否定するものではなく、この問題に関する報道が大げさであると非難する内容です。例えば、ジャーナリストのブライアン・クレブス(Brian Krebs)氏による黙示録的な記事『Trojan Source’ Bug Threatens the Security of All Code(トロイの木馬ソースのバグがすべてのコードのセキュリティを脅かす)』などは、そうした批判に当たるものです。

この問題は実在します。しかし幸いなことに、解決策は非常にシンプルです。このような文字を含むコードのコンパイルは、リリース済みまたは近日リリース予定のパッチで防ぐことができます(例えば、Rustコンパイラの開発元はすでにセキュリティアドバイザリを公開しています)。独自のソフトウェアビルドツールを使用している場合は、ソースコード内にあってはならないはずの隠し文字について同様のチェックを追加することをお勧めします。

サプライチェーン攻撃の危険

多くの企業は、開発作業を外部に委託したり、既製のオープンソースモジュールをプロジェクトに使用したりしています。こうした開発環境は、サプライチェーンを通じた攻撃を受ける可能性があります。サイバー犯罪者は、開発委託先のセキュリティを侵害したり、オープンソースプロジェクトにコードを埋め込んだりして、最終版のソフトウェアに悪意あるコードを混入させることができます。このようなバックドアはコード監査によって発見されるものですが、発見されなかった場合、信頼できる提供元からソフトウェアを入手したエンドユーザーは、データを抜き取られることになります。

Trojan Sourceは、これよりもはるかに洗練された攻撃の一例です。このようなアプローチを使って、攻撃者は、最終製品に何メガバイトもの悪意あるコードを忍ばせるのではなく、検知しにくいインプラントをソフトウェアの重要部に埋め込み、何年にもわたってそれを悪用することが可能なのです。

安全でいるために

Trojan Source型の攻撃からの防御としては、以下の対策をお勧めします。

  • 使用しているプログラミング言語のコンパイラをすべて更新する(パッチがリリースされている場合)。
  • ソースコード中の限られた範囲の制御文字を検出する独自のスクリプトを作成する。

サプライチェーン攻撃に対抗するには、手動によるコード監査とさまざまな自動テストを実施する必要があります。自分のコードをサイバー犯罪者の視点で見て、セキュリティの仕組みを破壊しかねない単純なエラーを見つけ出すことは、決して悪いことではありません。このような分析を行うリソースが社内にない場合は、外部の専門家に依頼することを検討してください。

ヒント