OpenSSH 9.2: stricter default sandbox policy in OpenSSH client on OpenBSD
Tags: openbsd, openssh, security
Published: 2023-02-16 14:51:30



[The Release Notes](https://www.openssh.com/releasenotes.html) for OpenSSH 9.2 (published on 2023-02-02) mentioned “stricter default sandbox policy” by “_disabling the ~C command-line that was previously enabled by default_.”


> Turning off the command-line allows platforms that support sandboxing of the ssh client (currently only OpenBSD) to use a stricter default sandbox policy.


## TL;DR
In summary, the OpenSSH client sandboxing feature on OpenBSD uses a combination of techniques such as pledge, unveil, chroot jail, and privilege separation to restrict the access of the OpenSSH client process to the system resources, directories and privileged operations. This helps to reduce the risk of security vulnerabilities in the OpenSSH client process from causing damage to the system. Disabling command-line escape makes it more secure. This article describes the context.



##What is OpenBSD client sandboxing?
OpenSSH client sandboxing is a security feature implemented in OpenSSH on the OpenBSD operating system. The goal of this feature is to isolate the OpenSSH client process from the rest of the system to limit the damage that could be caused by potential security vulnerabilities.


##How does it work?
OpenSSH client sandboxing is achieved through a combination of different techniques. First, the OpenSSH client process is run in a restricted environment using the "ssh-agent" program. This environment is created using the "pledge" and "unveil" system calls, which limit the system resources that the OpenSSH client process can access. For example, the `pledge()` system call restricts the system calls that the OpenSSH client process can make, while the `unveil()` system call limits the files and directories that the OpenSSH client process can access.

Second, the OpenSSH client process is executed in a chroot jail, which restricts the directories that the process can access. This ensures that even if the OpenSSH client process is compromised, the attacker will not be able to access other parts of the system.

Finally, the OpenSSH client sandboxing feature uses privilege separation to separate the privileged and non-privileged parts of the OpenSSH client process. This ensures that if an attacker gains access to the non-privileged part of the OpenSSH client process, they will not be able to execute privileged operations.

##OpenSSH client pledge() example
The OpenSSH client on OpenBSD uses `pledge()` to restrict the operations that can be performed by the process. The `pledge()` call is made in the `ssh_init()` function in the file `ssh.c`.

Here's an excerpt from the OpenSSH client code in `ssh.c` that demonstrates how `pledge()` is used to set the restricted-service operating mode:

```
#ifdef HAVE_PLEDGE
   if (pledge("stdio rpath wpath cpath unix inet dns recvfd tty proc exec id", NULL) == -1) {
        error("pledge(): %s", strerror(errno));
        cleanup_exit(255);
    }
#endif
```


This call to `pledge()` sets the following promises:

- stdio: permits use of standard I/O functions
- rpath: permits read-only access to the file system for specific functions
- wpath: permits write access to the file system for specific functions
- cpath: permits creation of files and directories
- unix: permits access to Unix domain sockets
- inet: permits access to Internet sockets
- dns: permits access to DNS functions
- recvfd: permits receipt of file descriptors
- tty: permits access to the tty
- proc: permits access to process-related functions
- exec: permits execution of other programs
- id: permits access to identity-related functions

The second argument to `pledge()` is set to `NULL`, which means that the current promises are not changed.


By calling `pledge()` with these promises, the OpenSSH client is restricted to only the operations needed to perform SSH connections, and other operations that could be exploited by attackers are disallowed.

##OpenBSD httpd web server `pledge()` example
Here's another example of OpenBSD code that uses `pledge()` to create a restricted-service operating mode. This code is from the OpenBSD httpd web server:

```
int main(int argc, char **argv)
{
    /* ... */

#ifdef __OpenBSD__
    /* enter the pledge */
    if (pledge("stdio rpath wpath cpath inet dns", NULL) == -1)
        err(1, "pledge");
#endif

    /* ... */
}

```
This call to `pledge()` sets the following promises:

- stdio: permits use of standard I/O functions
- rpath: permits read-only access to the file system for specific functions
- wpath: permits write access to the file system for specific functions
- cpath: permits creation of files and directories
- inet: permits access to Internet sockets
- dns: permits access to DNS functions


Note that this call to `pledge()` is conditional on the OpenBSD operating system being detected, using the OpenBSD preprocessor macro. This is because `pledge()` is an OpenBSD-specific system call and is not available on other operating systems.


Again, by calling `pledge()` with these promises, the httpd web server is restricted to only the operations needed to serve web pages, and other operations that could be exploited by attackers are disallowed.