web-dev-qa-db-ja.com

ASP.NETはNTAUTHORITY \ IUSRを偽装しますが、偽装は無効になっています。 ASP.NETのバグ?

Windows7でASP.NET4.0アプリケーションを実行しています/ IIS 7.5「ASP.NETv4.0Classic」アプリケーションプールで、ネットワークサービスとして実行するように構成されています。アプリケーションにはローカルSQLServerインスタンスに接続するApplication_EndRequestハンドラー。SQL接続文字列はIntegrated Security=SSPIを指定します。Web.configはnothas <identity impersonate="true" />を持っています。

http://localhost/TestSite/を参照すると、次の例外がスローされます。

System.Data.SqlClient.SqlException (0x80131904): Login failed for user 'NT AUTHORITY\IUSR'.
   ...
   at System.Data.SqlClient.SqlConnection.Open()
   at Global.Application_EndRequest(Object sender, EventArgs e)

この例外は、http://localhost/TestSite/default.aspx(IISで構成されているデフォルトのドキュメント)またはその他の.aspxページを参照したときにnotスローされます。このような場合、アプリケーションは「NT AUTHORITY\NETWORKSERVICE」としてSQLServerに正しく接続します。これは、有効なログインです。

偽装が無効になっているのに、ASP.NETがEndRequestで「NTAUTHORITY\IUSR」を偽装するのはなぜですか?これはASP.NETのバグですか?

次のGlobal.asax.csファイルは、問題を示しています。

public class Global : HttpApplication
{
    public Global()
    {
        this.BeginRequest += delegate { Log("BeginRequest"); };
        this.PreRequestHandlerExecute += delegate { Log("PreRequestHandlerExecute"); };
        this.PostRequestHandlerExecute += delegate { Log("PostRequestHandlerExecute"); };
        this.EndRequest += delegate { Log("EndRequest"); };
    }

    protected void Application_EndRequest(Object sender, EventArgs e)
    {
        try
        {
            using (SqlConnection connection = new SqlConnection("Server=.;Integrated Security=SSPI"))
            {
                connection.Open();
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine(ex);
        }
    }

    private static void Log(string eventName)
    {
        HttpContext context = HttpContext.Current;
        Type impersonationContextType = typeof(HttpContext).Assembly.GetType("System.Web.ImpersonationContext", true);
        Trace.WriteLine(string.Format("ThreadId={0} {1} {2} Impersonating={3}",
            Thread.CurrentThread.ManagedThreadId,
            context.Request.Url,
            eventName,
            impersonationContextType.InvokeMember("CurrentThreadTokenExists", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetProperty, null, context, null)));
    }
}

トレース出力は次のとおりです。

ThreadId=3 http://localhost/TestSite/ BeginRequest Impersonating=False
ThreadId=3 http://localhost/TestSite/ PreRequestHandlerExecute Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx BeginRequest Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx PreRequestHandlerExecute Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx PostRequestHandlerExecute Impersonating=False
ThreadId=7 http://localhost/TestSite/default.aspx EndRequest Impersonating=False
ThreadId=7 http://localhost/TestSite/ PostRequestHandlerExecute Impersonating=True
ThreadId=7 http://localhost/TestSite/ EndRequest Impersonating=True
System.Data.SqlClient.SqlException (0x80131904): Login failed for user 'NT AUTHORITY\IUSR'.
   ...
   at System.Data.SqlClient.SqlConnection.Open()
   at Global.Application_EndRequest(Object sender, EventArgs e)

TestSite/DefaultHttpHandlerにマップされている)へのリクエストは、nestedリクエストをTestSite/default.aspx(マップされている)に生成するように見えることに注意してくださいASP.default_aspxへ)。 ASP.NETはTestSite/default.aspxの処理を終了した後、TestSite/への要求の処理を再開すると、「NT AUTHORITY\IUSR」になりすます。

UPDATE:この問題を Microsoft Connect に送信しました。

13
Michael Liu

ほとんどの場合、サーバー、サイト、またはアプリケーションの設定は、「匿名認証」モードでページ要求がIUSRユーザーとして処理されるように設定されています。アプリケーションがなりすましを要求していないことは問題ではありません。 IISはそれを強制しています。(ちなみに、「偽装」は、Windowsランドでは、別のユーザーの資格情報を想定するための一般的な用語です。ASP.NETに固有のものではありません。)

少し背景:

セキュリティ上の理由から、IISを使用すると、サーバーは異なるシステム資格情報で「匿名」および「認証済み」の要求を処理できます。

現在、IIS 7.5では、匿名認証とフォーム認証の両方が有効になっている場合(これは一般的です)、Webサイトユーザーがフォーム経由でログインする前に、ユーザーは「匿名」と見なされます。ユーザーがFormsAuthでログインすると、ユーザーは「認証済み」と見なされます。

この動作は、Forms認証を認識していなかったIIS 6.0からの変更であり、すべてのForms-Authenticatedユーザーを匿名と見なしたため、最初は混乱しました。

必要に応じて、匿名リクエストのフィールドとなるIDを変更できます。私の好み(そしてあなたのようにも聞こえます)は、彼らが 私のサイトのアプリプールと同じシステム資格情報。 IISを実行するには、次のようにします。

  1. IISマネージャー(inetmgr)を開きます
  2. [接続]パネルで、サイトのノードにドリルダウンして選択します
  3. 右側のパネルの[IIS]グループで、[認証]アイコンをダブルクリックします。
  4. 「匿名認証」を右クリックし、コンテキストメニューから「編集...」を選択します。
  5. ポップアップダイアログで、 「アプリケーションプールID」 ラジオボタン。
  6. [OK]をクリックします。

ステップ5も最初は混乱しました。「アプリケーションプールID」は「アプリケーションプール疑似アカウント」(IIS 7.5)のもう1つの新機能)を意味すると思ったからです。もちろん、それが実際に何を意味するのか。 、は 「それが何であれ、アプリプールが実行するように構成されているのと同じアカウント。」

そのサーバー上のすべてのWebサイト、または特定のサイトの単一のアプリケーションに対してデフォルトでこの動作が必要な場合は、これらのレベルで認証オプションを構成することもできます。 [接続]ペインで構成するノードを選択し、手順3〜6を繰り返します。

27
Matthew Schaad

アプリケーションが(おそらく)偽装を使用していないのに、アプリケーションが「NT AUTHORITY\IUSR」としてログインしようとするのはなぜですか?

もしあなたがそうするなら

<identity impersonate="true"/>

ログインしたユーザーになりすます

もしあなたがそうするなら

<identity impersonate="true" userName="contoso\Jane" password="pass"/>

上記で設定したユーザーになりすます。

ただし、偽装せずにWindows認証を使用する場合は、デフォルトのシステムアカウントを使用するのが理にかなっています。

IUSRとして最初に試行し、その後の要求で自動的にNETWORKSERVICEに切り替わる理由がわかりません。ただし、あるサーバーから別のサーバーにジャンプする場合、アプリケーションプールの資格情報は使用されないことを私は知っています。以下に示すように偽装ユーザーを設定しない限り、NETWORK SERVICEは、サーバーの外部でリソースをフェッチするために使用されるデフォルトのアカウントです。

    <connectionStrings>
        <add name="myConnectionString" connectionString="Data Source=MyServerName;Initial Catalog=MyDataBaseName;Integrated Security=True;"
          providerName="System.Data.SqlClient" />
      </connectionStrings>

<identity impersonate="true" userName="contoso\Jane" password="pass"/>
1
Arcturus