Microsoft ASP.NET で偽装されたユーザーのコンテキストで実行されるプロセスを生成する

この記事では、偽装されたユーザーのコンテキストで実行されるプロセスを生成する方法について説明します。

元の製品バージョン: ASP.NET
元の KB 番号: 889251

概要

この詳細な記事では、偽装されたユーザーのコンテキストで実行されるプロセスを ASP.NET ページで生成する方法について説明します。 偽装されたユーザーのコンテキストで実行されるプロセスを生成するには、 メソッドを System.Diagnostics.Process.Start 使用できません。 これは、ASP.NET では、偽装はプロセス レベルではなくスレッド レベルで実行されるためです。 そのため、ASP.NET から生成するすべてのプロセスは、偽装されたコンテキストではなく、ASP.NET ワーカー プロセスのコンテキストで実行されます。

手法の説明

この問題を回避するには、次の Win32 API に対してプラットフォーム呼び出し (P/Invoke) を呼び出す必要があります。

  • 関数は CreateProcessAsUser 、いずれかのパラメーターで指定されたセキュリティ トークンの ID の下にプロセスを作成します。 ただし、関数の呼び出しには CreateProcessAsUser プライマリ トークンが必要です。 そのため、偽装されたトークンをプライマリ トークンに変換する必要があります。

  • 関数は DuplicateTokenEx 、偽装されたトークンをプライマリ トークンに変換します。 関数の呼び出しでは、 CreateProcessAsUser このプライマリ トークンが使用されます。

注:

関数の呼び出しを CreateProcessAsUser 機能させるには、偽装されたユーザーに次のセキュリティ ユーザー権限を割り当てる必要があります。

  • Windows を実行しているコンピューターで、[ プロセス レベルのトークンを置き換える ] ユーザー権利と [ クォータの増加 ] ユーザー権限を偽装ユーザーに割り当てます。
  • Windows Server または Windows XP を実行しているコンピューターで、偽装されたユーザーに プロセス レベルトークンを置き換える 権限を割り当てます。

プロセスを生成する手順

Microsoft は、例示のみを目的としてプログラミング例を提供しており、明示または黙示にかかわらず、いかなる責任も負わないものとします。 これには、市販性または特定の目的との適合性についての黙示の保証も含まれますが、これに限定はされません。 この記事は、説明されているプログラミング言語、手順を作成およびデバッグするために使用されているツールに読者が精通していることを前提にしています。 マイクロソフト サポート窓口では、特定のプロシージャの機能説明に関するご質問に対して支援いたしますが、本例を特定の目的を満たすために機能を追加したり、プロシージャを構築することは行いません。 偽装されたユーザーのコンテキストで実行されるプロセスを生成するには、次の手順に従います。

  1. Visual Studio .NET で、新しい Visual C# ASP.NET Web アプリケーションを作成し、アプリケーションにQ889251という名前をけます。

  2. コード ビューWebForm1.aspx ファイルを開きます。

  3. WebForm1.aspx ファイルで、using コード ブロックに次のステートメントを追加します。

    using System.Runtime.InteropServices;
    using System.Security.Principal;
    
  4. 次のコード行のようなコード行を見つけます。

    public class WebForm1 : System.Web.UI.Page
    
  5. 手順 4 で識別されたコード行の後に、次のコードを追加します。

    [StructLayout(LayoutKind.Sequential)]
    public struct STARTUPINFO
    {
        public int cb;
        public String lpReserved;
        public String lpDesktop;
        public String lpTitle;
        public uint dwX;
        public uint dwY;
        public uint dwXSize;
        public uint dwYSize;
        public uint dwXCountChars;
        public uint dwYCountChars;
        public uint dwFillAttribute;
        public uint dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public uint dwProcessId;
        public uint dwThreadId;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public int Length;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
    }
    [DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true, CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
    public extern static bool CloseHandle(IntPtr handle);
    [DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser", SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
    public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
    [DllImport("advapi32.dll", EntryPoint="DuplicateTokenEx")]
    public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
    
  6. ソリューション エクスプローラーで、[WebForm1.aspx] を右クリックし、[開く] をクリックします。 Web フォームが デザイン ビューで開きます。

  7. [ 表示 ] メニューの [ HTML ソース] をクリックします。

  8. [HTML ソース] ウィンドウ内のすべての既存のコードを次のコードに置き換えます。

    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="Q889251.WebForm1" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
       <HEAD>
          <title>WebForm1</title>
          <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
          <meta name="CODE_LANGUAGE" Content="C#">
          <meta name="vs_defaultClientScript" content="JavaScript">
          <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
       </HEAD>
       <body>
          <form id="Form1" method="post" runat="server">
             <P>&nbsp;</P>
             <P>
                Enter Path of process to be run (with relevant parameters)
                <asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
             </P>
             <P>
                <asp:Button id="Button1" runat="server" Text="CreateProcess"></asp:Button>
             </P>
             <P>
                <asp:Label id="Label1" runat="server">Status:</asp:Label>
             </P>
             <P>
                <asp:Label id="Label2" runat="server">Impersonated Identity:</asp:Label>
             </P>
          </form>
       </body>
    </HTML>
    
  9. [ 表示 ] メニューの [ デザイン] をクリックします。

  10. [CreateProcess] をダブルクリックします。 Button1_Clickメソッドがコードに挿入され、コードがコンテンツ ウィンドウに表示されます。

  11. 既存 Button1_Click のメソッドを次のコードに置き換えます。

    private void Button1_Click(object sender, System.EventArgs e)
    {
        IntPtr Token = new IntPtr(0);
        IntPtr DupedToken = new IntPtr(0);
        bool ret;
        Label2.Text+=WindowsIdentity.GetCurrent().Name.ToString();
        SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
        sa.bInheritHandle = false;
        sa.Length = Marshal.SizeOf(sa);
        sa.lpSecurityDescriptor = (IntPtr)0;
        Token = WindowsIdentity.GetCurrent().Token;
        const uint GENERIC_ALL = 0x10000000;
        const int SecurityImpersonation = 2;
        const int TokenType = 1;
        ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken);
        if (ret == false)
        {
            Label1.Text +="DuplicateTokenEx failed with " + Marshal.GetLastWin32Error();
        }
        else
        {
            Label1.Text+= "DuplicateTokenEx SUCCESS";
            STARTUPINFO si = new STARTUPINFO();
            si.cb = Marshal.SizeOf(si);
            si.lpDesktop = "";
            string commandLinePath;
            commandLinePath = TextBox1.Text;
            PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
            ret = CreateProcessAsUser(DupedToken,null,commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, "c:\\", ref si, out pi);
            if (ret == false)
            {
                Label1.Text +="CreateProcessAsUser failed with " + Marshal.GetLastWin32Error();
            }
            else
            {
                Label1.Text +="CreateProcessAsUser SUCCESS. The child PID is" + pi.dwProcessId;
                CloseHandle(pi.hProcess);
                CloseHandle(pi.hThread);
            }
            ret = CloseHandle(DupedToken);
            if (ret == false)
            {
                Label1.Text+=Marshal.GetLastWin32Error();
            }
            else
            {
                Label1.Text+="CloseHandle SUCCESS";
            }
        }
    }
    
  12. [ ビルド] メニューで、[ ソリューションのビルド] をクリックします。

  13. [ デバッグ ] メニューの [ 開始] をクリックします。

  14. [WebForm1] ページで、開始するプロセスのパスを入力します。 たとえば、「」と入力します SystemDriver \Windows\Notepad.exe

  15. [ CreateProcess] をクリックします。

関連情報