SSH Command Restrictions
When SSH command restrictions are set, users may only perform whitelisted commands. SSH command restrictions are configured as white-list glob or regular-expression patterns.
You can define whitelists per target SSH account. Each target SSH account may have:
- A default whitelist. All users with access to the account may perform these whitelisted commands.
- Additional role-based whitelists. Use these to allow users with certain roles to perform additional commands.
Users can perform any command that is allowed by the default whitelist, or by additional whitelists that match their roles.
High-level steps for enabling SSH command restrictions includes:
When SSH command restrictions are enabled for a host account, the restrictions control the following:
- SSH shell: Shell channel is terminated at PrivX server's restricted shell where user input is parsed into sequences of shell commands and each command is verified. Allowed commands are executed on the target server.
- SSH exec: The command sent in SSH protocol's exec request is verified and - if allowed then - executed on the target server.
During validation the executed command is first split into a set of normalized sub-commands. Every sub-command must match a whitelist pattern for the command to be allowed to execute.
The normalization step does the following:
- Reconstructs the statement to a one line statement
- Removes extra white space and adds white space where it is missing
- Replaces the deprecated backtick syntax with command substitution syntax
$()
- Removes trailing shell comments
Complex statements like if statements, while loops, command substitutions, etc. result into a set of sub commands that always includes the whole normalized statement and then the individual commands within the statement. For examples about complex commands and whitelist patterns, see SSH Command Restrictions.
Both normalization and pattern matching are done in the context of the target user's login-shell variant. The shell variant is configured in the PrivX host account command restrictions. PrivX supports bash
and posix
shell variants.
Allowing and blocking execution of commands generates audit events based on the host account configuration.
When to use SSH Command Restrictions
The recommended way to control what users are allowed to execute on target hosts is to implement proper access control and separation of duties using target system user accounts, groups, file system permissions and sudoer configurations. This ensures that user's permissions on the target host are same regardless of how the user connects to the target.
However, sometimes re-configuring the target server is not possible or - due to the temporary nature of the need for access - it is not feasible. In such cases the SSH command restrictions feature can be used to restrict the commands a user is allowed to execute when connecting to the target host through PrivX.
The feature can also be used when execution of commands should not be not restricted, but certain commands should trigger alerts. This can be achieved by forwarding audit events to an external SIEM system.
Managing Whitelists
You can manage SSH command whitelists under AdministrationโDeploymentโSSH Command Whitelists.
A whitelist consists of:
- A unique name
- Pattern type:
glob
orregex
- List of patterns
- Optional comment
Glob Pattern Syntax
You can use glob patterns to specify whitelisted commands.
pattern:
{ term }
term:
`*` matches any sequence of non-separator characters
`**` matches any sequence of characters
`?` matches any single non-separator character
`[` [ `!` ] { character-range } `]`
character class (must be non-empty)
`{` pattern-list `}`
pattern alternatives
c matches character c (c != `*`, `**`, `?`, `\`, `[`, `{`, `}`)
`\` c matches character c
character-range:
c matches character c (c != `\\`, `-`, `]`)
`\` c matches character c
lo `-` hi matches character c for lo <= c <= hi
pattern-list:
pattern { `,` pattern }
comma-separated (without spaces) patterns
Regular Expression Syntax
Regular expressions provide a more complex and powerful language for specifying whitelist patterns.
Regular expression patterns follow the standard golang regexp rules:
When matching against commands, the regexp patterns return a match that begins as early as possible in the input (leftmost), and among those it chooses the one that a backtracking search would have found first. This so-called leftmost-first matching is the same semantics that Perl, Python, and other implementations use, although it is implemented without the expense of backtracking.
Regular-expression patterns for whitelists must start with the start anchor ^
. Otherwise the patterns could match parts in the middle of commands, which leads to unwanted command-validation results.s
Regular expressions are inherently harder to get right than glob patterns. We recommend preferring glob patterns, and using regular expressions only for patterns that cannot be expressed with glob.
Pattern Testing
You should always verify that the patterns match only the required commands, and do not accidentally match any unwanted commands.
To test patterns, select a whitelist and expand Evaluate Patterns. Here you can specify the shell variant and type in a list of test commands. PrivX parses the whitelist patterns and evaluates the test commands. The evaluation result is displayed in the GUI.
For additional suggestions about whitelist patterns, see Common Pitfalls and Whitelist Pattern Cheat Sheet.
Enabling Command Restrictions on Host Accounts
Command restrictions are enabled per host account in the PrivX GUI, on AdministrationโHostsโHost.
Command restrictions for an account in the target host:
- Enable command restrictions: enable or disable command restrictions for the host account.
- Command whitelist: specify the default whitelist.
- Rshell variant: specify the target-account login-shell variant,
bash
orposix
. - Rshell terminal banner: optional banner to be displayed in the SSH terminal.
- Command policies
- Allow unmatched commands: Allow execution of commands that do not match any whitelist patterns.
- Audit matched commands: Generate an SSH-whitelisted-command-allowed (1801) sensitive audit event when a command matching a whitelist pattern is allowed to execute.
- Audit unmatched commands: Generate a SSH-command-blocked (1803) sensitive audit event when a command is blocked or a SSH-non-whitelisted-command-allowed (1802) when a command not matching any whitelist pattern is allowed to execute.
All audit events containing SSH commands are generated with audit-exposure: sensitive
. Default rsyslog configuration shipped in PrivX rpm will silently drop such audit events to avoid such sensitive SSH commands to be persisted to log files on the PrivX server.
For more information about sending sensitive audit events to SIEM, see Session Recording.
Differences to normal SSH Shell
PrivX restricted-shell functionality is more restricted compared to a normal SSH shell.
Environment Variables
Environment variables do not persist over multiple commands:
rshell:user@target:/home/user$ export foo=bar
rshell:user@target:/home/user$ echo $foo
rshell:user@target:/home/user$
However they are available in all commands executed on one line:
rshell:user@target:/home/user$ export foo=bar; echo $foo
bar
rshell:user@target:/home/user$
Exit Status
Exit status of previous command is not available after the command has returned. However similar to environment variables, the exit status is available in $?
in other commands executed on the same line:
rshell:user@target:/home/user$ /bin/false; echo $?
1
rshell:user@target:/home/user$
Background Processes
Processes cannot be started in the background, also processes cannot be intercepted and moved to background.
Command History and Command Completion
Target-server shell-command history is unavailable. However, the command history of ongoing SSH sessions can be browsed with up and down arrows.
Shell-command completion is unavailable.
Common Pitfalls
Testing only allowed commands
When writing whitelist patterns you should always test that the patterns do not unintentionally allow commands that should be blocked.
Allowing users to launch child shell processes
Command restrictions are applied only to the user's login shell or SSH exec command. If the whitelist allows the user to launch child shell process, then the command restrictions cannot be applied to any commands executed within the child shell process.
Ways for a user to launch a child shell process:
- Explicit command:
/bin/sh
,/bin/bash
, etc - Instruct a running program to open a shell: For example
!sh
inless
,:shell
invi
orM-x shell
inemacs
- Via
su
orsudo -i
Some programs can be started in a restricted mode which has disabled starting child shell processes. For example vi -Z
and rview
commands start vi in restricted mode where the :shell
command is disabled.
Allowing directory traversal
Too open whitelist patterns may allow users to open or modify unintended files.
For example a regex pattern ^vi -Z /etc/rsyslog\.d/.*$
would allow the following commands:vi -Z /etc/rsyslog.d/privx-syslog.conf
vi -Z /etc/rsyslog.d/../sudoers
In glob syntax the wildcard *
never matches the directory separator, but **
does. In regular expression syntax [^/]
matches all other characters except the directory separator /
, but .*
matches every character including the directory separator.
Allowing command substitutions
Command substitutions can be used for obfuscating commands.
For example the command $(echo "Y2F0IC9ldGMvcGFzc3dkCg==" | base64 -d)
executes the shell command cat /etc/passwd
. Therefore a whitelist that allows $(**)
, echo **
and base64 **
effectively allows executing any command.
Allowing user to modify scripts and execute them
Allowing commands to be executed from directories where the user has write permissions may enable the user to modify the command before executing it. This can happen for example in following ways:
- User is allowed to execute commands that modify or overwrite other allowed scripts and commands
- User is allowed to redirect command output to overwrite other allowed scripts and commands
- User is allowed to upload files and overwrite other allowed scripts and commands
The PrivX host account service options can be used to disable file transfers.
Typical editors support opening files, creating files and saving to alternate files. Allowing user to launch an editor as a privileged user may enable the user to replace binaries and scripts on the target system.
Whitelist Pattern Cheat Sheet
Simple Commands
command-a; command-b
Each command is whitelisted separately.
Example Command | ls -la; rm /tmp/foo |
Glob Pattern | ls** rm /tmp/* |
Regex Pattern | ^ls.*$ ^rm /tmp/[^/]+$ |
AND, OR, command pipelining
command-a && command-b
command-a || command-b
command-a | command-b
Commands on both sides of the operator are whitelisted separately.
Example Command | `echo foo |
Glob Pattern | echo ** tr ** |
Regex Pattern | ^echo .*$ ^tr .*$ |
Redirection
command <input >output 2>error
command <input 2>&1 >output
command <input &>output (bash only)
command >>output
command <<EOF
input-line-1
input-line-2
EOF
Complete statement and command are whitelisted separately. Each redirect is whitelisted separately.
Example Command | base64 <input.txt >output.txt |
Glob Pattern | base64** <** >** |
Regex Pattern | ^base64.*$ ^<.*$ ^>.*$ |
Glob patterns cannot be used to express character sequences that exclude redirection characters >
and <
.
Parsing of redirects has changed in PrivX 26. Now redirects are parsed as separate sub commands and need to be explicitly whitelisted.
Conditional Statements
if cond-a; then command-a; elif cond-b; then command-b; else command-c; fi
case word in pattern) command-a;; *) command-b;; esac
Conditional statement is whitelisted separately. All conditions and commands within the body are whitelisted separately.
Example Command | if /bin/true; then echo "yep" elif /bin/false; then echo "nope" else echo "unknown" fi |
Glob Pattern | if **; then **; elif **; then **; else **; fi /bin/true /bin/false echo ** |
Regex Pattern | ^if [^;]+; then .*; elif [^;]+; then .*; else .*; fi$ ^/bin/true$ ^/bin/false$ ^echo .*$ |
While and Until loops
while cond; do command-a; done
until cond; do command-a; done
Loop statement is whitelisted separately. The condition and all commands within the body are whitelisted separately.
Example Command | while /bin/true; do echo "foo"; done |
Glob Pattern | while **; do **; done /bin/true echo ** |
Regex Pattern | ^while [^;]+; do .*; done$ ^/bin/true$ ^echo .*$ |
For loops
for name in word; do command-a; done
Loop statement is whitelisted separately. Commands within the body are whitelisted separately.
Example Command | for d in /tmp/ /etc/ /usr/local/; do echo $d; done |
Glob Pattern | for **; do **; done echo ** |
Regex Pattern | ^for [^;]+; do .*; done$ ^echo .*$ |
Bash C-Style For Loop
for (( expr1; expr2; expr3 )); do command-a; done
Loop statement is whitelisted separately. Arithmetic expression is whitelisted separately. Commands within the body are whitelisted separately.
Example Command | for (( i = 0; i < 10; i = i +1 )); do echo $i; done |
Glob Pattern | for **; do **; done ((**)) echo ** |
Regex Pattern | ^for [^;]+; do .*; done$ ^\(\(.*\)\)$ ^echo .*$ |
Conditional Constructs
[ command ]
Conditional construct is whitelisted separately.
Example Command | [ -n "$foo" ] |
Glob Pattern | \[ ** \] |
Regex Pattern | ^\[ .* \]$ |
Bash style
[[ expression ]]
Conditional construct is whitelisted separately.
Example Command | [[ $foo -ge 0 ]] |
Glob Pattern | \[\[ ** \]\] |
Regex Pattern | ^\[\[ .* \]\]$ |
Command Substitution
$(command)
`command`
Command substitution and all commands are whitelisted separately.
Example Command | `$(echo "Y2F0IC9ldGMvcGFzc3dkCg==" |
Glob Pattern | $(**) echo ** base64 -d |
Regex Pattern | ^\$\(.*\)$ ^echo .*$ ^base64 -d$ |
The normalization step converts deprecated backtick syntax to $()
command substitution syntax. The whitelist patterns must always be written to match the $()
syntax.