Theo de Raadt a propus să includă în OpenBSD un nou mecanism pentru reducerea suprafeței de atac, implementat prin extinderea funcționalităților apelului de sistem openat. Patch-urile cu implementarea unor flaguri suplimentare pentru openat și open, care limitează posibilitatea de a naviga către directoare superioare prin „/..” și de a accesa căi absolute, au fost pregătite pentru nucleu, libc, precum și pentru unele aplicații din sistemul de bază. Modificările nu sunt încă incluse în OpenBSD-current și sunt în discuție printre dezvoltatori.
Familia apelurilor de sistem openat(2) funcționează ca un analog al open(2), cu excepția faptului că, dacă în parametrul „path” este specificat un calea relativă, fișierul deschis este definit în raport cu directorul asociat cu descriptorul de fișier „fd”, nu față de directorul de lucru curent. Dacă se transmite un drum absolut în openat, de exemplu: int dirfd = open("/tmp", O_RDONLY | O_DIRECTORY); int hfd = openat(dirfd, "/etc/hosts", O_RDONLY);
funcția openat() va ignora „dirfd” și, ca urmare, calea absolută va fi tratată în mod obișnuit.
Prin urmare, înlocuirea open() cu openat() nu îmbunătățește în mod inerent securitatea programului. O astfel de apel poate accelera analizarea căii, dar nu limitează accesul la sistemul de fișiere. Flagurile care interzic căile absolute (de exemplu, RESOLVE_BENEATH și/sau RESOLVE_IN_ROOT pentru openat2 în Linux) nu garantează protecția: programatorul trebuie să le adauge la toate apelurile potrivite, iar în cazul controlului procesului de către un atacator, acesta poate folosi alte căi pentru a deschide fișiere.
Pe parcursul lucrului la utilitarul openrsync, Theo a avut nevoie să limiteze capacitățile acestuia de a naviga în sistemul de fișiere, dar nu a fost posibil să facă acest lucru prin metodele unveil() și pledge(). Atunci a apărut ideea unui mecanism similar cu openat(), dar cu proprietăți de securitate care completează pledge/unveil sau chiar funcționează în absența acestora.
Ideea principală este de a face restricțiile parte din descriptorul de catalog în sine. Pentru aceasta, se propune o flag F_BELOW, care poate fi setată prin fcntl(), sau o flag O_BELOW pentru open(). Un astfel de descriptor „dirfd” restricționat va permite doar navigarea în jos în arborii de directoare: apelurile openat() cu un drum absolut sau cele cu navigare în sus prin „..” vor eșua cu eroarea ENOENT. În cazul unui atac care duce la executarea codului, tabela descriptorilor de fișiere a procesului va conține mai puțini „dirfd” funcționali, ceea ce va limita suprafața de atac.
Sursa: opennet.ro
