OS X YosemiteのDYLD_PRINT_TO_FILEの権限昇格を抑える「SUIDGuard」の正しい(?)仕込み方

2015/8/13追記 本脆弱性(CVE-2015-3760)は、OS X 10.10.5で修正されています。 https://support.apple.com/ja-jp/HT205031

2015/7/26追記 SektionEinsのStefan Esserさんから、SUIDGuardを起動時に自動読み込みできるようpkg化したSUIDGuardNGが公開されました。
https://github.com/sektioneins/SUIDGuard/releases/download/1.0.0d1/SUIDGuardNG.pkg

https://twitter.com/i0n1c/status/624501679237517312:twitter:detail:left

当該pkgを管理者権限を利用可能なユーザでインストールし再起動すると、下記の通りOS X起動時にSUIDGuardNGがロードされます。
脆弱性が存在するSUIDGuardによる対策を行っていなかった10.10.4にて検証)
利用は自己責任で。


bash-3.2# kextstat | grep SUID
58 0 0xffffff7f80a3e000 0x3000 0x3000 com.sektioneins.driver.SUIDGuardNG (1) <7 4 3 2 1>
bash-3.2# dmesg | grep SUID
Security policy loaded: SUID Guard Kernel Extension (suidguard)

SUIDGuardNG.pkgでインストールされるのはこんな感じ。


$ pkgutil --pkgs=.*SUIDGuardNG.*
com.sektioneins.driver.SUIDGuardNG

$ pkgutil --files com.sektioneins.driver.SUIDGuardNG
Library
Library/Extensions
Library/Extensions/SUIDGuardNG.kext
Library/Extensions/SUIDGuardNG.kext/Contents
Library/Extensions/SUIDGuardNG.kext/Contents/Info.plist
Library/Extensions/SUIDGuardNG.kext/Contents/MacOS
Library/Extensions/SUIDGuardNG.kext/Contents/MacOS/SUIDGuardNG
Library/Extensions/SUIDGuardNG.kext/Contents/_CodeSignature
Library/Extensions/SUIDGuardNG.kext/Contents/_CodeSignature/CodeResources

注意▪️twitter等でワンライナーで広まっているDYLD_PRINT_TO_FILE脆弱性を試してrootを取得した場合、/etc/sudoersが書き換えられます。
/etc/sudoersを元に戻すのはSUIDGuard/SUIDGuardNGの役目ではありませんので、必ず/etc/sudoersの内容が元に戻っているかどうか確認してください。

https://twitter.com/i0n1c/status/624644608526577664:twitter:detail:left
https://twitter.com/i0n1c/status/624653431526019072:twitter:detail:left


※追記ここまで-------------------------------

騒がれているOS X Yosemiteにて一般ユーザがroot権限を奪取できる脆弱性について、ちょっと気になったのでメモ。

当該脆弱性は、7/7にドイツのSektionEins GmbHが、下記で公開したものである。
OS X 10.10 DYLD_PRINT_TO_FILE Local Privilege Escalation Vulnerability
https://www.sektioneins.de/en/blog/15-07-07-dyld_print_to_file_lpe.html

日本では、下記あたりから認識が広まったようだ。
https://twitter.com/applechinfo/status/623996009824190464:twitter:detail:left

合わせて、当該脆弱性に対処するためのSUIDGuard がSektionEins GmbHより先日公開された。
https://github.com/sektioneins/SUIDGuard

これを受けて、@applechinfo さんが
https://twitter.com/applechinfo/status/624071261950357504:twitter:detail:left
で実際にSUIDGuardを試されている。

が、
「 "SUIDGurd.kext"は約300行もないCコードでSektionEinsの署名付き、使い方は"/System/Library/Extensions"へコピーするだけで、管理者権限での認証が必要ですが、認識されればSUID/SGID rootバイナリが環境変数” DYLD_*”から保護されるようになっています。」
と書かれているが、若干説明が不足しているように思う。

まず、10.10以降はkextへの署名が必須になった。このため、署名のないkextをロードすることが標準ではできないので、SektionEinsが署名したうえで公開してくれているのはとても意味がある。
kextへの署名は、通常のアプリへの署名とは異なり、Appleに個別に権限リクエストが必要であり、Appleが許可をして初めてCertificationCenterからkext用署名のリクエストができるようになる、というめんどくさい流れになっている。
(参考:http://qiita.com/gamako/items/9980a08a24916f9f98b2

このため、SektionEinsがgithubで公開してくれているソースコードを、自らXcodeでBuildしても、Yosemiteではロードに失敗する。
よって、下記にあるSektionEinsが署名済のSUIDGuard.kextを使用する必要がある。
https://github.com/sektioneins/SUIDGuard/releases


そして、上記applechinfoさんの検証記事に記載されているスクリーンショットでは、確かにSUIDGuardは確認済の開発元として署名されていることは確認できるものの、SUIDGuardは「読み込み済:いいえ」「読み込み可能:いいえ」となってしまっている。

大学など、不特定多数の人間が一般ユーザで利用する環境において、当該脆弱性を回避するならば、SUIDGuardを起動時にロードさせる必要があるので、手順を簡単に書くと下記の通りとなる。

※root権限を使用できるユーザで作業する
※SUIDGuard.kext.tar.bz2 をダウンロードしておく

$ sudo -s
Password:
#
# chown root:wheel SUIDGuard.kext.tar.bz2
# tar -xvzf SUIDGuard.kext.tar.bz2
x SUIDGuard.kext/
x SUIDGuard.kext/Contents/
x SUIDGuard.kext/Contents/_CodeSignature/
x SUIDGuard.kext/Contents/Info.plist
x SUIDGuard.kext/Contents/MacOS/
x SUIDGuard.kext/Contents/MacOS/SUIDGuard
x SUIDGuard.kext/Contents/_CodeSignature/CodeResources
# mv SUIDGuard.kext /System/Library/Extensions
# kextutil -b com.sektioneins.SUIDGuard
# cd /Library/LaunchDaemons
# vi jp.ac.example.SUIDGuard.plist

jp.ac.example.SUIDGuard.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>KeepAlive</key>
        <false/>
        <key>Label</key>
        <string>jp.ac.example.SUIDGuard</string>
        <key>ProgramArguments</key>
        <array>
                <string>/sbin/kextload</string>
                <string>/System/Library/Extensions/SUIDGuard.kext</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StandardErrorPath</key>
        <string>/dev/null</string>
        <key>StandardOutPath</key>
        <string>/dev/null</string>
        <key>UserName</key>
        <string>root</string>
</dict>
</plist>

続き 

# plutil -lint jp.ac.example.SUIDGuard.plist
jp.ac.example.SUIDGuard.plist: OK

# launchctl load -w jp.ac.example.SUIDGuard.plist            

# launchctl list | grep SUID   
-       0       jp.ac.example.SUIDGuard
     
# kextstat | grep SUID
  131    0 0xffffff7f82a38000 0x2000     0x2000     com.sektioneins.SUIDGuard (1) <7 4 2 1>

# dmesg | grep SUID
Security policy loaded: SUID Guard Kernel Extension (suidguard)

再起動し、起動時に正常にSUIDGuardが読み込まれているか確認する。

参考:http://www.heise.de/forum/heise-Security/News-Kommentare/Einzeiler-beschert-Adminrechte-unter-Mac-OS-X-10-10/Re-Mein-Workarround/posting-21028401/show/