1 ポイント 投稿者 GN⁺ 2024-03-31 | 1件のコメント | WhatsAppで共有
  • xz.git の CMakeLists.txt 変更は、Landlock サンドボックス検出をヘッダーの存在確認から実際のコンパイルテストへ切り替える過程で、テストコード内に単独の . 文字が入り込んだ事例である
  • 新しい検査は、linux/landlock.h が存在していても必要な syscall 定義 がない可能性のあるシステムを除外するために追加された
  • コンパイルテストは <linux/landlock.h><sys/syscall.h><sys/prctl.h> をインクルードし、prctlSYS_landlock_create_rulesetSYS_landlock_restrict_selfLANDLOCK_CREATE_RULESET_VERSION を参照する
  • 従来の基準だった HAVE_LINUX_LANDLOCK_HHAVE_LINUX_LANDLOCK に変更され、SANDBOX_COMPILE_DEFINITIONSANDBOX_FOUND の設定もこの結果に従う
  • このコミットは Autotools と CMake ビルドの Linux Landlock feature test 修正であり、提示された diff は CMake 側の変更を示している

CMake における Landlock 検出方式の変更

  • 対象ファイルは xz.git の CMakeLists.txt で、変更箇所は # Sandboxing: Landlock ブロックである
  • 従来の CMake ロジックは、ENABLE_SANDBOXON または landlock で、かつ SANDBOX_FOUND でない場合に check_include_file(linux/landlock.h HAVE_LINUX_LANDLOCK_H) でヘッダーの存在だけを確認していた
  • 変更後は check_c_source_compiles により、小さな C コードを実際にコンパイルして Landlock の利用可否を確認する
    • 一部のシステムでは、linux/landlock.h があっても Linux Landlock に必要な syscall 定義が存在しない場合がある
    • テストコードは <linux/landlock.h><sys/syscall.h><sys/prctl.h> をインクルードする
    • my_sandbox() 内で prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)SYS_landlock_create_rulesetSYS_landlock_restrict_selfLANDLOCK_CREATE_RULESET_VERSION を参照する

単独文字と変数名の変更

  • 挿入されたコンパイルテストコードの include ブロックの次に、単独の . 行がある
  • 結果変数は HAVE_LINUX_LANDLOCK_H から HAVE_LINUX_LANDLOCK に変更された
  • 条件文も if(HAVE_LINUX_LANDLOCK_H) から if(HAVE_LINUX_LANDLOCK) に変更された
  • SANDBOX_COMPILE_DEFINITION の値は "HAVE_LINUX_LANDLOCK_H" ではなく "HAVE_LINUX_LANDLOCK" を使う
  • その後の SANDBOX_FOUND ON 設定は維持されている

1件のコメント

 
GN⁺ 2024-03-31
Hacker News の意見
  • 答え: https://git.tukaani.org/?p=xz.git;a=commitdiff;h=f9cf4c05edd...
    Linux の Landlock アクセス制御システムをよく知らないなら、説明はここにある: https://docs.kernel.org/userspace-api/landlock.html
    xz 公式(おそらく……)のインシデント対応ページ: https://tukaani.org/xz-backdoor/

    • つまり、その関数は後続の C コードがコンパイルできるかを確認し、その場合にだけ Landlock を有効にしていたということ?
      ところが diff の左端付近にくっついていて見分けにくい小さな ピリオド1つのせいで、C コードが常に無効になり、その結果 Landlock が常にオフになっていた、と?
      卑劣なほど見事で、見事なほど卑劣だ。最初に読んだときは自分も見落とした
    • これは もっともらしい否認可能性がある
      隠すなら Unicode の類似文字を置き換える、もっと良い方法もある。フォントによってはピクセル単位で同じに見えるものもある
      自分が流れを見落としているのかもしれないが、ここで故意だと確定したのか?
    • これはあまりに悪質で、PR 中にその場で見つかっても「おっと、自分の IDE の自動フォーマットがこうしたみたい」と言って済ませられるくらいだ
    • Lasse Collin が再び登場していて、おそらく怒っているようだ
    • 自分のバージョン管理システムは、こういうひとかたまりの緑/赤の文字列よりも、変更された文字をもっとよく強調表示してくれる気がする
  • 注意深くざっと見ていたら、明らかにあってはいけない場所にピリオドが見えたので、「思ったほど難しくないな」と思った
    画面を軽く触ったら、そのピリオドが動いた
    くそったれの モニターのホコリ

  • システムのセキュリティが、こんなにゆるい 正しさの連鎖に依存しているなんて信じられない。防げるポイントはいくらでもあった
    + # A compile check is done here because some systems have
    + # linux/landlock.h, but do not have the syscalls defined
    + # in order to actually use Linux Landlock.
    そういうシステムのヘッダーを修正して、明示的に除外されるようにすべきだ。ヘッダーが自分の機能を宣言しないなら、何の意味があるのか?
    それに、バイナリ blob が作られた後(オープンソースからコンパイルされたとしても)に、セキュリティが保たれているか確認するテストが一つもない理由も分からない
    Web サイトの決済機能だって、主要機能に対するエンドツーエンドテストなしにはデプロイしないはずだ。機能追加が安定性より優先されるという 優先順位の不一致があるように見える
    修正が単に . を削除するだけでないことを願う。HN の別の投稿で、. の削除を示しているのを今見たところだ

    • 彼はまったく新しい テストフレームワークを導入したうえで、2年かけてゆっくりバックドアを仕込んだ
    • 引用したのは Jia Tan の言葉だ [1]。その悪意ある行為者が、そもそも検査を意図的に壊しながら書いたコメントだ
      ヘッダーの修正や追加テストでは防げなかっただろう。そもそもヘッダーが壊れていた兆候はなく、追加テストも別の方法で損なわれたり、リリース tarball で無視されたりし得たからだ
      [1] https://git.tukaani.org/?p=xz.git;a=commit;h=328c52da8a2bbb8...
    • 少し横道にそれるが、GCC 9.4.0 が壊れた arm_acle.h ヘッダーを配布したことがあった [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100985] — そのヘッダーを含むコードは常にコンパイルに失敗した
      ユーザーが GCC 9.4.0 でコンパイルしようとする可能性があり、そのヘッダーに依存する機能はアプリケーションにとって中核的ではなかったため、ビルドがヘッダーの破損を検出した場合は、その機能を単にオフにして警告を出した
      xz に戻ると、セキュリティが最優先事項でないなら、オプション機能の失敗を無視して続行するのも合理的に見える。もちろん事後的には非難しやすいが、その文脈を除けば、完全に筋が通らない判断というわけではない
    • オープンソースのユーザーとして、こういう提案をできるほど詳しくはないので、直接開発して貢献してくれるならありがたいと思う
    • 引用したコメントコードが正確だと分かっているのか?
  • うわ、彼の最後のコミットは セキュリティ報告をさらに悪化させている: https://git.tukaani.org/?p=xz.git;a=commitdiff;h=af071ef7702...

    • なぜこれが受け入れられたんだ? 純粋に気になる
  • Landlock はどこで/どのように使われる想定だったのだろう?
    圧縮/展開のような汎用ライブラリでは、実際には使いにくそう。ライブラリはプログラムが何をすべきか、何を制限すべきかを知り得ない
    プログラムならもっと明確かもしれない
    sshd への攻撃では liblzma をライブラリとして使っていた。なら Landlock を無効にすることは無関係に見えるのでは? まだ見つかっていない悪いコードがさらにあるか、後で入れる計画だったという合図なのだろうか?

    • おそらく sshd 自体が、実行の特定の時点以降に自分の権限をロックダウンするために使っていたのだろう
      Landlock を取り除けば、デーモンが自分自身をロックしなくなり、悪用段階に到達したときにペイロードの実行が容易になる
      この2つが無関係だとは思わない。すでにペイロードを念頭に置いていて、これが障害になると気づいていたように見える
    • 変だ。同じプロジェクトで互いに無関係な バックドアのような作業を2つやるのは、本当に雑だと思う。得るものは少ないのに、発覚リスクだけを大きく高めているように見える
      この件は非常に混乱している。信じがたいほど巧妙な部分もあれば、かなり粗く見える部分もある
    • 使えるし良い考えだが、意図的なバックドアというよりは 脆弱性の悪用を防ぐためのものだ
      アイデアとしては、ライブラリが複雑な処理を別スレッドで開始し、ユーザーコードが呼び出した API の中でそのスレッドを待つ、というもの。スレッドは自分で Landlock を適用してから処理を始める。何か問題が起きればコードは隔離される
      もちろんこの場合は、サンドボックスが攻撃者に制御されるので機能しない。攻撃者が単に無効化するか、本来より弱くできるからだ。それでも別の方法で行うことはできる
  • いったいここで何を狙っていたのだろう? 後からさらに多くのバックドア、よりもっともらしく否認できるバックドアを入れようとしていたのか? 私には oss-fuzz もこの変更も、見つかったバックドアを実際に発見することはなかったように思える
    それなのに、なぜバックドアの卵を1つのかご、つまり1つのライブラリに集中させたのだろう?

    • そのライブラリは十分に深く入り込んでおり、十分に信頼されていて、主要開発者はメンタルヘルスの問題でインターネットから長く離れることがあった
      さらに、ライブラリ自体をバックドア化するのではなく、それを使うツールを狙うやり方だ。「Reflections on trusting trust」風だ
      失敗するまでは完璧な計画に聞こえる
    • しかし、それが たった1つのライブラリだけだったと誰が言えるのか?
  • xz で Landlock が有効になるのを妨げることが、なぜ有用だったのか気になる。後の段階で xz アーカイブに悪意ある内容を注入しようとしていたのだろうか? もしそうなら、なぜ xz 自体に悪意ある動作をそのまま入れなかったのか?

    • 意図的な脆弱性は、実際の 悪意ある内容よりはるかに隠しやすいからだ
      メンテナンスしている C プロジェクトにバッファオーバーフローや use-after-free をこっそり入れることは、見つからずにできるかもしれない。実際のトロイの木馬を配布するのははるかに難しく、xz-to-sshd バックドアでそれが露呈した
    • ssh を狙ったもの以外に、xz 自体を標的にしたもっと微妙なバックドアがある可能性もある。明らかに目的は 隠密性だった
  • これは意外なほど目立つ。機能を無効にする手法は賢いし、コミットもかなりもっともらしい。なのに、なぜ単なるスペルミスではなく、明白な 構文エラーを選んだのだろう? たとえばミスが PR_SET_NO_NEW_PRIV だったら気づけただろうか?
    そのほうが否認可能性も高かったはずだ

  • それはさておき、この マルウェアチームは、セキュリティ問題を識別するよう AI を訓練するための素晴らしいデータセットを作ってくれた。すべてのコミットにセキュリティ問題があり、オープンソースコミュニティが1つずつ調べて見つけていくのだから
    整理作業をしているメンテナたちに感謝する。きっと楽しい仕事ではないはずだ

    • うまく一般化できるとは思えない。せいぜい 軍拡競争にすぎない
    • 私が見た AI 活用の中ではかなり格好いい部類だ
    • こういう話は初めて聞いた。関連情報を少し投稿してもらえる?
  • だから、自動で機能を有効/無効にする configure 風のビルドシステムは本当に好きではない。何かが欲しければ明示的に有効にしたい。機能をデフォルトにする十分な理由があるなら、代わりに明示的に無効化できるようにすべきだ

    • パッケージング時にはこれがものすごい苦痛になる。パッケージを設定し、ビルドできるまで依存関係を追加して、終わったと思う。ところが機能 X が抜けている。何だ? ああ、libY がないから黙って無効化されたのか。戻って追加する。すると今度はユーザーが機能 Z がないと報告してくる
      単に標準機能セットを用意し、必要に応じて --enable-a --disable-b を許可すればよい
      チェック処理のバグを黙って飲み込んでしまうというのは、また別の問題だ