FW: How to spawn a process that runs under the context of the impersonated user in Microsoft ASP.NET pages
2013-02-01 17:20
841 查看
FW: http://support.microsoft.com/kb/889251
This step-by-step article describes how to spawn a process that runs under the context of the impersonated user in Microsoft ASP.NET pages. To spawn a process that runs under the context of the impersonated user, you cannot use the System.Diagnostics.Process.Start method. This is because in ASP.NET, impersonation is performed at the thread level and not at the process level. Therefore, any process that you spawn from ASP.NET will run under the context of the ASP.NET worker process and not under the impersonated context.
Description of the technique
To work around this issue, you must make platform invoke (P/Invoke) calls to the following Win32 APIs:
The CreateProcessAsUser function creates a process under the identity of the security token that is specified in one of the parameters. However, the call to the CreateProcessAsUser function requires a primary token. Therefore, you must convert the impersonated token to a primary token.
The DuplicateTokenEx function converts an impersonated token to a primary token. The call to the CreateProcessAsUser function uses this primary token.
Note For the call to the CreateProcessAsUser function to work, the following security user rights must be assigned to the impersonated user:
On a computer that is running Microsoft Windows 2000, assign the Replace a process level token user right and the Increase quotas user right to the impersonated user.
On a computer that is running Microsoft Windows Server 2003 or Microsoft Windows XP, assign the Replace a process level token user right to the impersonated user.
Steps to spawn a process
Microsoft provides programming examples for illustration only, without warranty either expressed or implied. This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose. This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures. Microsoft support engineers can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements. To spawn a process that runs under the context of the impersonated user, follow these steps:
In Microsoft Visual Studio .NET 2003, create a new Visual C# ASP.NET Web application, and then name the application Q889251.
Open the WebForm1.aspx file in code view.
In the WebForm1.aspx file, add the following statements to the using block of code.
using System.Runtime.InteropServices;
using System.Security.Principal;
Locate the line of code that looks similar to the following line of code.
public class WebForm1 : System.Web.UI.Page
After the line of code that is identified in step 4, add the following code.
[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);
In Solution Explorer, right-click WebForm1.aspx, and then click Open. The Web form opens in design view.
On the View menu, click HTML Source.
Replace all the existing code in the HTML Source window with the following code.
<%@ 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> </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>
On the View menu, click Design.
Double-click CreateProcess. The Button1_Click method is inserted into the code, and the code appears in the content pane.
Replace the existing Button1_Click method with the following code.
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";
}
On the Build menu, click Build Solution.
On the Debug menu, click Start.
In the WebForm1 page, type the path of a process that you want to start. For example, type SystemDriver\Windows\Notepad.exe.
Click CreateProcess.
References
For more information, click the following article number to view the article in the Microsoft Knowledge Base:
306158
(http://support.microsoft.com/kb/306158/ )
How to implement impersonation in an ASP.NET application
321748
(http://support.microsoft.com/kb/321748/ )
How to create a local Web server ASP.NET application
842790
(http://support.microsoft.com/kb/842790/ )
A System.Security.SecurityException exception occurs when you try to impersonate a user from a secondary thread in an ASP.NET Web application
This step-by-step article describes how to spawn a process that runs under the context of the impersonated user in Microsoft ASP.NET pages. To spawn a process that runs under the context of the impersonated user, you cannot use the System.Diagnostics.Process.Start method. This is because in ASP.NET, impersonation is performed at the thread level and not at the process level. Therefore, any process that you spawn from ASP.NET will run under the context of the ASP.NET worker process and not under the impersonated context.
Description of the technique
To work around this issue, you must make platform invoke (P/Invoke) calls to the following Win32 APIs:
The CreateProcessAsUser function creates a process under the identity of the security token that is specified in one of the parameters. However, the call to the CreateProcessAsUser function requires a primary token. Therefore, you must convert the impersonated token to a primary token.
The DuplicateTokenEx function converts an impersonated token to a primary token. The call to the CreateProcessAsUser function uses this primary token.
Note For the call to the CreateProcessAsUser function to work, the following security user rights must be assigned to the impersonated user:
On a computer that is running Microsoft Windows 2000, assign the Replace a process level token user right and the Increase quotas user right to the impersonated user.
On a computer that is running Microsoft Windows Server 2003 or Microsoft Windows XP, assign the Replace a process level token user right to the impersonated user.
Steps to spawn a process
Microsoft provides programming examples for illustration only, without warranty either expressed or implied. This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose. This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures. Microsoft support engineers can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements. To spawn a process that runs under the context of the impersonated user, follow these steps:
In Microsoft Visual Studio .NET 2003, create a new Visual C# ASP.NET Web application, and then name the application Q889251.
Open the WebForm1.aspx file in code view.
In the WebForm1.aspx file, add the following statements to the using block of code.
using System.Runtime.InteropServices;
using System.Security.Principal;
Locate the line of code that looks similar to the following line of code.
public class WebForm1 : System.Web.UI.Page
After the line of code that is identified in step 4, add the following code.
[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);
In Solution Explorer, right-click WebForm1.aspx, and then click Open. The Web form opens in design view.
On the View menu, click HTML Source.
Replace all the existing code in the HTML Source window with the following code.
<%@ 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> </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>
On the View menu, click Design.
Double-click CreateProcess. The Button1_Click method is inserted into the code, and the code appears in the content pane.
Replace the existing Button1_Click method with the following code.
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";
}
On the Build menu, click Build Solution.
On the Debug menu, click Start.
In the WebForm1 page, type the path of a process that you want to start. For example, type SystemDriver\Windows\Notepad.exe.
Click CreateProcess.
References
For more information, click the following article number to view the article in the Microsoft Knowledge Base:
306158
(http://support.microsoft.com/kb/306158/ )
How to implement impersonation in an ASP.NET application
321748
(http://support.microsoft.com/kb/321748/ )
How to create a local Web server ASP.NET application
842790
(http://support.microsoft.com/kb/842790/ )
A System.Security.SecurityException exception occurs when you try to impersonate a user from a secondary thread in an ASP.NET Web application
相关文章推荐
- How to spawn a process that runs under the context of the impersonated user in Microsoft ASP.NET pages
- It is not possible to run two different versions of ASP.NET in the same IIS process.问题的解决
- It is not possible to run two different versions of ASP.NET in the same IIS process:IIS
- It is not possible to run two different versions of ASP.NET in the same IIS process
- How to Pop Open an image window that resizes to fit the image in ASP.net 1.x and 2.0 Beta 1
- HOW TO: Change the Owner of a User-Defined Data Type That Is in Use in SQL Server 2000
- Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance
- how to prevent multiple login for same user in asp.net
- How to use Events in the Context of C#
- Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance. The connection
- Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance. The connection
- how to use javascript to control the usercotrol in the asp.net
- Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance. The connection
- How to load the specified mscordacwks.dll for managed debugging when multiple .NET runtime are loaded in one process
- CodeSnip: How to Get Id of the Record Using ASP.NET and SQL Server 2000
- Link ASP.NET Data Grid to Microsoft Excel in the client side
- How to find PID of process listening on a port in Linux? netstat and lsof command examples
- Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance. The connection
- How to set the DefaultButton in a Page Based on ASP.NET Master Page
- How to check the usage of net ports in linux?