Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process SE DEBUG mode is not set on Windows #1429

Merged
merged 7 commits into from
Feb 25, 2019
Merged

Conversation

giampaolo
Copy link
Owner

@giampaolo giampaolo commented Feb 24, 2019

From the code:

/*
 * Set this process in SE DEBUG mode so that we have more chances of
 * querying processes owned by other users, including many owned by
 * Administrator and Local System.
 * https://docs.microsoft.com/windows-hardware/drivers/debugger/debug-privilege
 */

^ that is what we are supposed to do on module import. While I was refactoring this function I realized that the code which uses it never checks return code/error, so possibly SE DEBUG has never been set (or it has been broken at some point, I wouldn't know). Now it's set and will raise exception on import in case of error (not what I want - will change it later). Perhaps this means we're now gonna get less AccessDenied exceptions for PIDs owned by other/system users?

@jloden - you wrote this code 10 years ago - brings back memories =)

UPDATE: confirmed SE DEBUG was not set. I tested with a limited user and it seems we get slightly less AD exceptions .

…id we ever set SE DEBUG at all?) - if SE DEBUG can't be set we now raise an exception on import; that's bad - I'll change it later, and I will probably replace it with a warning
@giampaolo giampaolo changed the title Fix / investigate SE DEBUG on Windows Process SE DEBUG mode is not set on Windows Feb 25, 2019
@giampaolo
Copy link
Owner Author

Confirmed SE DEBUG was not set. I tested with a limited user and it seems we get slightly less AD exceptions .

@cwegener
Copy link

X-post from gopsutil with just the relevant part:

why does psutil have a need to bypass the Win32 security system by using the SeDebugPrivilege instead of returning an actual 'access denied' error if the user who runs psutil does not have permissions to kill the process? Does psutil do the same bypassing of the OS security on non-Windows platforms?

@giampaolo
Copy link
Owner Author

As the code comment says, the rationale is getting less access denied exceptions for non-admin users. This was added at the inception of the project, around 15 years ago, so I don't recall the exact circumstance that led to this decision. It may be possibile that this was necessary on windows XP and it's not longer necessary today.

@cwegener
Copy link

The additional problem is actually this PR, which escalated the use of the privilege from a narrow use case (process.kill API) to now always run with the dangerous SE_DEBUG_NAME privilege all the time.

I think that the limited use case is actually somewhat acceptable:

  1. Try to kill process
  2. If access denied, try adding the SE_DEBUG_NAME privilege to the Python interpreter process (current process)
  3. Try to kill the process again
  4. Remove the SE_DEBUG_NAME privilege from the Python interpreter process again.

The above would be acceptable.

On the contrary, constantly running with the dangerous token all the time is causing problems:

  1. EDR tools will pick this elevated token up and create alerts
  2. Malicious actors will take advantage of psutil to steal credentials or do other damage

@giampaolo
Copy link
Owner Author

Point is I'm not sure whether SE_DEBUG_NAME was added only because of kill(). It's possible it reduces access denied also for other APIs, hence why it's enabled for the whole lifetime of the (python) process.

Can you provide some links / literature that recommends against using SE_DEBUG_NAME for security reasons?

@cwegener
Copy link

Can you provide some links / literature that recommends against using SE_DEBUG_NAME for security reasons?

The documentation from Microsoft words it in a somewhat passive manner here:

https://learn.microsoft.com/en-us/windows/win32/secauthz/enabling-and-disabling-privileges-in-c--

Your application should thoroughly verify that the privilege is appropriate to the type of account, especially for the following powerful privileges

I am still in the process of creating a minimal example that will actually trigger an alert in an EDR system, in my case using Microsoft Defender for Endpoint as the EDR tool.

I can successfully trigger a 'Credential access' false positive alert in Defender for Endpoints when using a large Golang program that uses gopsutil. Once I have managed to write a very small Golang program with gopsutil that also triggers the problematic scenario, I will try and also port that to python psutil.

@cwegener
Copy link

Point is I'm not sure whether SE_DEBUG_NAME was added only because of kill().

The way I interpret it, it was added for kill() only in 2009 in the early days of psutil 4a9678b

I haven't specifically looked for another commit between 2009 and 2019 that would have broadened the use of the Debug privilege prior to this PR.

It's possible it reduces access denied also for other APIs, hence why it's enabled for the whole lifetime of the (python) process.

Yes, I'm pretty confident that it will. I would have to look it up, but I wouldn't be surprised if even some everyday tools from Microsoft that ship together with Windows OS would probably have used this privilege in the past. With Windows 10 and later though, I don't think this would be the case anymore.

@jloden
Copy link
Collaborator

jloden commented Nov 30, 2023 via email

@cwegener
Copy link

Thanks Jay! Really appreciate the feedback and the time taken.

I suspect that you would still have the same issues with granting psutil
read permissions to other processes, but if there's a better and more
secure way to do this that doesn't create deployment issues or break a lot
of backwards compatibility, it's worth reviewing.

This was my original intention, but I fear that it would be substantial work involved in it.

And also I believe that even some Microsoft built-in Windows tooling itself (e.g. taskmgr.exe) probably has long been using this way of obtaining handles.

At this stage, I'm still in the research and experimentation phase to gain a full understanding of the situation, including:

  1. Impact on the whole EDR situation, which triggered my investigation in the first place => I'm not even 100% certain yet that a process with SE_DEBUG_NAME opening handles to other processes (which are considered security-critical processes like lsass.exe ) is the main issue that I'm chasing here, but it looks very likely to be true. example scenarios: [1]
  2. What is Microsoft doing in their own tooling and API landscape? I.e. how does latest taskmgr.exe work on Win10/Win11? Are different Win32 APIs being used now by Microsoft's own tools?
  3. Better understanding of the Win32 security model as it relates to default security principals (users) and their default privileges in Win32 (e.g. NT AUHTORITY\SYSTEM would have always had some sort of SE_DEBUG enabled by default in many versions of Windows)

[1] https://niiconsulting.com/checkmate/2019/11/token-manipulation-attacks-part-2-process-of-impersonation/

@jloden
Copy link
Collaborator

jloden commented Dec 1, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants