2015-11-06 6 views
21

TL; DRWindowsIdentityTokenプロパティに含まれるユーザトークンを(たとえば、someIdentity.Token)ように偽装することができ:このWindowsIdentityコードを間違ったユーザーに騙すことは可能ですか?

var validated = new WindowsIdentity(someIdentity.Token); 

は...そのユーザを表すと主張インスタンスが返され実際には認証されていませんが、IsAuthenticatedtrue、有効な.Name.Userなどと設定されていますか?

以下、私はこれにいくつかの境界を置いています。 完全になりすましを防ぐことはおそらく不可能です。


全文:this answer

Damien_The_Unbelieverは巧みに私のいくつかのコードは、それがなかったとき、それはWindowsIdentityインスタンス内の有効な認証済みのユーザーを持っていたと信じるようにだまさすることができることを実証しました。

WindowsIdentity identity = Thread.CurrentPrincipal == null 
    ? null 
    : Thread.CurrentPrincipal.Identity as WindowsIdentity; 

if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) { 
    // ...use and trust the SID in identity.User, the 
    // username in identity.Name, etc.... 
} 

(理由このコードあります:かいつまんでは、私のコードは、それが認証されたユーザを代表して、私は.UserでSIDに頼ることができると、Thread.CurrentPrincipal.Identity場合WindowsIdentityのインスタンスだったとIsAuthorizedtrueだったと仮定しました。スレッドではなく、WindowsIdentity.GetCurrent()を使用している)

ていることにだますために彼のコードは(わずかに修正):。

var ident = WindowsIdentity.GetCurrent(); 
Thread.CurrentPrincipal = new WindowsPrincipal(ident); 
var fakeSid = new SecurityIdentifier("S-1-3-0"/* E.g., some SID you want to trick me into believing is the real user */); 
typeof(WindowsIdentity).GetField("m_user", BindingFlags.Instance | BindingFlags.NonPublic) 
    .SetValue(ident, fakeSid); 

かつ確実ENOあなたがそれをして上のコードを呼び出すと、コードがだまされてしまいます。 Kudos Damien。

だから真の軍拡競争方式で、ここでなりすましをキャッチし、それを拒否した私の改訂コードです:あなたが見ることができるように

WindowsIdentity identity = Thread.CurrentPrincipal == null 
    ? null 
    : Thread.CurrentPrincipal.Identity as WindowsIdentity; 

if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) { 
    var validated = new WindowsIdentity(identity.Token); 
    if (!validated.User.Equals(identity.User) || !validated.IsAuthenticated || validated.IsAnonymous) { 
     // Something fishy is going on, don't trust it 
    } else { 
     // Good! Use the validated one 
     identity = validated; 
     // ...use and trust the SID in identity.User, the 
     // username in identity.Name, etc.... 
    } 
} 

、それが提供するアイデンティティからTokenを取り、新しいWindowsIdentityを作成し、そのトークンを使用するインスタンスIDのSIDが一致する場合、検証されたIDを信頼し続けます。 (documentation for WindowsIdentity(IntPtr token)IsAuthenticatedの初期値はfalseになることを言いますが、それは私が有効なユーザートークンを使用して、それを作成したと仮定すると、私のテストでは、単に間違っている。)

私は考えだまさすることができることを見ることができる唯一の方法は、それにもかかわらず、それがWindowsが行う妥当性検査に合格している偽のユーザートークンである必要があります。それは私にはあり得ないようです。しかし、これは私の無知の領域です。


境界

私はちょうど私の原因dilienceをやって、シングルサインオンのセキュリティここでの合理度の撮影だということに注意してください。悪意のあるアプリがシステムコール/侵害されたWindows自体を傍受することに成功した場合、私はそれについて多くのことを行うことはできません。ダミアンは他の質問に対するコメントで指摘したように、おそらく強力な命名法を完全に無視したホストコンテナを構築することができます(したがって、完全に偽のWindowsIdentityタイプを与えることができます)。けっこうだ。完璧な殺し。私はちょうどダミアンが優しく実証したようにドアを開けたままにしたくない。私がシステムをリリースし、それが現場で簡単にハッキングされたならば、私はそれを恥ずかしく思うでしょう。 :-)

+4

私の能力をはるかに超えていますが、大きな問題です!与えられた答えを見ることに興奮しています:) – levelonehuman

+0

@levelonehuman私の考えはまさに! –

+2

"Skeetは今私を失敗させない!" ;-) –

答えて

6

これは実用的であることを実証するために、「Microsoft Fakes」という名前のクールなVisual Studioアドオンを使用してください(名前自体は多くのことを意味します...)。

Fake自体はVisual Studioのテスト機能に縛られていますが、それがポイントになります。標準的なチュートリアルに従ってプロジェクトをセットアップし、システム用の偽アセンブリを追加することができます(実際はmscorlib +システム)

これはライブラリプロジェクトのコードです。 ...)。

namespace ClassLibrary1 
{ 
    public class Class1 
    { 
     public static void MyCheck() 
     { 
      WindowsIdentity identity = Thread.CurrentPrincipal == null 
       ? null 
       : Thread.CurrentPrincipal.Identity as WindowsIdentity; 

      if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) 
      { 
       var validated = new WindowsIdentity(identity.Token); 
       if (!validated.User.Equals(identity.User) || !validated.IsAuthenticated || validated.IsAnonymous) 
        throw new Exception("Something fishy is going on, don't trust it"); 
       else 
        throw new Exception("Good! Use the validated one. name is:" + validated.Name); 
      } 
      else 
       throw new Exception("not in"); 
     } 
    } 
} 

これは、テストプロジェクトにおけるテストコードです:

namespace UnitTestProject1 
{ 
    [TestClass] 
    public class UnitTest1 
    { 
     [TestMethod] 
     public void TestMethod1() 
     { 
      using (ShimsContext.Create()) 
      { 
       System.Security.Principal.Fakes.ShimWindowsIdentity.AllInstances.NameGet = (i) => 
       { 
        return "Simon the hacker"; 
       }; 

       WindowsIdentity wi = WindowsIdentity.GetCurrent(); // this is the real one "Simon". 
       Thread.CurrentPrincipal = new WindowsPrincipal(wi); 

       Class1.MyCheck(); 
      } 
     } 
    } 
} 

これは、Visual Studioのプロジェクトのレイアウトです:

enter image description here

はまた、あなたがmscorlibを変更することを確認してください。このように自動的に生成された偽のファイル:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/" Diagnostic="true" TargetFrameworkVersion="v4.6"> 
    <Assembly Name="mscorlib" /> 
    <ShimGeneration> 
    <Clear /> 
    <Add Namespace="System.Security.Principal" /> 
    </ShimGeneration> 
</Fakes> 

これは、System.Security.Principal名前空間全体をシームレスにすることを意味し、両方のプロジェクトにフレームワーク4.6を使用し、対応するTargetFrameworkVersion属性を追加することをお勧めします。

さて、あなたはテストを実行したときに、これはあなたが表示されますものです:

enter image description here

[OK]を、あなたの特定のシナリオでは、私は偽物を使用することはできないかもしれませんが、基本的な技術、それすべてのAPIを再ルーティングすることに頼っています(.NETよりも低いですが、それはDetoursと呼ばれています)。これらのハッカーをすべて信じています。

要約すると、私のマシン上で実行されている場合、私はマシンに物理的にアクセスできない限り、それをハックすることができます。

+0

ありがとうございます。 Damien氏は他の質問に対するコメントで指摘したように、強力な命名法を完全に無視したホストコンテナを構築する可能性がある(したがって、WindowsIdentityタイプを完全に偽装する可能性がある)。 *しかし、(それほど驚くべきことではないが)それは簡単なことである。Damienのコメントに基づいて、管理されていないWindows呼び出しを使用してトークンを認証するかもしれないと思っていましたが、問題をレイヤーに戻すだけです。呼び出しプロセスはそれらも傍受する可能性があります。または、私のアセンブリのバイトコードを編集してチェックをバイパスしてください。 –

+1

ああ、ありがとう、私はバグを修正しました - :) –

+0

それは私のマシン上で実行されている場合、*私はそれをハックすることができます*、あなたの非常に豊富な経験豊富な専門家の意見では、問題のシステムは「正常」ですが、一部のユーザーが実際には情報を見ることができないユーザーが混在している状況で実行されます。私たちはここで分類された物質を話しているわけではありません(もちろん、機密扱いの機械とネットワーク上にあったとしても)。私が与えられたアイデンティティを利用してください。質問に私の小規模なチェックをしますか?アンマネージコード?それはだますことができる、私はちょうどラインを見つけることを試みている:...-) –

関連する問題