
Polkit に 12 年前の最初のバージョンから存在した脆弱性「Pwnkit」 35
ストーリー by headless
境界 部門より
境界 部門より
主な Linux ディストリビューションに標準でインストールされるツールキット Polkit (旧名: PolicyKit) の最初のバージョン (12 年前) から存在したメモリ破損の脆弱性 (CVE-2021-4034) について、発見した Qualys が解説している
(Qualys Security Blog の記事、
Red Hat のアドバイザリー、
Neowin の記事、
Ars Technica の記事)。
Qualys が Pwnkit と名付けた脆弱性は非特権ユーザーがrootの権限でコマンドを実行できるようにする Polkit の コマンドラインツール pkexec に存在する。pkexec の main() 関数ではコマンドライン引数の数 (argc) を適切に処理せず、常に 1 以上として扱うため、引数リスト (argv) が空の状態でも境界外のメモリを引数 (argv[1]) として読み書きしてしまう。
境界外の直近にあるのは 1 つ目の環境変数 (envp[0]) であり、pkexec は読み取った値を実行ファイルの名前として PATH 環境変数で指定されたディレクトリを探し、一致する実行ファイルが見つかったらパスを付加して envp[0] を上書きする。これにより、通常は main() 関数実行前に除去される「安全でない」変数を pkexec の環境に再導入することが可能であり、悪用することでローカルでの権限昇格が可能になる。
Polkit では argc が 1 未満の場合に処理を終了する修正を行っており、修正済みの Polkit パッケージが入手可能になり次第更新することが推奨される。
Qualys が Pwnkit と名付けた脆弱性は非特権ユーザーがrootの権限でコマンドを実行できるようにする Polkit の コマンドラインツール pkexec に存在する。pkexec の main() 関数ではコマンドライン引数の数 (argc) を適切に処理せず、常に 1 以上として扱うため、引数リスト (argv) が空の状態でも境界外のメモリを引数 (argv[1]) として読み書きしてしまう。
境界外の直近にあるのは 1 つ目の環境変数 (envp[0]) であり、pkexec は読み取った値を実行ファイルの名前として PATH 環境変数で指定されたディレクトリを探し、一致する実行ファイルが見つかったらパスを付加して envp[0] を上書きする。これにより、通常は main() 関数実行前に除去される「安全でない」変数を pkexec の環境に再導入することが可能であり、悪用することでローカルでの権限昇格が可能になる。
Polkit では argc が 1 未満の場合に処理を終了する修正を行っており、修正済みの Polkit パッケージが入手可能になり次第更新することが推奨される。
悪意や脆弱性を気にしないですむコンピューティングはもう (スコア:0)
未来永劫ありえないのだろうか。
なんか何を作るにもそこらへんが面倒そうでやる気が削がれる。
Re: (スコア:0)
人間に作らせるから悪いのであってAIに作らせてAIに管理させればいい。
# 市民、幸福は義務です
Re: (スコア:0)
AIなら必ず悪意無きものを作ると信用するなんて、お人よしですね。
Re: (スコア:0)
悪意なんぞなくてもロクでもないことをやらかすのは人間もAIも同じ
Re: (スコア:0)
月面の丘陵の掘削のために重力カタパルトで貨物ぶつけて丘陵を丸ごと粉砕なんて方法を編み出してしまうのですね
Re: (スコア:0)
ありえんよ。
開発者のやる気により脆弱性の問題は最小限に留められている。
やる気が無いなら何も作らない選択をする方が社会に貢献できる。
Re: (スコア:0)
脆弱性の問題にかかずらわらなければその分の時間を機能追加とかに宛てられるだろうに惜しいことだ
Re: (スコア:0)
オフラインで使えばよろし
Re: (スコア:0)
電源が?
Re: (スコア:0)
感覚ですが、Linuxは権限上昇のバグが多いような。PolicyKitとかsudoがあること自体がよくないんでしょうね。設計の問題ですかね。
Re: (スコア:0)
SELinuxが悪いと思っている。
Re: (スコア:0)
機能別に細かくカーネルapi 使用許諾を設定出来るつかさせるopenbsd さんならプロセス毎仮想化よりも部分的には強固ですよ
socket をガンガン塞いじゃったりされると広告で食ってるGoogle なんぞはたまったもんじゃないんで
けっして主流な方法にはならないだろうけど
Linuxはposix準拠ではない (スコア:0)
argv[0]にファイル名が入っていることはposixで明言されているが、Linuxでは慣習扱い。
linux man pageのexecve(2),exec(3)でもそう書いてある。
Linuxをposix準拠だと思い込み、しっかりlinux man pageを読まなかったのが悪い。
Re:Linuxはposix準拠ではない (スコア:1)
この件はargv[1]の内容を無条件に読んでしまう脆弱性で、argv[0]に何が入っているかは関係ないのだが
Re: (スコア:0)
そうすると、ストーリーの「常に 1 以上として扱うため、引数リスト (argv) が空の状態でも」は間違い、ってことだな。「常に 1 より大きいとして扱うため、」と書くべきか。
Re: (スコア:0)
でもリンク先の修正をみると、argc1の場合に対処してるよ。
Re: (スコア:0)
「常に 1 以上として扱うため、引数リスト (argv) が空の状態でも」は正しい。
argc==0でもargv[1]を読んでしまう。execve()を使うと可能だそうだ。
Re: (スコア:0)
argvの配列はNULLで終端されている(argv[argc]はNULLになる)ので、たとえ引数の個数(argc)がゼロ個でもargv[0]は常に有効(もちろん*argv[0]が有効とは限らないが)。だから「argv[1]の内容を無条件に読んでしまう」も「(argcを)常に 1 以上として扱うため」も正しい。
Re: (スコア:0)
つまり#4192327は
「posix準拠ならargv[0]に必ずファイル名がセットされるのでargcが0になることはありえない、Linuxだとargcが0でargv[0]に終端NULLがセットされるケースがあるためにこのようなことが起きる」
と言いたかったわけか
Re: (スコア:0)
argvを頭から呼び出して引数が何個入ってるか調べるとどうせ1万回に一回くらいヘマをやらかすので素直にargcを見たほうがいいと思う。
これなら引数の数を取り違えたせいでメモリを書き換えたり変なところを読んだりする不具合を生む確率が多分1万1千回に一回くらいにへる。
Re: (スコア:0)
配列とその要素数を別々に管理しなければならない言語を捨てたほうがいいと思う。よく反論で持ち出される組み込み(フリースタンディング環境)ではmainの存在すら保証されていないからここの議論のスコープ外だし。
Re: (スコア:0)
arg[0]に必ずファイル名が入るのか、それとも終端NULLが入っているかもしれないかは、この脆弱性に関係大有りだろ。
Re: (スコア:0)
この(Polkitの)脆弱性は、argv[1]は常に値が(最悪でも終端NULLが)入っていると仮定してアクセスしてしまったというものなので。もっと一般的な話として*argv[0]にアクセスしてしまったという脆弱性なら関係あるけど。
Re: (スコア:0)
もう少し正確に言うと、書き変えても大丈夫だと思っていた、ですな。
argv[n] を書きかえるというトリックを使ってるのは、pkexec のコードがダサい
argc=0 で呼び出されると argv[1] には environ が入ってるというのは *nix がダサい
argv** が const* const* じゃないのは main() の仕様がダサい
argv[n] で範囲外アクセス出来るのは C がダサい
世の中ダサいものばかりですね
Re: (スコア:0)
2番めは4番目の未定義動作の結果としてたまたま生じたことなので*nixのせいにするのは少々酷ではありませんかね
Re: (スコア:0)
やはりC言語は滅ばなければならないですな。
いつもの流れ。
Re: (スコア:0)
argc=0はLinux環境でしか起こらないんだから、*unix全般に広げている2番目はそもそも見当違い。
Re: (スコア:0)
C99では起きます。C89は調べていない。
Re: (スコア:0)
範囲外アクセスを許すOSに根本的な問題があるのではないでしょうか
Re: (スコア:0)
読んでいるのはあくまでargv[1]だから、argv[0]に何が入っていようが直接には関係ない。
現実にはそんな実装はまずありえないけど、argv[0]が終端NULLでもargv[1]にもNULLがセットされていれば大丈夫だったわけだから。
Re: (スコア:0)
POSIX.1-2017から削除されたって書いてあるぞ。どれくらあてになる文章かわからんけど。
https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html [opengroup.org]
まあだから、それまではargc>=1だったってことだし、argc==0みたいなことをするのは
やめようよって長々と書いてあるけど。こういう問題がおきそうだって予想してたようだね。
Re: (スコア:0)
argv、argcだからとか特別視せずに配列とその要素数が与えられてるのだから基本に忠実にできるのならそうした方が良い。
mainは呼び出し頻度的にパフォーマンスに影響しにくいし、mainをある種の外部とのインターフェースとして見て、呼び出し側をあまり信用しないという考え方に立って、(パラメータの仕様がどうあれ)型の仕様として取りうる値の範囲でちゃんとチェックすべきだと思う。
pkexec.c見たけど、輸送機械、産業機械系なんかの組込みやってる人なら割と目視で見つけられる気がする。
サポート切れ機器がさらに危なっかしくなる? (スコア:0)
12年前だと古いssh鯖とかルータとかも影響ありそうですな
Re: (スコア:0)
任意コード実行と組み合わせられると凶悪ですね