2017-09-02にPeter Wullingerが書きました :
remoteリモートdbusへのトンネル接続
☑ハードコードssh(パスなし)
☑エスケープ、解析、アンエスケープのバグがあります
☑これは文書化しないでください
systemctl
プログラムの-H
または--Host
オプション を使用すると、systemdは、D-Busライブラリに、systemd-stdio-bridge
という名前のプログラムを実行している内部でssh
を実行するように指示しますリモートマシン上。このプログラムは、リモートマシンのD-BusブローカーとローカルマシンのD-Busクライアントであるsystemctl
間の単純なメッセージポンプとして機能します。 systemctl
は、ローカルシステムと通信しているように、SSHとsystemd-stdio-bridge
を介してプロキシされているデスクトップバスと通信します。
それに応じて、これは別のsystemdセキュリティ問題かもしれないと他の人々は疑問に思いました。それは...ですか?
(これは一般的なSSHセキュリティに関する質問ではなく、この特定のsystemdメカニズムに関する質問です。 " SSHトンネリングのセキュリティへの影響は何ですか? "。これは" systemdのsystemv initと比較したセキュリティへの影響は何ですか? "のような質問でもありません。初心者にとって、これはvan Smoorenburg rc
ファイルについてはまったく意味がありません。)
Twitterでこれを議論することは、Fermatがマージナリアを介して数学的な証明を議論することに相当する現代のことです。だから、ピーター・ウリンジャーが収まるスペースがなかったものを拡大してみましょう マージン Twitterの投稿。
もちろん、systemdの人々がこれを行うことができる他の方法がありました:
ssh -x- アカウント@ホスト systemctl stuff…の代わりに
systemctl -H アカウント@ホストstuff…
systemctl
がのようなものを生成するように、ローカルドメインソケットにOpenSSHの組み込み転送メカニズムを使用します。ssh -xT -L/run/user /ユーザー/アカウント@ホスト/ bus:/ run/dbus/system_bus_socket- アカウント@ホスト/bin/trueの代わりに(そうするように)
ssh -xT- アカウント@ホスト systemd-stdio-bridge
are実際に取られたアプローチにはいくつかの問題があり、そのうちのいくつかはセキュリティです関連。しかしながら、これまでのところ、完全な脆弱性のレベルに上昇するようには見えません。
systemd-stdio-bridge
プログラムは何ですか?」まず、システム管理者がログとps
の出力を見て、これらすべての人がsystemd-stdio-bridge
をSSH経由で実行しているのではないかと考えます。 「 奇妙な 'agetty'プロセスが私のVPSで実行されています。 "からわかるように、 Weitse Venemaのagetty
プログラム について不思議に思っている人がいます MacOSには、人々をだますためのsystemd
というマルウェアがすでにあります なので、システム管理者がsystemd-stdio-bridge
についても不思議に思っていると想像するのは、一筋縄ではいきません。
問題は、これがsystemdのdocoが貧しいよりも悪い別の機会であるということです。まったくありません。 systemdの人々によって書かれた systemd-stdio-bridge
のマニュアルページ はまったくありません。したがって、システム管理者の最初の手段であるマニュアルを読むことは役に立ちません。 ( これはsystemd担当者の意図によるものです 、彼らはユースケースで実行中のプログラムを特定したいシステム管理者を含めていません。)
システム管理者が、プログラムがsystemd-bus-proxyd
と呼ばれるフェーズを通過したことを知るのに役立つ場合があります。このフェーズには、マニュアルページがありました。それとマニュアルページの両方がsystemdから削除されましたが、 古いプログラムが後でsystemd開発者のDavid Herrmannによって戻されたとき の場合、マニュアルページは一緒に復元されませんでした。 (注意して、掘り下げると、systemd-bus-proxyd
の古いマニュアルページに、systemd-stdio-bridge
の現在のコマンドラインの使用法が正しく記述されていないことに注意してください。)
Systemdの開発者がプログラムと一緒にdocoを検討した場合、現在のバグを1つ見つけた可能性があります。特定の状況でsystemctl
がsystemd-stdio-bridge
がサポートしないオプションを渡し、systemd-stdio-bridge
がsystemctl
が使用しないさまざまなオプションをサポートします。
sd_bus_set_address
のものは何ですか?」Peter Wullingerのメモの1つは、これは文書化されていないということです。これは、少なくともsystemd-stdio-bridge
プログラムのコードを読み取ろうとするシステム管理者の場合にも当てはまります。これはコンパイルされたCプログラムであり、解釈されたスクリプト言語で書かれたものではありません。 Peter Wullingerが指摘するように、sd_bus_set_address()
関数の呼び出しに依存しています。 systemdの人々はsd_bus_set_address()
のマニュアルページを提供せず、他のsystemdマニュアルページにぶら下がっているハイパーリンクを残します(- the sd_bus_new()
manualからのハイパーリンクなど) page たとえば)。
Peter Wullingerが「エスケープ、パース、エスケープされていないバグ」であると考えているものは、最初は明確ではありませんでした。しかし、内部では多くの解析が行われています。 systemdのデスクトップバスライブラリが、構成部品から "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=account%40Host,argv4=systemd-stdio-bridge,arg5=--machine=fred
"などの文字列を1か所で作成し、それらを別の場所の構成部品に戻すために解析することだけが重要です。そして、ダニエルJ.バーンスタイン(他の多くの人の間で)から、解析を回避するように設計していることを知っています。次に、アンマーシャリングして機械可読形式に戻すことをお勧めします。
Peter Wullingerがargv2=--
が存在する理由について言及していたことがわかりました。もちろん、これはよく知られた問題であり、あまりに広く例示されているとは悲しいことです。ただし、前述の余分なシリアル化と逆シリアル化における追加のより微妙な解析関連の問題は、システムの非常にその場しのぎの性質です。 argv3
で渡される等号文字は%3d
としてエスケープされることに注意してください。ただし、arg5=--machine=
の等号はエスケープされません。シリアライゼーションは、デシリアライゼーションと同じ規則に従いません。このようにして、バグとセキュリティの問題が発生します。これは、ダニエルJ.バーンスタインが最初に解析しないことで回避することを推奨したまさにその1つです。
もちろん、systemd-stdio-bridge
は、十分な丸みを持たせるためにすべてのコーナーをノックオフしていないホイールの再発明であるという概念があります。結局のところ、前述のとおり、OpenSSHには、リモートホストからローカルマシンへのSSH接続を介してローカルドメインソケットへのアクセスを転送するための、はるかに広く使用およびテストされている組み込みメカニズムがあります。 (これは、systemd開発者のDavid Herrmannがsystemd-stdio-bridge
プログラムを再導入する前の年にリリースされたOpenSSH 6.7以降で使用されています。このパッチは、systemdが存在する前の2006年から存在します。)
これに対抗することは2つのことです。
まず、リモートでプログラムを生成し、SSH接続を介して送信される標準の入出力を介してプログラムと通信することは、SSHの珍しい使用法ではありません。結局のところ、それは物事を行うrexec
モデルです。
次に、ローカルドメインソケットの転送は慎重に行う必要があります。標準のI/Oメカニズムでは、他のD-Busクライアントプログラムは(デバッグアクセスのようなトリックがなければ)転送メカニズムを使用して、リモートのD-Busブローカーに接続できません。ただし、前述のメカニズムは次のことに注意する必要があります。
/run/user/user/account@Host/
へのアクセスを許可しない/run/user/user/
がユーザー以外の誰かによって書き込み可能にならないように保護し、他の誰も一緒に来て、/run/user/user/account@Host
をこっそりとシンボリックリンクに置き換えたり、他のそのようなトリックを実行したりしないようにします。/run/user/user/account@Host/bus
がsystemctl
の複数の呼び出しの間で衝突しないように注意してください(これは、bus
だけでなく、ローカルで一意の名前を使用することで実行できます)Systemdのドキュメントとソースコードの山を掘り下げた後に作成された短いツイートについて詳しく説明します(トーンを説明する可能性のある楽しいものはありません)。
すべてが this Tweet によってトリガーされました。これは、systemdが(メイン開発者が何度も指摘したように)すべての入力を検証しないことを示しています。
_systemctl --Host <Host>
_ ドキュメントに記載されています 指定した操作をssh経由でリモートで実行します。
これがどのように機能するか
systemctlは、Hostパラメータを sd_bus_open_system_remote()
に渡します。これは、ドキュメントに記載されていない機能( バグレポート )-としても supports です。 = _<hostspec>:<machine>
_表記を使用して、特定のコンテナ内のリモートホスト上のバスに接続するように指示します。
sd_bus_open_system_remote()
は、特別なバスアドレス_unixexec:path=ssh,argv1=-xT,argv2=--,argv3=<hostname>,argv4=systemd-stdio-bridge <container>
_を作成します。これは、_$PATH
_からssh
を選択し、ターゲットマシン上のターゲットユーザーのリモート_systemd-stdio-bridge
_から_$PATH
_を選択することに注意してください。この特別なバスアドレスは、dbusの仕様と参照実装に追加されたようです systemd作成者の1人が 。
この文字列は bus_start_address()
によって(まだローカルに)解析され、任意のdbusプロキシコマンドをサポートします。 unixexec
。
そして最後に、これは bus_start_address()
をトリガーして、提供されたコマンドラインを実行し、そのプログラムのstdin/stdoutへのパイプを介してdbusを実行します。
私の考えでは、これは文書化されていない間接化の3つのレイヤーであり、_ssh <Host> systemctl --machine <machine>
_でも取得できる単純な便利な機能を取得します。
このような暗黙の魔法により、通常、内部のバグサーチャーが自動操縦になります。
まあ、それはありましたが、それは重要ではありません: 最近のコミット の前に、systemctl
は最初の_:
_より後のすべてをホスト名から取り除きますが、その他すべてを最初のコマンドラインとしてssh
に渡します引数。これはまだローカルで実行されており、コマンドラインからは非常に明白であるため、それほど問題とは思われません。
しかし、すべての複雑な性質を法として、リモートプロキシを持つことは、おそらくこれを処理するより安全な方法の1つです。 _-L
_は、SSHポート転送とローカルソケットの適切なクリーンアップと適切なセキュリティを有効にする必要があるため、問題があります。 _-W
_は、UNIXドメインソケットをサポートしていません(現時点では)。少なくとも現在の方法では、ForceCommand
を使用できます。
本当のセキュリティの脅威は、プロセス全体が本質的に文書化されていない自動化されたプロセスで明示的に実行できるものを置き換え、途中でかなりの数の仮定をハードコード化することにあると考えられます。