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)