OpenBSD – fixando todas as chamadas de sistema
O novo recurso de “pinning” de syscalls do OpenBSD — que restringe de onde e quais chamadas de sistema um binário pode invocar — está gerando debate sobre quanta proteção real ele oferece contra técnicas modernas de exploração como ROP, e se ele apenas reforça caminhos de ataque já raros. Os comentaristas contrapõem o histórico do OpenBSD de mitigações proativas, às vezes especulativas, a preocupações com complexidade adicional, modelos de ameaça pouco claros e a descoberta de um overflow de buffer nesta própria implementação. O debate também aborda questões mais amplas de prática de engenharia de segurança, incluindo a dependência de C versus a adoção de Rust ou verificações mais fortes do compilador, e como medir o valor de mitigações que podem prevenir, e não apenas corrigir, vulnerabilidades.
Escopo da nova fixação de syscalls
- O kernel agora restringe syscalls de forma mais rigorosa:
- Antes: syscalls só eram permitidas a partir da região de texto da libc dos processos.
- Agora: fixadas a stubs específicos de syscall da libc.
- Para binários estáticos: apenas as syscalls efetivamente referenciadas no binário são permitidas; as demais ficam, na prática, desativadas.
- O
.textdo programa não pode mais executar syscalls diretamente; elas precisam passar pela libc (ou pelold.sodurante a inicialização). - Runtimes de linguagem normalmente chamam a libc, então continuam utilizáveis; runtimes “weirdo” ou JITs que sintetizam syscalls brutas em tempo de execução podem ser bloqueados.
Impacto na segurança e técnicas de exploração
- A fixação reduz alguma liberdade de ROP/JOP:
- Não dá mais para transformar qualquer instrução
syscallalcançável em uma syscall arbitrária; apenas o número de syscall registrado é permitido. - Ainda é possível abusar dos argumentos da syscall permitida (por exemplo, ainda chamar
execvese o programa normalmente o faz).
- Não dá mais para transformar qualquer instrução
- Para binários estáticos, atacantes não podem fazer ROP para syscalls que o programa nunca usou (por exemplo,
execvese estiver ausente), o que é visto como um confinamento útil. - JITs ainda podem saltar para thunks de syscall permitidos; JavaScript no navegador, em geral, não faz syscalls diretamente de qualquer forma.
- Outro efeito de mitigação: syscalls restringidas à libc complicam o bypass de ASLR quando o atacante só conhece o layout do binário principal e procura por padrões de bytes
syscallno texto.
Debate sobre eficácia e modelagem de ameaças
- Visões favoráveis:
- Se a mitigação é barata e não adiciona superfície de ataque, vale a pena incluí-la.
- O OpenBSD historicamente implantou mitigações antes de classes de ataques serem públicas (por exemplo, desativar hyperthreading antes de Spectre/Meltdown; aleatoriedade “desnecessária” que mais tarde bloqueou ataques a cache DNS).
- Baixos números de CVE e mitigações que antecipam vulnerabilidades são citados como evidência de boa intuição.
- Visões céticas:
- Mitigações sem mapeamento explícito para explorações reais/CVEs e cadeias de exploração testadas são criticadas como “amorfas” e potencialmente “teatro de segurança”.
- Toda mitigação adiciona complexidade e custo de manutenção de longo prazo; sem um modelo de ameaça claro, isso pode degradar a segurança no geral.
- Alguns argumentam que, se uma mitigação não interrompe claramente técnicas atuais em circulação, é em grande parte um exercício acadêmico.
- Outros respondem que focar estreitamente em “CVEs corrigidas” recompensa erros do passado e subestima bugs evitados.
Bug de implementação descoberto
- Um bug trivial, mas real, foi encontrado no novo código:
- Mistura de signed/unsigned em uma macro
MAXpermite que um atacante force uma contagem interna (npins) a ficar negativa, levando a subalocação e escritas fora dos limites no heap indexadas por números de syscall controlados pelo atacante. - Um esboço de exploração exemplo usa entradas de tabela de “pinned syscall” cuidadosamente forjadas para primeiro envenenar a memória e depois forçar
npinsa -1, que é então limitado a um pequeno valor positivo antes da alocação.
- Mistura de signed/unsigned em uma macro
- Discussão sobre ferramentas:
- Alguns observam que verificações de inteiros/tipagem no estilo Rust poderiam ter evitado essa classe de bug.
- Outros apontam que compiladores C já têm flags (por exemplo, warnings de comparação com sinal, sanitizers, traps de overflow) que poderiam ter detectado isso, mas que não estão universalmente habilitadas.
C vs. Rust e as restrições do OpenBSD
- Rust é elogiado por semântica de inteiros mais segura e verificação de tipos, mas:
- O OpenBSD tem ~dezenas de milhões de linhas de C, muitas plataformas e pouquíssima mão de obra.
- Reescrever ou integrar profundamente Rust no código central do SO é visto como de alto risco e intensivo em recursos.
- Alguns argumentam que novos sistemas operacionais voltados para segurança deveriam começar com Rust; outros enfatizam que Rust não é bala de prata e que código C maduro, com ferramentas cuidadosas, ainda pode ser viável.
Meta: postura de segurança e ecossistema do OpenBSD
- Alguns participantes dizem que a base de usuários do OpenBSD é pequena demais para existir um rico “meta” de exploração conhecido empiricamente, então boa parte disso é extrapolada de outras plataformas.
- Há tensão entre:
- Pessoas que veem o slogan e a reputação do OpenBSD como exagerados ou enganosos.
- Pessoas que veem o trabalho contínuo de hardening e o número relativamente baixo de falhas graves como justificativa suficiente, e ficam intrigadas com tentativas agressivas de desencorajar outros a usá-lo.