I'm not sure this is the right place to ask about this, but I can't think of where the right place would be, so I'm just going to list my thoughts on this.
Anyways, these are just my thoughts that I wanted to get out there. Happy to hear about any plans/concerns/a better place to have this discussion.
So I know there have been a LOT of discussions about getting a "sudo for Windows" built. I'm not sure that we have any concrete plans in place, but I know it's something a lot of us want. I'm certainly not the person to be asking about this - perhaps @bitcrazed or @yodurr can comment more?
Thanks for the quick response! If I had to guess I'd say this probably would go to either whoever deals with UAC/token management or dev mode, but I don't know of any other Windows team that's as community friendly and easily reachable, so I figured it's worth a shot starting a discussion.
It's really conflicting, because I've seen so many scripts that just pop up the UAC dialog, and I could throw something together for myself that doesn't, but I can only fix the annoyance issue, not the "things being designed around the platform not supporting this" one.
While we're not able to give you a firm timeline right now, I can echo @zadjii-msft's comment - we are sooooooooo keen for "Add sudo" to bubble up our priority list so we can get to work on it :)
As with anything to do with security, we will be working with the Windows core security & management teams to make sure that we "do it right".
Good to know it's on the list, that's about as much as I can ask for. Thanks!
@parkovski - If that's all you can ask for, I fear for your imagination :D ;)
Hey now. I can ask for chocolate and berries to be a healthy diet or for politicians to stop pitting people against each other, but realistically all I'm gonna get is command line elevation.
Chocolate isn't healthy? Pfffft!
Uh oh, my cover's blown :(
This will likely depend on ConPTY or something, as it鈥檚 currently impossible to get the STDOUT, STDERR or聽STDIN of聽an聽elevated process from a non鈥慹levated process :( (I know as I tried to implement a聽sudo
cmdlet for聽PowerShell).
We need a full sudo, not just a "run as admin in terminal".
Sudo allows to run arbitrary commands as arbitrary users, following it's configuration.
Not terminal related, but I have a pretty good PowerShell sudo that has been working well for me in Windows.
Edit your profile:
PS > notepad $PROFILE
Add the following sudo
function:
function sudo {
Start-Process -Verb RunAs -FilePath "pwsh" -ArgumentList (@("-NoExit", "-Command") + $args)
}
Then invoke in your shell. Supports cmdlets, executables, anything that could normally be typed into a PS prompt:
PS > sudo Remove-Item .\test.txt # Remove a file
PS > sudo Copy-Item .\test.txt C:\ # Copy a file
PS > sudo net start w3svc # Start IIS
If you want to pass in a variable or expression that will be evaluated at run time, rather than pre-evaluated, wrap it in braces. For example:
PS > $myvar = "a"
PS > sudo echo $myvar # $myvar is pre-evaluated, so the command reads: sudo echo "a"
PS > sudo { $PSVersionTable } # with braces, $PSVersionTable is not evaluated until it is run as administrator
Remove "-NoExit"
from the sudo function if you'd prefer to have the administrator window close when complete.
@vsalvino Thanks, but this still requires UAC which is a no-go for some use cases (ssh). Unfortunately the only real solution to this is going to require a pretty decent amount of work.
I don't guarantee that my opinion is absolutely correct. If there is something wrong with this, please remind me.
Implementing sudo without sharing terminals is very easy in Windows. For example, I have developed Privexec (Run the program with the specified permission level Trust Installer, System, MIC, AppContainer ...) to support the process of starting the administrator rights and can wait.
wsudo -A -w pwsh
But the difficulty is that Windows RunAs does not support inheriting standard output.
So how to implement a sudo program, after creating a new process, enables the privileged process to inherit the existing terminal?
Regardless of the operating system, the act of escalation is actually a process that requests a high-privileged process to start a low-privileged process.
We look at the file permissions of the sudo program exa -g -h -l --time-style long-iso /usr/bin/sudo
(exa is a replacement for ls written in Rust.):
This means that when we execute sudo,Since the owner of sudo is root. and contains the S_ISUID privilege, sudo can set itself to root, and after verifying that the user credentials are valid, the user-entered command is initiated. The child process just inherits the permissions of sudo.
I executed top
and sudo top
in the same terminal, and I found that the input and output are consistent:
Use UAC to grant administrator privileges from standard users in Windows. The process is as follows ShellExecute Internals::
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
, and uses the handle retrieved in step 3.EXTENDED_STARTUPINFO_PRESENT
and the results of steps 1 and 4.Therefore, there are several ideas for implementing sudo that can inherit input and output on Windows. The first one is Windows improvement. When the AppInfo service creates a process, if the process's subsystem is CUI and needs to inherit input and output, the process will be called. The console lets the child process inherit, but here I am not sure if the console can inherit from different permission levels.
Another solution is the C/S architecture, which is divided into sudo and sudo-srv. sudo is the client that privates the privilege. Sudo-srv acts as a service running with System privileges. When the user runs sudo, sudo interacts with the user. The command line, the credential is sent to sudo-srv through the encryption code, sudo-srv uses LogonUserW to verify that the user credentials are valid, When the starting process subsystem is CUI, sudo-srv uses the conpty+CreateProcessAsUserW method to start the child process, and then the conpty The output interacts with sudo and sudo is output to the terminal. The benefits of this approach are not required for Windows updates.
In the code below, we need to replace CreateProcessW with CreateProcessAsUserW in sudo-srv to start the admin process:
__declspec(noinline) inline HRESULT CreateConPty(const std::wstring& cmdline,
const unsigned short w,
const unsigned short h,
HANDLE* const hInput,
HANDLE* const hOutput,
HANDLE* const hSignal,
PROCESS_INFORMATION* const piPty)
{
// Create some anon pipes so we can pass handles down and into the console.
// IMPORTANT NOTE:
// We're creating the pipe here with un-inheritable handles, then marking
// the conhost sides of the pipes as inheritable. We do this because if
// the entire pipe is marked as inheritable, when we pass the handles
// to CreateProcess, at some point the entire pipe object is copied to
// the conhost process, which includes the terminal side of the pipes
// (_inPipe and _outPipe). This means that if we die, there's still
// outstanding handles to our side of the pipes, and those handles are
// in conhost, despite conhost being unable to reference those handles
// and close them.
// CRITICAL: Close our side of the handles. Otherwise you'll get the same
// problem if you close conhost, but not us (the terminal).
HANDLE outPipeConhostSide;
HANDLE inPipeConhostSide;
HANDLE signalPipeConhostSide;
SECURITY_ATTRIBUTES sa;
sa = { 0 };
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = nullptr;
CreatePipe(&inPipeConhostSide, hInput, &sa, 0);
CreatePipe(hOutput, &outPipeConhostSide, &sa, 0);
// Mark inheritable for signal handle when creating. It'll have the same value on the other side.
sa.bInheritHandle = TRUE;
CreatePipe(&signalPipeConhostSide, hSignal, &sa, 0);
SetHandleInformation(inPipeConhostSide, HANDLE_FLAG_INHERIT, 1);
SetHandleInformation(outPipeConhostSide, HANDLE_FLAG_INHERIT, 1);
std::wstring conhostCmdline = L"conhost.exe";
conhostCmdline += L" --headless";
std::wstringstream ss;
if (w != 0 && h != 0)
{
ss << L" --width " << (unsigned long)w;
ss << L" --height " << (unsigned long)h;
}
ss << L" --signal 0x" << std::hex << HandleToUlong(signalPipeConhostSide);
conhostCmdline += ss.str();
conhostCmdline += L" -- ";
conhostCmdline += cmdline;
STARTUPINFO si = { 0 };
si.cb = sizeof(STARTUPINFOW);
si.hStdInput = inPipeConhostSide;
si.hStdOutput = outPipeConhostSide;
si.hStdError = outPipeConhostSide;
si.dwFlags |= STARTF_USESTDHANDLES;
std::unique_ptr<wchar_t[]> mutableCommandline = std::make_unique<wchar_t[]>(conhostCmdline.length() + 1);
if (mutableCommandline == nullptr)
{
return E_OUTOFMEMORY;
}
HRESULT hr = StringCchCopy(mutableCommandline.get(), conhostCmdline.length() + 1, conhostCmdline.c_str());
if (!SUCCEEDED(hr))
{
return hr;
}
bool fSuccess = !!CreateProcessW(
nullptr,
mutableCommandline.get(),
nullptr, // lpProcessAttributes
nullptr, // lpThreadAttributes
true, // bInheritHandles
0, // dwCreationFlags
nullptr, // lpEnvironment
nullptr, // lpCurrentDirectory
&si, // lpStartupInfo
piPty // lpProcessInformation
);
CloseHandle(inPipeConhostSide);
CloseHandle(outPipeConhostSide);
CloseHandle(signalPipeConhostSide);
return fSuccess ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
Simple flow chart:
There is also a simpler solution, that is, using an intermediate program, ShellExecute starts an intermediate program, and then the intermediate program will reattach to the console of the parent process according to the command line parameters, thus implementing a shared console like sudo. Refer to @lukesampson's psutils/sudo here. But this solution still requires UI interaction.
Now wsudo implements this mechanism in the dev branch (Windows Terminal Dev test OK). see: M2Team/Privexec@ead21177d6a83368f82aeda40bf3adf597ecc173
wsudo-tie source
wsudo create a administrator wsudo. administrator wsudo create TrustedInstaller process:
In Windows, similar to sudo is the TrustedInstaller service, and the TrustedInstaller service runs the TrustedInstaller.
Thanks for sharing your detailed thoughts @fcharlie. It turns-out that when considering a sudo-like feature as part of an operating system like Windows, that there are a lot of edge cases, and threat model issues to sift through and resolve. Providing a sudo-like capability requires a great deal of care to make sure that one doesn't, for example, accidentally introduce a weakness or vulnerability into the system, while also ensuring that the solution provides sufficient utility and behaves as users would expect.
Do bear with us - we will be taking a more detailed look into this feature request in the future, once we have the resources & intent necessary to perform the detailed research and analysis.
Is there anything that the community can do to work with you to help get those resources assigned? Perhaps there's a uservoice issue which can be up-voted, etc.?
I will create a new POC (Prove Of Concept) project and push to GitHub recently. (With elevation and drop right support.)
I think sudo-like implementations in windows should be different from implementations in POSIX. So I think it is OK for this project to add some features which NSudo (https://github.com/M2Team/NSudo, the project created by myself) have.
Would having elevated profiles be something to consider in the meantime?
This will likely depend on ConPTY or something,
Did ConPTY give us what we need?
Lets be realistic, sudo is a solution but not the solution. I suspect 5-nines of sudo files contain
${USER} ALL=NOPASSWD: ALL
The Windows security model is - in principle - richer and more fine grained than the Linux model, but like the registry, it went too long without an authority to manage it.
But MS security is impossibly difficult to navigate with extant tools, because they've never thought to treat it as a graph or establish a formal control over their own introduction/use of ACLs.
And you can see this in the way that even with contemporary additions to Windows, it's very rare to see ACLs more refined than "allow"/"deny". Windows CLI tools typically require you to have the same privileges to read as to write, because no developer at MS wants to waste their time doing the code-archaeology to find the set of elsewhere-in-windows ACLs that apply to the thing they're adding.
So the notion of MS adding cli-sudo is terrifying for multiple reasons: it will be a primary vector for attacks because of people setting nopasswd: all
; the lack of an MS ACL-czar will result in every MS team adding "handy", negligibly documented, weirdly interconnected/dependent ACLs with unintended side-effects that become major attack vectors; and in order to do anything that is not nopasswd: all
you are going to have a thousand line config file so complex and confusing that you will _wish_ it just xml and yaml with some jinja templates and a slab of ruby for good effect to make it _easier_ to read.
We're talking about a system that has the fine granularity of 'Full Control, Read & Execute, List contents, Read, Write, Special Permissions', and yet resorts to an orthogonal ACL system for ACL configuration which has a setting Local Computer Policy > Computer Configuration > Windows Settings > Security Settings > Local Policies > Security Options > Accounts : Administrator Account Status
which is _disabled by default_ and in whose explanation text explicitly states:
TL;DR: Windows 10 security systems are excellent, Windows 10 security baggage is the devil's own least favorite sex toy and Windows 10 cli sudo without some other preparatory work on Windows security infra is likely to be the equivalent of typing "thisisunsafe" into a Chrome window telling you that the site you're trying to access is unsafe...
@bgshacklett
Re: "Is there anything that the community can do to work with you to help get those resources assigned"
Nothing right now - any supported solution in this space will require OS plumbing. We do continue to track this ask though, and are driving a series of conversations. Stay tuned.
@dadpolice You can run Terminal elevated with Admin rights by right clicking and hitting "Run as Administrator":
HOWEVER, note that elevation is not the same as running as a different user - when you run elevated, you still run with your identity, but with additional (Admin) rights.
@bitcrazed I am aware of that. I am talking about running as a different user account, the specific issue that was raised in #2200, closed as "duplicate," yet appears to be completely ignored in this discussion.
Yeah, sorry - that's not a supported scenario for modern/UWP apps.
Could you describe your use-case - why you want to run Terminal from one user account as a different user identity?
@bitcrazed I have a standard, unprivileged user account that I use to log into my computer, plus an admin account that I use to manage various environments. If "run as" isn't supported in UWP apps then Terminal will never be usable to me. It's unclear why you chose to make this a UWP app.
Is it necessary for the Terminal to run as another user or do you just need to be able to run Administrative commands from PowerShell or your preferred shell? Most built-in PowerShell cmdlets support passing in other credentials which can be retrieved easily with -Credential $(Get-Credential)
. Worst case, if a command doesn't directly support passing in credentials, using Invoke-Command
as a wrapper, with explicit credentials is another option.
It's not "necessary" but it's far nicer from a convenience perspective to simply have a PowerShell window running under my admin credentials and use it when necessary, rather than adding -Credential or Invoke-Command to every single command I run. The "workaround" here is to just not use Terminal if it doesn't support basic features.
@dadpolice Could I ask what you're trying to achieve by running a standard user account and then running some apps under the identity of an admin? This is basically what UAC has provided since Vista, but with smoother UX, and better OS & Tool support.
@bitcrazed You misunderstand. What I refer to as my "admin account" is not used for administrator privileges on my local device. It's used for managing servers/applications/environments/etc. that my standard account does not have access to. This is not an uncommon use case.
Again, what does having your "admin" account separate from your logged-in user account give you? Not saying its wrong or uncommon, trying to understand your use case.
Whilst this kind of setup was common on XP, it is now increasingly rare - I've not seen someone do this in > 10 years now.
It limits the rights my main account has so that if that account is compromised an attacker can do less damage with it. This is absolutely not rare, I have several friends and relatives who work in IT at other companies and they all have the same or similar setups.
@dadpolice do you mix match the (your) admin account with administrative privileges?
You can do all administrative stuff with administrative privileges via UAC. You do not need THE administrator account for that.
Simple restrict your user account rights and use UAC (elevated privileges) and do admin stuff with this. The administrative account is not necessary for that.
@DoCode I don't think you understand the use case I am describing.
@dadpolice ok. Sorry!
@DoCode I have the same setup as @dadpolice at my workplace.
The admin account has Domain Admin permissions, that means it has full permissions to hundreds of machines and company resources so it's not the kind of login you use for day to day computer use.
A simple example would be ransomware which if run from my domain admin account could encrypt the data of every computer on the network without even requiring elevation which is a massive risk.
Thus I have a regular account which is a local machine admin and my domain admin account which I only use when managing other computers/servers.
@dafzor thanks for your explanation! Now I understand your use cases!
@dadpolice - Again, you're manually doing what UAC provides: UAC removes the admin rights from your user token, even if you're a local admin. Then when you run a process "elevated"/admin-mode, the admin rights are added (if you pass/accept UAC prompts).
Thus, even if malware was to try to attack your user account, it wouldn't be able to do admin-only things on your machine because you'll need to manually permit it to do so.
Where this use-case ___IS___ more common is in an enterprise / online-services environment as described by @dafzor in which you might want to run a separate account with domain-admin rights from which you administer (potentially) many machines/environments.
But in such environments, it's generally wise not to use runas
since you'll then be running an app from a potentially lower integrity environment (your local non-admin desktop) under the identity of an account with considerable power and rights.
For example, imagine you ran Terminal (or any other app) in your std. user environment as domain/admin and that app was subjected to keyboard/mouse input injection attacks, etc. from malware running in your std. user account.
If you're going to need to use a domain admin or similar type of broad-rights account, it'd be wise to consider instead using a Secure Access Environment via Remote Desktop. For example, a Secured Terminal Services machine that's HEAVILY monitored, restricted, and protected with biometric/smart-card etc. access.
@bitcrazed Rich, the use case I am trying to describe is virtually identical to what @dafzor explained. The only difference would be that my secondary account is not literally a domain admin but simply is granted access to machines/environments that my primary account does not have access to. UAC is completely irrelevant to this discussion.
I'm not going to keep arguing with you about this use case because it is incredibly common and it's not going away any time soon. If you weren't aware of this then you have completely failed to grasp the needs of the enterprise users this application is supposed to serve. If Run As support is never going to be add to Terminal, just say that, I have no problem with not using Terminal. It's not going to kill me to keep using PowerShell.exe as I always have.
I'm not going to keep arguing with you about this use case because it is incredibly common
In a way, it's equivalent to the following pseudo function:
Function ElevatedExecute-Command
{
Param([String] $Username = "Administrator", [String] $Command, [String] $Credential)
if (!$Credential) {
$Credential = Get-Credential $Username
}
Invoke-Command -Computer LocalHost -Credential $Credential $Command
}
But there's also a lot more to it than that (since it can facilitate allowing some users to passwordlessly execute some commands). And, it's basically how everything, everywhere, that isn't in a container, is done.
sudo rm -rf bitcrazed
Please do not delete my PM. I will have to restore him from a backup. 馃槃
It's alright, I wasn't in the sudoers group :)
null
For example, imagine you ran Terminal (or any other app) in your std. user environment as domain/admin and that app was subjected to keyboard/mouse input injection attacks, etc. from malware running in your std. user account.
If you're going to need to use a domain admin or similar type of broad-rights account, it'd be wise to consider instead using a Secure Access Environment via Remote Desktop. For example, a Secured Terminal Services machine that's HEAVILY monitored, restricted, and protected with biometric/smart-card etc. access.
What protection is in place which prevents the afore-mentioned keyboard/mouse injection attacks from passing through an RDP session?
I'm just gonna chime in here in support of exactly what @dadpolice is trying to say. I came here looking for the answer to this exact issue, which is the ability to run as different user for Terminal the way I do with Powershell everyday. This is EXTREMELY common, and we have internal enterprise stuff which checks that you are logged in with you admin (NOT LOCAL ADMIN - domain administrative) account. So you run as different user a powershell prompt. It's been this way for many years, and is not going away any time soon. We have local User management tools that have been built that also requires this for helpdesk people, who run these tools as their helpdesk admin account.
I'm genuinely surprised there seems to be so much confusion over this as its been standard behavior in Enterprises for as long as I've been in IT (over 15 years). So if Terminal will never support this, please just let us know - but as someone who's been digging into UWP development as well, this will greatly limit the usability of UWP in the Enterprise if it won't support such a standard operation.
as someone who's been digging into UWP development as well, this will greatly limit the usability of UWP in the Enterprise if it won't support such a standard operation.
@bitcrazed Make sure the store team hears this ask. This is something that we can't solve on our own, put we can certainly try and push the store team on.
Appreciate everyone's feedback here. Don't get me wrong though: I have seen and used this pattern for almost 20 years too, but I've seen it decline in use considerably over the last several years.
@bgshacklett The RDP client has various layers of protection to prevent arbitrary keyboard and mouse injection attacks, and features like enforceable biometric/security-device multi-factor authentication, enforced session timeout, etc. to protect/reduce-impact from a variety of attacks.
Alas, the limitation we're primarily facing is that UWP apps don't support Runas
Now, all this said, you're right that the Terminal as it stands today doesn't support runas scenarios, and we should explore whether we can.
I've created issue #4217 to track the runas ask. We'll discuss with a bunch of teams internally - UWP runtime team, security, etc. and see what we can come up with. We'll update #4217 once we have some info to share.
The proposal is well written and fully supported. Now you can only use Runas in Windows Terminal to elevate permissions in a new window, which is very inconvenient in both PowerShell and Windows Terminal. Sudo in Linux is very simple and convenient, I hope it can be unified with this experience.
Most helpful comment
While we're not able to give you a firm timeline right now, I can echo @zadjii-msft's comment - we are sooooooooo keen for "Add sudo" to bubble up our priority list so we can get to work on it :)
As with anything to do with security, we will be working with the Windows core security & management teams to make sure that we "do it right".