Theo de Raadt ha proposto di includere in OpenBSD un nuovo meccanismo per ridurre la superficie d'attacco, realizzato attraverso l'estensione delle capacità della chiamata di sistema openat. Le patch con l'implementazione di ulteriori flag per openat e open, che limitano la possibilità di risalire ai cataloghi superiori tramite «/..» e fare riferimento a percorsi assoluti, sono state preparate per il kernel, libc e alcune applicazioni del sistema di base. Le modifiche non sono ancora incluse in OpenBSD-current e sono attualmente in fase di discussione tra gli sviluppatori.
La famiglia di chiamate di sistema openat(2) funziona come un'alternativa a open(2), eccetto per il fatto che se nel parametro «path» viene specificato un percorso relativo, il file aperto è definito rispetto alla directory associata al descrittore di file «fd», invece che rispetto alla directory di lavoro corrente. Se si passa a openat un percorso assoluto, ad esempio: int dirfd = open(«/tmp», O_RDONLY | O_DIRECTORY); int hfd = openat(dirfd, «/etc/hosts», O_RDONLY);
La funzione openat() ignorerà «dirfd» e, di conseguenza, il percorso assoluto verrà elaborato normalmente.
Pertanto, la sostituzione di open() con openat() di per sé non aumenta la sicurezza del programma. Tale chiamata può accelerare l'analisi del percorso, ma non limita l'accesso al filesystem. Non garantiscono protezione neppure i flag che proibiscono i percorsi assoluti (ad esempio, RESOLVE_BENEATH e/o RESOLVE_IN_ROOT per openat2 in Linux): il programmatore deve aggiungerli a tutte le chiamate appropriate e, in caso di cattura del controllo del processo, un attaccante potrebbe sfruttare altri modi per aprire file.
Durante lo sviluppo dello strumento openrsync, Theo ha avuto la necessità di limitare le sue capacità di attraversamento del filesystem, ma non è stato possibile farlo utilizzando le funzioni unveil() e pledge(). È quindi emersa l'idea di un meccanismo simile a openat(), ma con proprietà di sicurezza che completano pledge/unveil o addirittura funzionano in assenza di essi.
L'idea principale è quella di integrare le restrizioni direttamente nel descrittore del catalogo. A tal fine, viene proposto il flag F_BELOW, che può essere impostato tramite fcntl(), oppure il flag O_BELOW per open(). Un descrittore «dirfd» limitato in questo modo permetterà solo le operazioni di discesa nell'albero dei cataloghi: le chiamate openat() con un percorso assoluto o con il passaggio verso l'alto tramite «..» si concluderanno con un errore ENOENT. In caso di attacco che porta all'esecuzione di codice, la tabella dei descrittori di file del processo conterrà «dirfd» meno funzionali, il che limiterà la superficie di attacco.
Fonte: opennet.ru
