Skip to main content

 none
NTSetInformationProcess (ProcessAccessToken) fails with STATUS_NOT_SUPPORTED RRS feed

  • Question

  • I had just created a new method to implement setuid() on Cygwin, which doesn't
    just call ImpersonateLoggedOnUser, but instead tries to replace the process token
    using NTSetInformationProcess (ProcessAccessToken).

    The problem with using
    ImpersonateLoggedOnUser is that the effect of calling
    setuid() can be reverted by a call to RevertToSelf(). This is contrary to how
    setuid() is supposed to work. For security reasons, a setuid() call must not be
    revertable when called from a privileged user account.

    So, to accomplish this, I re-implemented setuid() by replacing the process token.
    This works fine on all systems until Windows 2003.

    Guess what happens on Vista. The
    NTSetInformationProcess call returns with
    STATUS_NOT_SUPPORTED. I'm rather disappointed. I was going to make
    a system call more secure and Vista doesn't allow it. This contradicts security
    rather than helping it.

    So, here's the question: How is a POSIX layer supposed to implement setuid
    correctly if that feature has been removed from the OS? How is Interix going to
    do that?


    Corinna
    Tuesday, December 19, 2006 3:28 PM

Answers

  • Hello.

    I am a developer on the Windows Kernel Team. Before continuing, I want to stress as a disclaimer that NtSetInformationProcess, class ProcessAccessToken, is an undocumented and unsupported infterface. It is reserved for system component use and is subject to change between operating system releases. That being said, I would like to address your particular concern.

    The NT kernel was never intended to allow token switching once a process started running. This is because handles, etc. may have been opened in an old security context, inflight operations may use inconsistent security contexts, etc. As such, it typically does not make sense to switch a process' token once it has begun execution. However, this was not enforced until Vista.

    Unfortunately, it is difficult to properly implement setuid() semantics on NT as you have noted, though it too could be susceptible to the issues outlined above. After exploring alternative implementations for Interix we settled on leaving the lazy swap behavior intact for EXEs launched from POSIX binaries (image type = POSIX in the PE image). This was a reasonable compromise since the change was not security-based in nature, and allowed the legacy behavior to persist in conjunction with binaries that had (or should have) better control of their environment.

    Arun Kishan

    Windows Kernel Team

    Wednesday, January 3, 2007 3:14 AM

All replies

  • Ping?  Any help here?


    Corinna
    Saturday, December 23, 2006 2:47 PM
  • Hello.

    I am a developer on the Windows Kernel Team. Before continuing, I want to stress as a disclaimer that NtSetInformationProcess, class ProcessAccessToken, is an undocumented and unsupported infterface. It is reserved for system component use and is subject to change between operating system releases. That being said, I would like to address your particular concern.

    The NT kernel was never intended to allow token switching once a process started running. This is because handles, etc. may have been opened in an old security context, inflight operations may use inconsistent security contexts, etc. As such, it typically does not make sense to switch a process' token once it has begun execution. However, this was not enforced until Vista.

    Unfortunately, it is difficult to properly implement setuid() semantics on NT as you have noted, though it too could be susceptible to the issues outlined above. After exploring alternative implementations for Interix we settled on leaving the lazy swap behavior intact for EXEs launched from POSIX binaries (image type = POSIX in the PE image). This was a reasonable compromise since the change was not security-based in nature, and allowed the legacy behavior to persist in conjunction with binaries that had (or should have) better control of their environment.

    Arun Kishan

    Windows Kernel Team

    Wednesday, January 3, 2007 3:14 AM
  • Hi,

    > [...] NtSetInformationProcess, class ProcessAccessToken, is an undocumented and
    > unsupported infterface.


    I understand perfectly. It's just that some undocumented APIs look pretty useful to implement
    a certain behaviour...

    > The NT kernel was never intended to allow token switching once a process started running.

    Uh, ok. So
    the NtSetInformationProcess(ProcessAccessToken) API was only ever meant to
    set the process token at process creation time?

    > This is because handles, etc. may have been opened in an old security context, inflight
    > operations may use inconsistent security contexts, etc. As such, it typically does not make
    > sense to switch a process' token once it has begun execution.

    I'm wondering that this matters.
    I assumed that the security context only matters at creation
    time of the handle to the object. When I give a handle to a child process running under another
    user account, the handle is still valid in the context of the child process. So, without knowing
    how that's implemented, it sounds strange that this should be different when changing the
    user context in the running process.

    > After exploring alternative implementations for Interix we settled on leaving the lazy swap
    > behavior intact [...]. This was a reasonable compromise since the change was not
    > security-based in nature, and allowed the legacy behavior to persist in conjunction with
    > binaries that had (or should have) better control of their environment.


    Do I understand you correctly, with "lazy" you mean that Interix is using an equivalent
    approach(*) to Cygwin, which is, changing the user context using ImpersonateLoggedOnUser
    in the calling process and only switching to the final user context when starting child
    processes on exec(3) using CreateProcessAsUser? Or is there yet another way to do this
    which I just don't realize?

    What always bugged me with this technique is the fact that it's easily possible to switch back
    to the original user context in the calling process. OpenSSH, for instance, has a function
    permanently_set_uid(), which tests explicitly if it's possible to revert the user context after
    calling setuid(). If so, it treats that as a fatal error and exits. Since Cygwin's setuid is "broken"
    in this regard, it was necessary to add a bit of Cygwin-specific code to OpenSSH. Sure, I could
    implement setuid so that it doesn't allow a reversion to the original user context. But it would not
    reflect the reality, it would just fake security.


    Thanks for your informative and helpful reply,
    Corinna



    (*) I'm aware that you don't use the Win32 interfaces in Interix ;)
    Thursday, January 4, 2007 5:58 PM
  • Yes, it was initially only intended for our own use to enable CreateProcessAsUser. What was meant above about odd behavior is the inconsistencies that result since objects that perhaps a process could access previously may no longer be accessible (handle accesses remain fine). It's not a real security problem but is also of limited use unless you have total control of the target process to know its state at the time of the swap. Since for most NT processes there could be any number of threads doing various tasks (including injected threads), the effect of a swap during runtime is not deterministic.

    Our guidance around this to Interix was to use NT impersonation support for revertable setuid and for the permanent id change case (dropping privileges), we decided to support the primary token swap as noted above. We allow this if the primary exe is a POSIX exe since the environment is assumed to be more constrained.

    Arun

    Friday, February 16, 2007 9:54 AM
  • So short of implementing the actual swap myself in a driver, which I am loathe to do, or tricking the API into thinking I'm POSIX, is there any other way to achieve it?

     

    We have an application that worked fine on XP but is broken on Vista due to this change.

     

    Thursday, September 18, 2008 6:26 PM