Javaでの動的コード評価-賢いのか、ずさんなのか?


30

アプリケーション用にJavaで柔軟なACLフレームワークを作成しようとしています。

多くのACLフレームワークはルールのホワイトリストに基づいて構築されています。ルールはowner:action:resourceの形式です。例えば、

  • 「ジョンはリソースFOOBAR-1を表示できます」
  • 「MARYはリソースFOOBAR-1を表示できます」
  • 「MARYはリソースFOOBAR-1を編集できます」

これは、ルールをデータベースに簡単にシリアル化/永続化できるため魅力的です。しかし、私のアプリケーションには複雑なビジネスロジックがあります。例えば、

  • 「5年以上の年功歴を持つ部門1のすべてのユーザーは、リソースFOOBAR-1を表示できます。それ以外の場合は承認されません」
  • 「部門2のすべてのユーザーは、日付が2016年3月15日以降であれば、リソースFOOBAR-2を表示できます。それ以外の場合は許可されません」

最初に考えたとき、このような無限に複雑なルールを処理できるデータベーススキーマを考案するのは悪夢です。したがって、コンパイルされたアプリケーションにそれらを「焼き付け」、ユーザーごとに評価し、評価の結果としてowner:action:resourceルールを生成する必要があるように思えます。 コンパイルされたアプリケーションにロジックを焼き付けないようにします。

そのため、私はルールを述語:action:resourceの形式で表現することを考えていました。ここで、述語はユーザーが許可されるかどうかを決定するブール式です。述語は、JavaのRhinoエンジンで評価できるJavaScript式の文字列になります。例えば、

  • return user.getDept() == 1 && user.seniority > 5;

そうすることで、述部をデータベースに簡単に永続化できます。

これは賢いですか?これはずさんですか?これはギミックですか?これは過剰に設計されていますか?これは安全ですか(明らかに、JavaはRhinoエンジンをサンドボックス化できます)。


8
コンパイルされたアプリケーションにロジックを配置するよりも、これらのビジネスルールをデータベースにプッシュしようとすることの利点は何ですか?
ウィンストンイーバート

6
@WinstonEWertルールを外部化すると、ルールが変更、追加、または削除された場合にアプリケーションを再コンパイルおよび再配布する必要がなくなります。
-Twittopher


2
興味深い質問です!セキュリティにそれほど重点を置くのではなく、そのようなソリューションの保守、信頼性、使いやすさの側面に焦点を当てた答えを見つけたいと思います。
オリバー

6
これは、基本的にはユーザーが構成可能なルールエンジンであるOutlook電子メールルールに似ています

回答:


37

動的言語を実装言語のインタープリターにパイピングすることは、データ破損の可能性を悪意のあるアプリケーションの乗っ取りの可能性に拡大するため、通常は悪い考えです。言い換えれば、あなたがするあなたの方法で外出している作成するコードインジェクションの脆弱性を。

問題は、ルールエンジンまたはドメイン固有言語(DSL)によってよりよく解決できます。これらの概念を調べて、車輪を再発明する必要はありません。


16
しかし、ここではJavaScriptをDSLのようなスクリッピング言語として使用しませんか?必要なデータを設定し(読み取り専用)、スニペットを関数でラップし、安全に評価します。コードはブール値を返すこと以外は何もできないため、ここでは悪意のある機会はありません。
アモン

6
@Twittopher JavaScriptエンジン全体をドラッグしていくつかの述語を評価することは、1)完全にやり過ぎ、2)危険、3)エラーが発生しやすいようです。適切な場合、例=====はなく使用しました。すべてのルールがほぼ間違いなく終了する必要がある場合、チューリングの完全性を本当に提供しますか?JavaとJavaScript間のすべての相互作用がコーシャーであることを確認するためにフープをジャンプする代わりに、Kilianが提案したような単純なパーサーとインタープリターを作成してみませんか?ニーズに合わせて安全に調整するのがはるかに簡単になります。ANTLRまたは何かを使用します。
ドーバル

6
@Doval小さなDSLを書くことは正確な​​ロケット科学ではなく、3時間から5日間で簡単な言語を作成できました。しかし、これは1)完全な過剰、2)危険、3)エラーが発生しやすいようです。本当にミニ言語全体を書きたいですか?一部のビジネスルールが予想よりも複雑で、フル機能の言語が必要な場合はどうなりますか?ここで発明されていない症候群に苦しんでいますか?車輪を再発明する代わりに、既存の言語を使用してみませんか?すでに戦闘テスト済みの言語を使用する方がはるかに簡単です。
アモン

14
@amonそれが起こると、Killianが言ったように、実際のルールエンジン(JavaScriptではありません)が見つかります。両方のアプローチのリスクを同等にすることは誤解を招きます。チューリング完全言語のために通訳者を保護するあなたのすべての努力を破壊するために、たった一つの漏れが必要です。それは減法的なプロセスです。小さなDSLを誤って危険なものにするのははるかに困難です。それは付加的なプロセスです。間違いを犯す可能性が高いのは、構文ツリーを誤って解釈することであり、ユニットテストを行うことができます。通訳者にハードドライブのフォーマットを誤って与えることはおそらくないでしょう。
ドーバル

4
@amon:JSは副作用を持っていないかもしれないスニペットとしても、それがすることを選択することができませんブール値を返しますwhile (true) ;
Bergi

44

私はこれを行いましたが、しないことをお勧めします。

私がやったのは、すべてのビジネスロジックをLuaで記述し、そのLuaスクリプトをデータベースに保存することでした。アプリケーションが起動すると、スクリプトが読み込まれて実行されます。そうすれば、新しいバイナリを配布せずにアプリケーションのビジネスロジックを更新できます。

変更を加えるときは常にバイナリを更新する必要があることを常に見つけました。Luaスクリプトにはいくつかの変更がありましたが、必ず変更のリストが必要だったため、ほとんど常にバイナリの変更とLuaスクリプトの変更が必要になりました。常にバイナリを配布することを避けることができるという私の想像は、単にうまくいきませんでした。

はるかに役立つとわかったのは、バイナリの配布を容易にすることでした。私のアプリケーションは、起動時にアップデートを自動的にチェックし、アップデートをダウンロードしてインストールします。したがって、ユーザーは常にプッシュした最新のバイナリを使用しています。バイナリの変更とスクリプトの変更にほとんど違いはありません。もう一度やったら、アップデートをシームレスにするためにさらに努力しました。


3

データベースにコードが含まれていません。ただし、データベースに関数名を含め、リフレクションを使用してそれらを呼び出すことで、同様のことができます。新しい条件を追加するときは、コードとデータベースに追加する必要がありますが、それらに渡される条件とパラメーターを組み合わせて、非常に複雑な評価を作成できます。

言い換えれば、部門に番号を付けている場合、UserDepartmentIsチェックとTodayIsAfterチェックを簡単に作成し、それらを組み合わせてDepartment = 2およびToday> 03/15/2016にすることができます。許可の日付を終了できるようにTodayIsBeforeチェックが必要な場合は、TodayIsBefore関数を作成する必要があります。

ユーザーのアクセス許可についてはこれを行っていませんが、データ検証については行っていますが、動作するはずです。


2

XACMLは、本当に探しているソリューションです。これは、アクセス制御のみに焦点を合わせたルールエンジンの一種です。OASISによって定義された標準であるXACMLは、3つの部分を定義しています。

  • 建築
  • ポリシー言語(実際に必要なもの)
  • 要求/応答スキーム(承認決定の依頼方法)。

アーキテクチャは次のとおりです。

  • ポリシー決定ポイント(PDP)は、アーキテクチャの中核部分です。既知の一連のポリシーに対して着信許可要求を評価するコンポーネントです
  • Policy Enforcement Point(PEP)は、アプリケーション/ API /サービスを保護するコードです。PEPはビジネスリクエストをインターセプトし、XACML承認リクエストを作成し、PDPに送信し、応答を受信し、応答内で決定を実施します。
  • ポリシー情報ポイント(PIP)は、PDPを外部のデータソース(LDAP、データベース、Webサービスなど)に接続できるコンポーネントです。PEPは、「アリスはドキュメント#12を表示できますか?」などの要求をPEPが送信するときに役立ちます。PDPには、ユーザーの年齢を要求するポリシーがあります。PDPはPIPに「アリスの年齢を教えて」と尋ね、ポリシーを処理できるようになります。
  • ポリシー管理ポイント(PAP)は、XACMLソリューション全体を管理する場所です(属性の定義、ポリシーの作成、PDPの構成)。

拡張可能なアクセス制御マークアップ言語-XACMLアーキテクチャ

最初の使用例は次のとおりです。

/*
 * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
 * 
 */
 policy departmentOne{
    target clause department == 1
    apply firstApplicable
    /**
     * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
     */
    rule allowFooBar1{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }

 }

2番目のユースケースは次のとおりです。

 /*
  * "All users in department 2, if the date is after 03/15/2016, can VIEW resource FOOBAR-2, else not authorized"
  *  
  */
  policy departmentTwo{
    target clause department == 1
    apply firstApplicable
    rule allowFooBar2{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and currentDate>"2016/03/15":date and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }
  }

参照を使用して、両方のユースケースを単一のポリシーに結合できます。

  policyset global{
    apply firstApplicable
    departmentOne
    departmentTwo
  }

これで完了です!

XACMLおよびALFAの詳細については、次を参照してください。


0

ここで本当に必要なのはXACMLです。それはあなたが望むものをまさにあなたに与えます。必ずしもすべての役割を完全に分離した完全なアーキテクチャを実装する必要はありません...アプリケーションが1つだけの場合は、おそらくバラナを使用してPDPとPEPをアプリに統合することで逃げることができ、PIPは何でもかまいません既存のユーザーデータベースです。

これで、アプリのどこかで何かを承認する必要がある場合、ユーザー、アクション、およびコンテキストを含むXACMLリクエストを作成し、XACMLエンジンは、作成したXACMLポリシーファイルに基づいて決定を下します。これらのポリシーファイルは、データベースまたはファイルシステム、または構成を保持したい場所に保存できます。Axiomaticsには、生のXMLよりも読みやすいALFAと呼ばれるXACML XML表現の優れた代替手段と、ALFAポリシーからXACML XMLを生成するEclipseプラグインがあります。


1
これは質問にどう答えますか?
-gnat

彼は具体的には、外部で構成された承認システムを実装しようとしています。XACMLは、彼の特定のユースケースを非常にうまくカバーする、外部に設定可能な承認システムです。動的コード実行のより一般的な質問に対する素晴らしい答えではないかもしれませんが、彼の特定の質問に対する良い解決策です。
グレシモン

0

現在の会社でこれを行いましたが、結果に非常に満足しています。

式はjsで記述されており、ユーザーがElasticSearchのクエリから取得できる結果を制限するためにも使用されます。

トリックは、決定を下すのに十分な情報を利用できるようにすることです。そのため、コードを変更せずに、必要なパーマを実際に記述しながら、同時に高速に保つことができます。

権限はシステムを攻撃する必要のない人によって作成されるため、コードインジェクション攻撃についてはあまり心配していません。そして、while(true)例のようなDOS攻撃にも同じことが当てはまります。システムの管理者はそれをする必要がありません、彼らはちょうどみんなの許可を削除することができます...

更新:

XACMLのようなものは、組織の中央認証管理ポイントとして優れているようです。私たちのユースケースは、クライアントが通常、すべてを実行するIT部門を持たないという点でわずかに異なります。自己完結型のものが必要でしたが、可能な限りの柔軟性を維持しようとしました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.