Edited at

端末に意図しないコントロールキャラクタを漏らしてはならない

More than 5 years have passed since last update.

このポストでは、端末にコントロールキャラクタ・エスケープシーケンスが意図せず漏れてしまうことがどんな作用を引き起こしうるか、という話と、すでに各端末最新版でほぼ対応が完了している(任意のコードが最新版端末のデフォルト設定で確実に実行されてしまうような状況はもう確認されなくなった)と思われるタイトルレポーティング等にまつわる問題について書いてみます。

特に端末で動作するアプリケーションを書く人にとって、留意しておいた方が良い事案だとは思います。


結論


  • アプリケーションが外部から受け取ったデータを端末に流す(表示する)ときは、C0/C1の範囲の文字が含まれていないかチェックしましょう。

  • 端末エミュレータのアップデートには脆弱性の修正が含まれることがあるので、常に最新版にしておくのがおすすめです。


アプリケーションはコントロールキャラクタを漏らさないようにする

通常コントロールキャラクタというと、C0(\x00-\x1f,\x7f)、C1(\x80-\x9f,\xff)の範囲の文字を指します。アプリケーションの出力からはこの範囲の文字をきちんと意図して出す必要があります。

たとえば外部からもらってきた文字列を端末に表示するときは、この範囲の文字を潰したり代替文字で起き替えたりするようにアプリケーションを設計するべきです。

しかし現実にはそうは言っていられない場合(cygwinでWin32 Consoleアプリケーションを動かしたときなど)も多く、こういった状況下では端末サイドで大変なことにならないように対応を入れている、というのが実情です。

例を挙げてみます。

pythonのSimpleHTTPServerは端末上で

python -m SimpleHTTPServer

のように起動した場合、簡易Webサーバーが立ち上がり、アクセス状況を端末にロギングします。

SimpleHTTPServerがそのまま実運用されることはほぼ無いのでさしたる問題では無いはずなのですが、これは特殊なHTTPリクエストを送ってやることで外部から容易にエスケープシーケンスを紛れ込ませることができ、意図しない挙動を引き起こすことが可能です。

またいわゆる「冗長なUTF-8シーケンス」を使用することでコントロールキャラクタと同等の作用が引き起こされる、という抜け道を持つ端末もありました。もちろん私の知る限りでは最新版ですでに修正されていますが、アプリケーション側でも留意しておくにこしたことはありません。

一方アプリケーション側の対応はというとcursesを使用したものはほとんど大丈夫、と言ってよいと思います。しかしそうではないものは、C0レンジのサニタイズしか考慮されていなかったり、ちょっとしたいたずらを仕掛けることで容易に任意のエスケープシーケンスを漏らすことができたりするものが多く、いたずらする気が無くても勝手に漏れて変なことになっている状況もあったりします。


エスケープシーケンスが紛れ込んでも、表示が崩れるだけ?

シンプルな機能しか提供しない端末や安全に留意して実装されたものであれば、表示が崩れるだけです。たいした問題ありません。

しかしタイトルレポーティング等、応答報告を利用する一部の端末機能を絡めた場合、被害が拡大します。以下の報告が参考になると思います。

'Terminal Emulator Security Issues' - MARC

この問題に、さらにいくつかの端末の特性を組み合わせることによって、最悪任意のコードをユーザーに気づかれずに実行してしまうこともできます。(私の知る範囲の端末ではこの問題は最新版では修正されています)

アプリケーションサイドでは、こういった点を十分に留意しておく必要があります。


C1コントロールの扱い

盲点となっている事案として、8bit系におけるC1コントロールの扱いがあります。

普段あまり意識されることは無いと思いますが、端末には7bitモード(7bit符号系、7単位符号系)の端末と、8bitモード(8bit符号系、8単位符号系)のものがあります。

7bit端末におけるコントロールキャラクタの範囲は、\x00-\x1f,\x7f(C0)なのですが、ISO-2022 8bit端末ではこれに加え、\x80-\x9f,\xff(C1)もコントロールとして意味を持ちます。さらに、UTF-8モードの8bit端末では2バイトで1文字となる、\u0080-\u009f,\u00ffもC1コントロールとして扱われることがありますが(Markus Kuhnによる主張)、このあたりの方針は端末によって混乱しているというのが実情で、サニタイズの仕方が難しいのです。

これについては、DECSCLなどを出して8ビットコントロールを使えないようにする、という対策が考えられますが、個人的にはもうデフォルトで8ビットコントロール無効化でよいのでは、と感じています(ただエミュレータという側面があるソフトウェアなので話がややこしいです)。


まとめ

今回のタイトルレポーティングなどの問題は既知の話であるため書きましたが、個人的にこれからもっとセキュリティ上の検討をしなければいけないなと感じている領域に貼り付け周りの問題があります。

端末エミュレータは主として開発者が使用するツールであったりするのでこのあたりのチェックが甘いのが現状ですが、攻撃者が特定の開発組織をターゲットにする、という状況も考えられなくもないと思います。

いずれにしろこういったことに留意して端末アプリケーションを書く、ということを作法として定着させた方が健全なのではないでしょうか。