DEV Community

Pawel Suchanecki
Pawel Suchanecki

Posted on

OpenSSH 9.2: stricter default sandbox policy in OpenSSH client on OpenBSD

The Release Notes 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
Enter fullscreen mode Exit fullscreen mode

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

    /* ... */
}

Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)