Unable to use CreateProcessWithTokenW from ASP.NET

Discussion in 'ASP .Net Security' started by Aadil Abbas, Aug 6, 2003.

  1. Aadil Abbas

    Aadil Abbas Guest

    I need to create a child process from an impersonated ASP.NET application
    (web service), the child process should also run in the security context of
    the impersonated thread. I could not find any managed class that
    encapsulates this functionality, therefore I am using
    "CreateProcessWithTokenW" windows API function. Now this function is working
    fine for me from a .NET console application, but when I run it from a web
    service running on IIS 6.0 and windows 2003, it fails.

    CreateProcessWithTokenW requires a primary token in order to create a child
    process, for this reason I am using DuplicateTokenEx function. Now my
    DuplicateTokenEx function returns true, and creates a duplicate primary
    token, but unfortunately CreateProcessWithTokenW function fails with error
    code "5", this win32 error depicts "Access is denied". My parent process has
    the privilege "Replace a process level token".

    The dwCreationFlags passed to "CreateProcessWithTokenW" has
    "CREATE_NO_WINDOW", but still a window is created the reason being
    "CREATE_NEW_CONSOLE" is enabled by default as stated in the documentation. I
    have also tried by setting "DETACH_PROCESS" flag, in that case I get a
    different error: error code 87 "The parameter is incorrect". I presume
    either my calls to unmanaged code have some flaw or I am missing some
    security setting. Please see if you could spot anything wrong.

    [SecurityPermission(SecurityAction.Demand,ControlPrincipal = true)]
    public class ProcessToken
    {
    [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    internal static extern bool CreateProcessWithTokenW(IntPtr
    dupeTokenHandle,
    int dwLogonFlags, string applicationName, StringBuilder commandLine,
    int creationFlags, IntPtr environment,
    string currentDirectory,
    ref STARTUPINFO sui,
    out PROCESS_INFORMATION processInfo);

    [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    internal static extern bool DuplicateTokenEx(IntPtr tokenHandle, int
    dwDesiredAccess,
    ref SECURITY_ATTRIBUTES lpTokenAttributes, int
    SECURITY_IMPERSONATION_LEVEL ,
    int TOKEN_TYPE, ref IntPtr dupeTokenHandle);


    [DllImport("kernel32")]
    static extern bool CloseHandle(IntPtr handle);

    [StructLayout(LayoutKind.Sequential)]
    internal struct SECURITY_ATTRIBUTES
    {
    internal int nLength;
    internal int lpSecurityDescriptor;
    internal bool bInheritHandle;

    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct STARTUPINFO
    {
    internal int cb;
    [MarshalAs(UnmanagedType.LPTStr)]
    internal string lpReserved;
    [MarshalAs(UnmanagedType.LPTStr)]
    internal string lpDesktop;
    [MarshalAs(UnmanagedType.LPTStr)]
    internal string lpTitle;
    internal int dwX;
    internal int dwY;
    internal int dwXSize;
    internal int dwYSize;
    internal int dwXCountChars;
    internal int dwYCountChars;
    internal int dwFillAttribute;
    internal int dwFlags;
    internal short wShowWindow;
    internal short cbReserved2;
    internal IntPtr lpReserved2;
    internal IntPtr hStdInput;
    internal IntPtr hStdOutput;
    internal IntPtr hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct PROCESS_INFORMATION
    {
    internal IntPtr hProcess;
    internal IntPtr hThread;
    internal int dwProcessId;
    internal int dwThreadId;
    }

    // SECURITY_IMPERSONATION_LEVEL
    const int SecurityAnonymous = 0;
    const int SecurityIdentification = 1;
    const int SecurityImpersonation = 2;
    const int SecurityDelegation = 3;

    // TOKEN_TYPE
    const int TokenPrimary = 1;
    const int TokenImpersonation = 2;

    //dwLogonFlags Specifies the logon option
    const int LOGON_WITH_PROFILE = 1;
    const int LOGON_NETCREDENTIALS_ONLY = 2;

    // Access Token constants
    const int TOKEN_ALL_ACCESS = 0x10000000;

    //dwCreationFlags - Specifies how the process is created
    const int DETACHED_PROCESS = 0x00000008;
    const int CREATE_NO_WINDOW = 0x08000000;
    const int CREATE_SUSPENDED = 0x00000004;
    const int CREATE_NEW_CONSOLE = 0x00000010;
    const int CREATE_NEW_PROCESS_GROUP = 0x00000200;
    const int CREATE_SEPARATE_WOW_VDM = 0x00000800;
    const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
    const int CREATE_DEFAULT_ERROR_MODE = 0x04000000;

    //dwCreationFlags parameter controls the new process's priority class
    const int NORMAL_PRIORITY_CLASS = 0x00000020;
    const int IDLE_PRIORITY_CLASS = 0x00000040;
    const int HIGH_PRIORITY_CLASS = 0x00000080;
    const int REALTIME_PRIORITY_CLASS = 0x00000100;
    const int BELOW_NORMAL_PRIORITY_CLASS = 0x00004000;
    const int ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000;
    //dwFlags
    // This is a bit field that determines whether certain STARTUPINFO
    // members are used when the process creates a window.
    // Any combination of the following values can be specified:
    const int STARTF_USESHOWWINDOW = 0x0000000;
    const int STARTF_USESIZE = 0x00000002;
    const int STARTF_USEPOSITION = 0x00000004;
    const int STARTF_USECOUNTCHARS = 0x00000008;
    const int STARTF_USEFILLATTRIBUTE = 0x00000010;
    const int STARTF_FORCEONFEEDBACK = 0x00000040;
    const int STARTF_FORCEOFFFEEDBACK = 0x00000080;
    const int STARTF_USESTDHANDLES = 0x00000100;
    const int STARTF_USEHOTKEY = 0x00000200;


    public static string CreateTokenChild()
    {
    try
    {
    string temp = System.Web.HttpContext.Current.User.Identity.Name;

    StringBuilder sb = new StringBuilder();
    // process to execute
    sb.Append(@"cmd.exe");

    PROCESS_INFORMATION processInfo;
    STARTUPINFO startInfo = new STARTUPINFO();
    startInfo.cb = Marshal.SizeOf(startInfo);

    // Create Process with token
    IntPtr dupeTokenHandle = IntPtr.Zero;
    IntPtr tokenHandle = WindowsIdentity.GetCurrent().Token;

    // Setting security attributes
    SECURITY_ATTRIBUTES lpTokenAttributes = new SECURITY_ATTRIBUTES();
    lpTokenAttributes.nLength = Marshal.SizeOf(lpTokenAttributes);
    lpTokenAttributes.lpSecurityDescriptor = 0;
    lpTokenAttributes.bInheritHandle = true;

    bool retVal = DuplicateTokenEx(tokenHandle, TOKEN_ALL_ACCESS, ref
    lpTokenAttributes, SecurityImpersonation, TokenPrimary, ref
    dupeTokenHandle);

    bool ret = CreateProcessWithTokenW(dupeTokenHandle,
    LOGON_WITH_PROFILE , null, sb,
    CREATE_NO_WINDOW,
    IntPtr.Zero, "c:\\",
    ref startInfo, out processInfo);

    if(!ret)
    {
    // If failure ...
    int err = Marshal.GetLastWin32Error();
    return err.ToString();
    }
    }

    catch (Exception e)
    {
    return e.ToString();
    }
    return "child created";
    }
    }

    Thanks
    Aadil
     
    Aadil Abbas, Aug 6, 2003
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bite My Bubbles
    Replies:
    0
    Views:
    1,396
    Bite My Bubbles
    Sep 4, 2003
  2. Mickey
    Replies:
    2
    Views:
    655
    =?Utf-8?B?UmFzaWthIFdpamF5YXJhdG5l?=
    Apr 21, 2004
  3. Krishna Chytanya

    Unable to use Activex control in Asp.Net 2.0

    Krishna Chytanya, Nov 1, 2007, in forum: ASP .Net
    Replies:
    2
    Views:
    326
    Krishna Chytanya
    Nov 1, 2007
  4. japss
    Replies:
    0
    Views:
    601
    japss
    Jul 12, 2008
  5. Jake Barnes
    Replies:
    6
    Views:
    429
    9.co.uk
    Feb 8, 2006
Loading...

Share This Page