terminal
terminal copied to clipboard
Sudo/command line only elevation?
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.
- As Windows command line functionality improves to the point that the system can be used remote/headless, this is becoming more of a necessity than an annoyance. Actually, this really comes down to having an official SSH client: SSH connections have to open as Admin, potential security hole.
- This is not some black magic thing or something that needs a UAC redesign or kernel work. I've experimented a little, and you can create a local service running as the system account which will give you elevated processes from the command line. I didn't pursue this any further though, because I don't have the time to commit to securing and testing the service, but I at least know it's doable.
- Even if I did want to publish a fully-featured sudo service, many organizations are not going to trust a third-party utility that is that big of a potential security hole, and it's unlikely the official SSH distribution would come configured for it, so now we're back at point one again.
- There is auto-elevation built into UAC, but only for the Windows publisher. So if this was a system utility, it's not even necessary to run it as a separate service.
- I think for the vast majority of users, this is entirely unnecessary, and I'd be fine with something that's enabled as a part of dev mode or when installing SSH. Those two cases do need it though.
- With WSL now we have a weird [restricted token, elevated token] x [regular account, root] scenario going on, where you have to be in the right kind of command prompt to get the correct privileges. If we had Windows sudo, I don't think it'd be too hard to unify it with the WSL sudo command.
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’s currently impossible to get the STDOUT, STDERR or STDIN of an elevated process from a non‑elevated 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?
Premise
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.
Linux sudo internal
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:

Windows sudo design and ideas
Use UAC to grant administrator privileges from standard users in Windows. The process is as follows ShellExecute Internals::
- AppInfo goes and talks to the Local Security Authority to get the elevated token of the logged in user of Session 1.
- AppInfo loads up a STARTUPINFOEX structure (new to Vista), and calls the brand new Vista API InitializeProcThreadAttributeList() with room for one attribute.
- OpenProcess() is called to get a handle to the process that initiated the RPC call.
- UpdateProcThreadAttribute() is called with
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, and uses the handle retrieved in step 3. - CreateProcessAsUser() is called with
EXTENDED_STARTUPINFO_PRESENTand the results of steps 1 and 4. - DeleteProcThreadAttributeList() is called.
- Results are gathered, and handles are cleaned up.
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:

End
In Windows, similar to sudo is the TrustedInstaller service, and the TrustedInstaller service runs the TrustedInstaller.
Reference
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.
#2200 was closed as a duplicate of this issue but I don't really see that specific request - the ability to run Terminal as another user - being discussed here. Is anyone actively looking into that issue as part of this issue, and if not, why was #2200 closed? Frankly, the inability to run Terminal as my admin account renders it functionally useless for my day to day job, and I find it unlikely that there's only a few of us impacted this way. I understand that this is largely a limitation of UWP/Store apps as a whole, but that just makes me wonder why this was built as a Store app to begin with.
@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.