2016-01-22 25 views
5

root権限を持つコマンドを実行する必要のあるソフトウェアを作成しています。Macアプリケーションでswiftを使用して管理権限を取得する

今私はパスワードを一度尋ねてパスワードを保存してから、と一緒に引数としてNSAppleScriptにパスワードを入力することでこれをやります。

これは明らかに、誰かが自分のパスワードにアクセスできるようになると、ユーザーにとっては本当に安全ではありません。

私は一週間のうちに良いところを探していて、解決策を見つけることができません。

SMJobBlessより高い特権でアプリケーションをインストールできるようです。

私はアプリの例に従っており、SMJobBlessUtilスクリプトからエラーが発生しています。

SMJobBlessUtil.py: tool designated requirement (identifier "com.domain.AppName.SampleService" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: firstName lastName (XXXXXXXXXX)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */) doesn't match entry in 'SMPrivilegedExecutables' (anchor apple generic and identifier "com.domain.AppName.SampleService" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.CN] = "Mac Developer: firstName lastName (XXXXXXXXXX)") 

は明らかに、何かが間違っている:ここでは

はエラーです。ここでは、それぞれのプレースメントリストは、私はそれのように at this stackoverflow postや他の多くのを見てきました

<?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>CFBundleDevelopmentRegion</key> 
    <string>en</string> 
    <key>CFBundleDisplayName</key> 
    <dict/> 
    <key>CFBundleExecutable</key> 
    <string>$(EXECUTABLE_NAME)</string> 
    <key>CFBundleGetInfoString</key> 
    <dict/> 
    <key>CFBundleIdentifier</key> 
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 
    <key>CFBundleInfoDictionaryVersion</key> 
    <string>6.0</string> 
    <key>CFBundleName</key> 
    <string>Away</string> 
    <key>CFBundlePackageType</key> 
    <string>APPL</string> 
    <key>CFBundleShortVersionString</key> 
    <string>1.0.99</string> 
    <key>CFBundleSignature</key> 
    <string>????</string> 
    <key>CFBundleVersion</key> 
    <string>9</string> 
    <key>LSApplicationCategoryType</key> 
    <string>public.app-category.utilities</string> 
    <key>LSMinimumSystemVersion</key> 
    <string>$(MACOSX_DEPLOYMENT_TARGET)</string> 
    <key>LSUIElement</key> 
    <true/> 
    <key>NSHumanReadableCopyright</key> 
    <string>Copyright © 2016 firstName lastName. All rights reserved.</string> 
    <key>NSMainStoryboardFile</key> 
    <string>Main</string> 
    <key>NSPrincipalClass</key> 
    <string>NSApplication</string> 
    <key>SMPrivilegedExecutables</key> 
    <dict> 
     <key>com.domain.AppName.SampleService</key> 
     <string>anchor apple generic and identifier "com.domain.AppName.SampleService" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.CN] = "Mac Developer: firstName lastName (XXXXXXXXXX)"</string> 
    </dict> 
</dict> 
</plist> 

サービス情報の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>CFBundleIdentifier</key> 
    <string>com.domain.AppName.SampleService</string> 
    <key>CFBundleInfoDictionaryVersion</key> 
    <string>6.0</string> 
    <key>CFBundleName</key> 
    <string>SampleService</string> 
    <key>CFBundleVersion</key> 
    <string>6</string> 
    <key>SMAuthorizedClients</key> 
    <array> 
     <string>anchor apple generic and identifier "com.domain.AppName" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = xxxxxxxxxx)</string> 
    </array> 
</dict> 
</plist> 

アプリ情報plistのです。私が理解しているように、私は自分のplistsを正しくセットアップしました。私は間違って何をしていますか?

答えて

6

このアプローチの重要な部分がのReadMe.txtの「それはしくみ」の下の「プロパティリスト」セクションで説明されています

[…] when you sign the helper tool with a Developer ID, Xcode automatically sets the helper tool's designated requirement like this, and that's what you should use for SMPrivilegedExecutables. Moreover, this is what the "setreq" command shown above does: extracts the designated requirement from the built tool and put it into the app's Info.plist source code.

あなたは、少なくとも(製品ない署名されていませんので、あなたの例で説明されている証明書で)、このプロセスは常に失敗します。

デベロッパープログラムに参加していない場合は、create a self-signed certificateで署名できます。しかし、これは署名要件の目的を多かれ少なかれ打ち破るものである。デベロッパープログラムへの登録を計画していない場合は、次のようにプロセスを省略することができます。

  1. アプリの情報

  2. :ちょうどアプリの識別子に一致するようにSMAuthorizedClients下の要件を、あなたのヘルパーのInfo.plistで

    <string>identifier "com.domain.AppName.SampleService"</string>

    • 省略:plistのは、ちょうどヘルパーの識別子に一致するようにSMPrivilegedExecutables下の要件を省略します<string>identifier "com.domain.AppName"</string>

      • "サンプルのビルドと実行" ins ReadMe.txtの手順を実行し、通常通りにプロジェクトを構築して実行するだけです。

私はもちろん、このことをお勧めしますと言うことはできません。これらの署名要件は正当な理由のために存在する。これはNSAppleScriptがchmodchown介してルートsetuidビットを実行可能ヘルパーを与えることを使用されるであろう、しかし、少なくとも最終の代替よりも優れています。


ここで劇中の概念のいくつかについて詳しく説明する補足:

特権コードを実行すると、潜在的なセキュリティホールの多くが付属しています。安全にユーザーを認証することは、最初のステップに過ぎません。別のプロセスにすべての特権操作を委任することは、別の強力なステップであるが、依然として大きな問題は、あなたのアプリケーションことを確実にする方法である - ユーザーが実際の権限を付与された1は - 特権アクセスを利用することができる唯一のエンティティです。

Appleの例では、この問題を解決するためのコード署名の使用方法を示します。あなたが使い慣れていない場合に備えて:コード署名では、OS Xがあなたのプログラムが妥協したバージョンに置き換えられていないことを検証できるように暗号化して最終製品をマーキングします。これらの余分な「証明書の葉」の参照は元の例のSMAuthorizedClientsSMPrivilegedExecutablesであり、このために特別です。彼らはあなたのアプリとヘルパーが互いに相互作用するために署名されていなければならない証明書を記述します。

が絵を少しペイントしやすくするために、ここではこれが出て再生する方法の大まかな荒廃があります:のlaunchdに

  1. あなたのユーザー補助金の承認がcom.domain.AppName.SampleServiceラベルヘルパーデーモンをインストールします。
  2. launchdのアプリのInfo.plistでSMPrivilegedExecutablescom.domain.AppName.SampleServiceエントリを検索します。これは、ヘルパーのバイナリに署名する必要がある証明書を記述します。 (それらが一致しない場合は、理論的には攻撃者がルートとしてそれを実行するために、独自のバージョンを使用してヘルパーツールを交換しました。)インストールの有効なヘルパーツールを使用すると
  3. は、あなたのアプリケーションは、ヘルパーを起動するためのlaunchdに要求を行いますあなたのコントロール下。この時点で、launchdはヘルパーツールのInfo.plistのSMAuthorizedClientsセクションを参照して、アプリが実際にツールを実行する権利を持っていることを確認します。そして、もちろん、あなたのアプリの署名が改ざんされていないことを確認します。

あなたのシナリオに戻って取得する、あなたの製品は、現在作業している方法は、署名手順を排除することです。 launchdにチェックするよう指示したのは、あなたのアプリのInfo.plistが "com.domain.AppName"というIDをリストしているかどうかだけです。攻撃者がInfo.plistを変更するのを止めることは何もないので、一度自分のコントロールができたら、ヘルパーツールを使って害を冒すことができないという希望を抱いています。代替案を概説

追加補遺:

+0

私は賞金を保持するつもりはありませんでした。 Redditのあなたの投稿の問題は、それが文字列だということです。私は本当に順列をランダムに見つけました。しかし、あなたは答えが十分です。私は元の質問から必要とされる段階的な変更を組み込むために質問を編集することをお勧めします。私は数日間このことに固執していましたが、リンゴはずっと長いストリングを持っていますが、不完全なアイデンティティラインがどれだけ十分であるかはまだ分かりません。 – Cripto

+0

さて、私は愚か者を感じません。繰り返しますが、報酬は必要ではありませんでしたが、非常に感謝しています...私はあなたが求めた詳細と同様に全体的な根拠を説明しようと私の答えを更新しました。それがそれをカバーしなかったならば、躊躇しないでください。 –

0

あなたは正しい方向に移動しています。現在、特権ヘルパーツールは、特権モードでタスクを実行するためのベストプラクティスです。そのためにはSwiftも使えますが、Cバージョンの関数呼び出しをSwiftに置き換えるだけです。たとえば、代わりの

Boolean SMJobBless(CFStringRef domain, CFStringRef executableLabel, AuthorizationRef auth, CFErrorRef *outError); 

あなたが使用することができます(Appleは10.11 SDKの代替導入しています):

SMJobBless(_: CFString!, _: CFString, _: AuthorizationRef, _: UnsafeMutablePointer<Unmanaged<CFError>?>) -> UInt8 

しかし、私はインターネットでの特権ヘルパーツールの例を見たことがないし...だからあなたが見る必要がありますObjective Cコードに変換します。幸いにもObjのCコードはあまりありません。

関連する問題