4月17日、セキュリティ研究者が「MAD Bugs: Even "cat readme.txt" is not safe」と題した記事を公開した。この記事では、macOS上で広く使われているターミナルアプリケーション「iTerm2」のSSH統合機能を悪用することで、単純なcatコマンドでさえコード実行につながる可能性があることについて詳しく紹介されている。以下に、その内容を紹介する。
「catコマンドすら安全でない」— ターミナルエミュレータの新たな脅威
cat readme.txtのような単純なコマンドが危険になるという話は一見すると荒唐無稽に聞こえる。しかし、macOS上でデファクトスタンダードとなっているiTerm2を使っている場合、これは現実の脅威である。
iTerm2は、標準のTerminal.appよりも高機能なターミナルエミュレータとして多くの開発者に愛用されている。特にSSH統合機能は、リモートサーバーでの作業をより快適にする機能として注目されてきた。しかし、この便利な機能こそが今回の脆弱性の根源となっている。
iTerm2のSSH統合機能とconductorの仕組み
iTerm2のSSH統合機能は、従来のSSHクライアントとは異なるアプローチを取っている。単純に「コマンドをリモートシェルに盲目的に入力する」のではなく、リモート側にconductorと呼ばれる小さなヘルパースクリプトを配置する仕組みだ。
動作の流れは以下のようになる:
- iTerm2がSSH統合を開始(通常は
it2sshコマンド経由) - iTerm2がconductorスクリプトをリモート側に送信
- リモートのconductorがiTerm2のプロトコルパートナーとなる
- iTerm2とリモートのconductorがターミナルエスケープシーケンスを使って以下を調整:
- ログインシェルの発見
- Pythonインタープリターの確認
- ディレクトリ変更の同期
- ファイルアップロード
- コマンド実行
重要なのは、別途ネットワークサービスは存在しないということだ。conductorはリモートシェルセッション内で動作するスクリプトに過ぎず、プロトコルは通常のターミナルI/Oを通じて運ばれる。
PTYと信頼境界の破綻
現代のターミナルエミュレータは、1970年代のハードウェアターミナルをソフトウェアで再現したものだ。シェルやコマンドラインプログラムは、依然として本物のターミナルデバイスのように見えるものと通信することを期待している。そのため、OSはPTY(疑似ターミナル)という仕組みを提供している。
通常のSSHセッションでは:
- iTerm2がPTYにバイトを書き込む
- フォアグラウンドプロセスが
sshプロセス sshがそれらのバイトをリモートマシンに転送- リモートのconductorがstdinからそれらを読み取る
SSH統合プロトコルは、以下のターミナルエスケープシーケンスをトランスポートとして使用する:
DCS 2000p: SSHコンダクターをフックするために使用OSC 135: プリフレーマーコンダクターメッセージに使用
バグの本質は信頼境界の破綻である。iTerm2は、実際に信頼できる本物のconductorセッションから来ていないターミナル出力からでも、SSHコンダクタープロトコルメッセージを受け入れてしまう。つまり、信頼できないターミナル出力がリモートconductorになりすまし、コード実行を引き起こせる。
巧妙な攻撃手法の詳細
攻撃者が用意するファイルには、偽のconductorトランスクリプトが含まれている。被害者が以下を実行すると:
cat readme.txt
iTerm2はファイルをレンダリングするが、そのファイルは単なるテキストではない。以下の要素が巧妙に仕込まれている:
- conductorセッションを宣言する偽の
DCS 2000p行 - iTerm2のリクエストに応答する偽の
OSC 135メッセージ
フックが受け入れられると、iTerm2は通常のconductorワークフローを開始する。ソースコードレベルでは、Conductor.start()が即座にgetshell()を送信し、それが成功するとpythonversion()を送信する流れになっている。
攻撃は最小限だが正確な偽のOSC 135メッセージを使用する:
getshell用のコマンドボディを開始- シェル発見出力のような行を返す
- そのコマンドを成功で終了
pythonversion用のコマンドボディを開始- そのコマンドを失敗で終了
- アンフック
この手順により、iTerm2は通常のフォールバックパスを通る。iTerm2がSSH統合ワークフローの十分な部分を完了したと判断すると、次のステップであるrun(...)コマンドの構築と送信に進んでしまう。
実証コードと再現方法
元記事では、genpoc.pyスクリプトを使って攻撃を再現できることが示されている。攻撃には2つのファイルが必要だ:
ace/c+aliFIo- 実行可能なヘルパースクリプトreadme.txt- 悪意のあるDCS 2000pとOSC 135シーケンスを含むファイル
攻撃が成功するには、攻撃者が用意した実行可能ファイルを含むディレクトリからcat readme.txtを実行する必要がある。これにより、最終的に攻撃者が作成したペイロードが実際の実行可能パスとして解決され、コード実行に至る。
修正状況と今後の対応
脆弱性の報告と修正の timeline は以下の通りだ:
- 3月30日: バグをiTerm2開発チームに報告
- 3月31日: コミット
a9e745993c2e2cbb30b884a16617cd5495899f86でバグが修正 - 記事執筆時点(4月17日): 修正はまだ安定版リリースに到達していない
iTerm2ユーザーは、公式GitHubから最新版を確認し、修正版がリリースされ次第アップデートすることが推奨される。
セキュリティ業界への示唆
この脆弱性は、ターミナルエミュレータの高度な機能が思わぬセキュリティリスクを生み出すことを示している。特に重要なのは:
- 信頼境界の明確化: プロトコル設計において、何を信頼し何を信頼しないかを明確にする必要性
- エスケープシーケンスの危険性: ターミナル制御用のエスケープシーケンスが攻撃ベクターとなりうること
- 機能の複雑化によるリスク: 便利な機能ほど、予期しない副作用を持つ可能性があること
この種の脆弱性は、2024年頃からターミナルエミュレータ分野で注目を集めており、他のターミナルアプリケーションでも類似の問題が発見される可能性が高い。開発者は信頼できないソースからのファイルをcatする際に、より一層の注意を払う必要があるだろう。
詳細はMAD Bugs: Even "cat readme.txt" is not safeを参照していただきたい。