Theo de Raadt proposed to include a new mechanism in OpenBSD to reduce the attack surface, implemented through the enhancement of the system call openat. Patches for additional flags for openat and open, which limit the ability to traverse to parent directories through "../" and access using absolute paths, have been prepared for the kernel, libc, and some applications from the base system. The changes have not yet been included in OpenBSD-current and are currently under discussion among developers.
The family of system calls openat(2) works as an analogue of open(2), except that if a relative path is specified in the "path" parameter, the file being opened is determined relative to the directory associated with the file descriptor "fd", rather than the current working directory. If an absolute path is passed to openat, for example: int dirfd = open("/tmp", O_RDONLY | O_DIRECTORY); int hfd = openat(dirfd, "/etc/hosts", O_RDONLY);
The openat() function will ignore "dirfd", and consequently, the absolute path will be handled in the usual way.
Therefore, replacing open() with openat() does not, by itself, enhance the security of the program. Such a call can speed up path resolution but does not limit access to the filesystem. The flags preventing absolute paths (e.g., RESOLVE_BENEATH and/or RESOLVE_IN_ROOT for openat2 in Linux) do not guarantee protection: the programmer must add them to all appropriate calls, and if the attacker takes control of the process, they can exploit other paths for opening files.
During the work on the openrsync utility, Theo encountered the need to limit its capabilities for traversing the filesystem, but it was not possible to do this using the unveil() and pledge() functions. Thus, the idea arose for a mechanism similar to openat(), but with security properties that complement pledge/unveil or even function in their absence.
Osnovna ideja je da se ograničenja učine delom samog deskriptora direktorijuma. U tu svrhu, predlaže se oznaka F_BELOW, koja se može postaviti putem fcntl(), ili oznaka O_BELOW za open(). Ograničen na ovaj način, deskriptor „dirfd“ će omogućavati samo prelaze niz stablo direktorijuma: pozivi openat() s apsolutnom putanjom ili s prelazom nagore kroz „..“ će završiti greškom ENOENT. U slučaju napada koji dovodi do izvršenja koda, tabela fiškalnih deskriptora procesa će sadržati manje funkcionalne „dirfd“, što će ograničiti površinu napada.
Izvor: opennet.ru
