Skip to content

Commit

Permalink
Add article about securing restricted sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
sdwheeler committed Oct 10, 2023
1 parent 4504512 commit 1e68c40
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
description: This article explains how to secure a restricted PowerShell session that is used for secure remote access.
ms.date: 10/10/2023
title: Securing a restricted PowerShell remoting session
---
# Securing a restricted PowerShell remoting session

There are scenarios where you want to host a PowerShell session that, for security reasons, has been
limited to a subset of PowerShell commands.

By definition, a restricted session is one where `Import-Module` isn't allowed to be used. There may
be other limitations, but this is the primary requirement. If the user can import a module, then
they can run anything they want.

Examples of restricted sessions include:

- Just-Enough-Administration (JEA)
- Custom restricted remoting implementations such as the Exchange and Teams modules

For most system administrators, JEA provides the best experience for creating restricted sessions
and should be your first choice. For more information about JEA, see the [JEA Overview][01].

## Recommendations for custom session implementations

If your scenario requires a custom implementation, then you should follow these recommendations.

### Limit the use and capabilities of PowerShell providers

Review how the allowed providers are used to ensure that you don't create vulnerabilities in your
restricted session implementation.

> [!WARNING]
> Don't allow the **FileSystem** provider. If users can write to any part of the file system, it's
> possible to completely bypass security.
>
> Don't allow the **Certificate** provider. With the provider enabled, a user could gain access to
> stored private keys.
### Don't allow commands that can create new runspaces

> [!WARNING]
> The `*-Job` cmdlets can create new runspaces without the restrictions.
### Don't allow the `Trace-Command` cmdlet.

> [!WARNING]
> Using `Trace-Command` brings all traced commands into the session.
### Don't create your own proxy implementations for the restricted commands

PowerShell has a set of proxy commands for restricted command scenarios. These proxy commands
ensure that input parameters can't compromise the security of the session. The following commands
have restricted proxies:

- `Exit-PSSession`
- `Get-Command`
- `Get-FormatData`
- `Get-Help`
- `Measure-Object`
- `Out-Default`
- `Select-Object`

If you create your own implementation of these commands, you may inadvertently allow users to run
code that prohibited by the JEA proxy commands.

You can run the following command to get a list of restricted commands:

```powershell
$commands = [System.Management.Automation.CommandMetadata]::GetRestrictedCommands(
[System.Management.Automation.SessionCapabilities]::RemoteServer
)
```

You can examine the restricted proxy commands by using the following command:

```powershell
$commands = [System.Management.Automation.CommandMetadata]::GetRestrictedCommands(
[System.Management.Automation.SessionCapabilities]::RemoteServer
)
$getHelpProxyBlock = [System.Management.Automation.ProxyCommand]::Create($commands['Get-Help'])
```

### Configure the session to use NoLanguage mode

PowerShell `NoLanguage` mode disables the PowerShell scripting language completely. You can't run
scripts or use variables. You can only run native commands and cmdlets.

For more information about language modes, see [about_Language_Modes][03].

### Don't allow the debugger to be used in the session

By default, the PowerShell debugger runs code in `FullLanguage` mode. Set the
**UseFullLanguageModeInDebugger** property in the **SessionState** to false.

For more information, see [UseFullLanguageModeInDebugger][02].

<!-- link references -->
[01]: ../../learn/remoting/jea/overview.md
[02]: /dotnet/api/system.management.automation.sessionstate.usefulllanguagemodeindebugger?#system-management-automation-sessionstate-usefulllanguagemodeindebugger
[03]: /powershell/module/microsoft.powershell.core/about/about_language_modes
162 changes: 102 additions & 60 deletions reference/docs-conceptual/learn/remoting/jea/security-considerations.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
description: Since JEA allows these users to run admin commands without having full admin access, you can then remove those users from highly privileged security groups.
ms.date: 11/16/2022
description: >-
Since JEA allows these users to run administrative commands without having full administrator
access, you can then remove those users from highly privileged security groups.
ms.date: 10/10/2023
title: JEA Security Considerations
---
# JEA Security Considerations
Expand All @@ -9,15 +11,14 @@ JEA helps you improve your security posture by reducing the number of permanent
your machines. JEA uses a PowerShell session configuration to create a new entry point for users to
manage the system. Users who need elevated, but not unlimited, access to the machine to do
administrative tasks can be granted access to the JEA endpoint. Since JEA allows these users to run
admin commands without having full admin access, you can then remove those users from highly
privileged security groups.
administrative commands without having full administrator access, you can then remove those users
from highly privileged security groups.

## Run-As account

Each JEA endpoint has a designated **run-as** account. This is the account under which the
connecting user's actions are executed. This account is configurable in the
[session configuration file][05], and the account you choose has a significant bearing on the
security of your endpoint.
Each JEA endpoint has a designated **run-as** account under which the connecting user's actions are
executed. This account is configurable in the [session configuration file][03], and the account you
choose has a significant bearing on the security of your endpoint.

**Virtual accounts** are the recommended way of configuring the **run-as** account. Virtual accounts
are one-time, temporary local accounts that are created for the connecting user to use during the
Expand All @@ -26,38 +27,38 @@ destroyed and can't be used anymore. The connecting user doesn't know the creden
virtual account. The virtual account can't be used to access the system via other means like
Remote Desktop or an unconstrained PowerShell endpoint.

By default, virtual accounts belong to the local **Administrators** group on the machine. This gives
them full rights to manage anything on the system, but no rights to manage resources on the network.
When authenticating with other machines, the user context is that of the local computer account, not
the virtual account.
By default, virtual accounts are members of the local **Administrators** group on the machine. This
membership gives them full rights to manage anything on the system, but no rights to manage
resources on the network. When the user connects to another machines from the JEA session, the user
context is that of the local computer account, not the virtual account.

Domain controllers are a special case since there isn't a local **Administrators** group. Instead,
virtual accounts belong to **Domain Admins** and can manage the directory services on the domain
controller. The domain identity is still restricted for use on the domain controller where the JEA
session was instantiated. Any network access appears to come from the domain controller computer
object instead.

In both cases, you may explicitly define which security groups the virtual account belongs to. This
is a good practice when the task can be done without local or domain admin privileges. If you
already have a security group defined for your admins, grant the virtual account membership to that
group. Virtual account group membership is limited to local security groups on workstation and
member servers. On domain controllers, virtual accounts must be members of domain security groups.
Once the virtual account has been added to one or more security groups, it no longer belongs to the
default groups (local or domain admins).
In both cases, you may assign the virtual account to specific security groups, especially when the
task can be done without local or domain administrator privileges. If you already have a security
group defined for your administrators, grant the virtual account membership to that group. Group
membership for Virtual accounts is limited to local security groups on workstation and member
servers. On domain controllers, virtual accounts must be members of domain security groups. Once the
virtual account has been added to one or more security groups, it no longer belongs to the default
groups (local or domain administrators).

The following table summarizes the possible configuration options and resulting permissions for
virtual accounts:

| Computer type | Virtual account group configuration | Local user context | Network user context |
| ---------------------------- | ----------------------------------- | ------------------------------------------------------- | -------------------- |
| Domain controller | Default | Domain user, member of '*DOMAIN*\Domain Admins' | Computer account |
| Domain controller | Domain groups A and B | Domain user, member of '*DOMAIN*\A', '*DOMAIN*\B' | Computer account |
| Member server or workstation | Default | Local user, member of '*BUILTIN*\Administrators' | Computer account |
| Member server or workstation | Local groups C and D | Local user, member of '*COMPUTER*\C' and '*COMPUTER*\D' | Computer account |

When you look at security audit events and application event logs, you see that each JEA user
session has a unique virtual account. This unique account helps you track user actions in a JEA
endpoint back to the original user who ran the command. Virtual account names follow the format
| Domain controller | Default | Domain user, member of `<DOMAIN>\Domain Admins` | Computer account |
| Domain controller | Domain groups A and B | Domain user, member of `<DOMAIN>\A`, `<DOMAIN>\B` | Computer account |
| Member server or workstation | Default | Local user, member of `BUILTIN\Administrators` | Computer account |
| Member server or workstation | Local groups C and D | Local user, member of `<COMPUTER>\C` and `<COMPUTER>\D` | Computer account |

When you look at Security audit and Application event logs, you see that each JEA user session has a
unique virtual account. This unique account helps you track user actions in a JEA endpoint back to
the original user who ran the command. Virtual account names follow the format
`WinRM Virtual Users\WinRM_VA_<ACCOUNTNUMBER>_<DOMAIN>_<sAMAccountName>` For example, if user
**Alice** in domain **Contoso** restarts a service in a JEA endpoint, the username associated with
any service control manager events would be `WinRM Virtual Users\WinRM_VA_1_contoso_alice`.
Expand All @@ -67,19 +68,18 @@ network resources in the JEA session. For example, when a JEA endpoint is used t
a REST API service hosted on a different machine. It's easy to write functions to invoke the REST
APIs, but you need a network identity to authenticate with the API. Using a group-managed service
account makes the second hop possible while maintaining control over which computers can use the
account. The effective permissions of the gMSA are defined by the security groups (local or domain)
to which the gMSA account belongs.
account. The security group (local or domain) memberships of the gMSA defined the effective
permissions for the gMSA account.

When a JEA endpoint is configured to use a gMSA, the actions of all JEA users appear to come from
the same gMSA. The only way to trace actions back to a specific user is to identify the set of
commands run in a PowerShell session transcript.

**Pass-thru credentials** are used when you don't specify a **run-as** account. PowerShell uses the
connecting user's credential to run commands on the remote server. This requires you to grant the
connecting user direct access to privileged management groups. This configuration is **not**
recommended for JEA. If the connecting user already has admin privileges, they can avoid JEA and
manage the system via other, unconstrained means. For more information, see the section below on how
[JEA doesn't protect against admins][02].
**Pass-through credentials** are used when you don't specify a **run-as** account. PowerShell uses
the connecting user's credential to run commands on the remote server. To use pass-through
credentials, you must grant the connecting user direct access to privileged management groups. This
configuration is **NOT** recommended for JEA. If the connecting user already has administrator
privileges, they can bypass JEA and manage the system using other access methods.

**Standard run-as accounts** allow you to specify any user account under which the entire PowerShell
session runs. Session configurations using fixed **run-as** accounts (with the `-RunAsCredential`
Expand All @@ -93,7 +93,7 @@ back to specific users and lacks support for mapping users to roles.

As with regular PowerShell remoting endpoints, each JEA endpoint has a separate access control list
(ACL) that controls who can authenticate with the JEA endpoint. If improperly configured, trusted
users may not be able to access the JEA endpoint and untrusted users may have access. The WinRM ACL
users may not be able to access the JEA endpoint, and untrusted users may have access. The WinRM ACL
doesn't affect the mapping of users to JEA roles. Mapping is controlled by the **RoleDefinitions**
field in the session configuration file used to register the endpoint.

Expand Down Expand Up @@ -124,12 +124,12 @@ CONTOSO\JEA_Lev2 AccessAllowed
To change which users have access, run either
`Set-PSSessionConfiguration -Name 'MyJEAEndpoint' -ShowSecurityDescriptorUI` for an interactive
prompt or `Set-PSSessionConfiguration -Name 'MyJEAEndpoint' -SecurityDescriptorSddl <SDDL string>`
to update the permissions. Users need at least *Invoke* rights to access the JEA endpoint.
to update the permissions. Users need at least _Invoke_ rights to access the JEA endpoint.

It's possible to create a JEA endpoint that doesn't map a defined role to every user that has
access. These users can start a JEA session, but only have access to the default cmdlets. You can
audit user permissions in a JEA endpoint by running `Get-PSSessionCapability`. For more information,
see [Auditing and Reporting on JEA][03].
see [Auditing and Reporting on JEA][02].

## Least privilege roles

Expand All @@ -153,39 +153,81 @@ see what applications are running on the system and `Stop-Process` to kill appli
responding. However, this entry also allows `Start-Process`, which can be used to start up an
arbitrary program with full administrator permissions. The program doesn't need to be installed
locally on the system. A connected user could start a program from a file share that gives the user
local admin privileges, runs malware, and more.
local administrator privileges, runs malware, and more.

A more secure version of this same role capability would look like:

```powershell
@{
VisibleCmdlets = 'Microsoft.PowerShell.Management\Get-Process', 'Microsoft.PowerShell.Management\Stop-Process'
VisibleCmdlets = 'Microsoft.PowerShell.Management\Get-Process',
'Microsoft.PowerShell.Management\Stop-Process'
}
```

Avoid using wildcards in role capabilities. Be sure to regularly
[audit effective user permissions][04] to understand which commands are accessible to the user.
Avoid using wildcards in role capabilities. Be sure to regularly audit effective user permissions to
see which commands are accessible to a user. For more information, see the _Check effective rights_
section of the [Auditing and Reporting on JEA][02] article.

## Best practice recommendations

The following are best practice recommendations to ensure the security of your JEA endpoints:

### Limit the use and capabilities of PowerShell providers

Review how the allowed providers are used to ensure that you don't create vulnerabilities in your
configured session.

> [!WARNING]
> Don't allow the **FileSystem** provider. If users can write to any part of the file system, it's
> possible to completely bypass security.
>
> Don't allow the **Certificate** provider. With the provider enabled, a user could gain access to
> stored private keys.
### Don't allow commands that can create new runspaces.

> [!WARNING]
> The `*-Job` cmdlets can create new runspaces without the restrictions.
### Don't allow the `Trace-Command` cmdlet.

> [!WARNING]
> Using `Trace-Command` brings all traced commands into the session.
### Don't create your own proxy implementations for the _restricted commands_.

PowerShell has a set of proxy commands for restricted command scenarios. These proxy commands
ensure that input parameters can't compromise the security of the session. The following commands
have restricted proxies:

- `Exit-PSSession`
- `Get-Command`
- `Get-FormatData`
- `Get-Help`
- `Measure-Object`
- `Out-Default`
- `Select-Object`

If you create your own implementation of these commands, you may inadvertently allow users to run
code that prohibited by the JEA proxy commands.

## JEA doesn't protect against admins

One of the core principles of JEA is that it allows non-admins to do some admin tasks. JEA doesn't
protect against users who already have administrator privileges. Users who belong **Domain Admins**,
local **Administrators**, or other highly privileged groups can circumvent JEA's protections via
another means. For example, they could sign in with RDP, use remote MMC consoles, or connect to
unconstrained PowerShell endpoints. Also, local admins on a system can modify JEA configurations to
allow additional users or change a role capability to extend the scope of what a user can do in
their JEA session. It's important to evaluate your JEA users' extended permissions to see if there
are other ways to gain privileged access to the system.

A common practice is to use JEA for regular day-to-day maintenance and have a just-in-time,
privileged access management solution that allows users to temporarily become local admins in
emergency situations. This helps ensure users aren't permanent admins on the system, but can get
those rights if, and only when, they complete a workflow that documents their use of those
One of the core principles of JEA is that it allows nonadministrators to do some administrative
tasks. JEA doesn't protect against users who already have administrator privileges. Users who belong
**Domain Admins**, local **Administrators**, or other highly privileged groups can circumvent JEA's
protections in other ways. For example, they could sign in with RDP, use remote MMC consoles, or
connect to unconstrained PowerShell endpoints. Also, local administrator on a system can modify JEA
configurations to add more users or change a role capability to extend the scope of what a user can
do in their JEA session. It's important to evaluate your JEA users' extended permissions to see if
there are other ways to gain privileged access to the system.

In addition to using JEA for regular day-to-day maintenance, it's common to have a just-in-time
privileged access management system. These systems allow designated users to temporarily become
a local administrator only after they complete a workflow that documents their use of those
permissions.

<!-- link references -->
[01]: /powershell/module/microsoft.powershell.core/get-pssessionconfiguration
[02]: #jea-doesnt-protect-against-admins
[03]: audit-and-report.md
[04]: audit-and-report.md#check-effective-rights-for-a-specific-user
[05]: session-configurations.md
[01]: xref:Microsoft.PowerShell.Core.Get-PSSessionConfiguration
[02]: audit-and-report.md#check-effective-rights-for-a-specific-user
[03]: session-configurations.md

0 comments on commit 1e68c40

Please sign in to comment.