Elevação de Privilégios, Linux, Sistemas Operacionais

Capabilities – O que são e como explorar para “elevação de privilégios”

Tempo de leitura: 7 minutos

Do “man” do Linux, lemos que “para o propósito de verificação de permissões, tradicionalmente a implementação do UNIX distinguiu duas categorias de processos: privilegiado ( da qual o usuário ID efetivo é 0, referenciado como superusuário ou root), e não-privilegiados (da qual o UID efetivo é diferente de zero). Processos privilegiados contornam todas as verificações do Kernel, enquanto processos não-privilegiados estão sujeitos a verificação total de permissão baseada na credencial do processo (usualmente: UID efetivo, GID efetivo e lista suplementar de grupos)”.

O “man” continua: “Iniciando com o Kernel 2.2, o Linux divide processos tradicionalmente associados com superusuário em unidades distintas, conhecidas como ‘capacidades’ (capabilities), que podem ser independentemente ativadas ou desativadas”.

Em outras palavras: antes, para um usuário rodar algum comando ou processo que necessitasse de alguma função reservada ao superusuário, era necessário:

  1. Dar “bit SUID” ao executável. Com isto, o usuário poderia rodar um programa com as permissões do dono do arquivo
  2. Ou dar permissão de “sudo” para o usuário. Assim o usuário pode rodar alguns comandos determinados como superusuário

O problema é que de acordo com o “princípio do menor privilégio”, que diz para apenas dar o privilégio necessário para realizar alguma ação, as duas formas acima expostas pecam, já que dão muito mais permissão que o necessário. Assim, o Linux, desde o Kernel 2.2, criou as “capacidades” que um executável pode ter de forma independente.

Capacidades possíveis

As capacidades que podem ser dadas para um executável no Linux são:

CAP_AUDIT_CONTROL – Ativar e desativar auditoria de Kernel; mudar regras de filtro de auditoria; ler startus e regras de filtro e de auditoria

CAP_AUDIT_READ – Permite ler um log de auditoria via multicast netlink socket

CAP_AUDIT_WRITE – Escrever registros no log de auditoria do Kernel

CAP_BLOCK_SUSPEND – Permite cancelamento de uma “suspensão” do sistema

CAP_CHOWN – Permite mudança de UIDs e GIDs em arquivos

CAP_DAC_OVERRIDE – Contorna verificações de permissão de leitura, escrita e execução

CAP_DAC_READ_SEARCH – Contorna verificação de leitura de um arquivo e diretórios e também verificação de execução

CAP_FOWNER – Contorna verificações que o Filesystem UID precisa bater com o UID do arquivo (por exemplo chmod e utime); permite definir flags inode em arquivos; permite definir “ACLs” em arquivos;

 CAP_FSETID – permite definir um “set-group-ID” para qualquer arquivo que o GID não bata com o “filesystem”

CAP_IPC_LOCK – Permite dar um “lock” na memória (mlock, mlockall, mmap, etc)

CAP_IPC_OWNER – Contorna verificações de permissão para operações nos objetos System V IPC

CAP_KILL – Contorna verificações de permissões em enviar sinais. Por exemplo com kill e a operação KDSIGACCEPT no ioctl.

CAP_LEASE – Permite concessões em arquivos (fcntl)

CAP_LINUX_IMMUTABLE – permite definir FS_APPEND_FL e FS_IMMUTABLE_FL em flags inode (ioctl_iflags)

CAP_MAC_ADMIN – Permite configuração de MAC ou mudança de estados

CAP_MAC_OVERRIDE – Permite contornar Controles Mandatórios de Acesso (MAC)

CAP_MKNOD – Permite criar arquivos especiais com o “mknod”

CAP_NET_ADMIN – Permite configurar interfaces de rede; administrar firewall; alterar tabelas de roteamento; definir modo promíscuo e outras atividades relacionadas a administração de redes

CAP_NET_BIND_SERVICE – Permite dar um “bind” em portas privilegiadas (abaixo de 1024)

CAP_NET_RAW – Usar pacotes e sockets RAW

CAP_SETGID – Permite realizar manipulações de GID em processos e forjar o GID quando passar alguma credencial por UNIX domain socket

CAP_SETFCAP – Permite definir capacidades de um arquivo

CAP_SETPCAP – Permite adicionar ou remover capacidades de uma herança de chamado de um processo qualquer

CAP_SETUID – Permite manipulações de UIDs de processos

CAP_SYS_ADMIN – Permite uma série de operações restritas a administração de sistema (quotactl, mount, umount, sethostname, etc)

CAP_SYS_BOOT – Permite usar reboot e kexec_load

CAP_SYS_CHROOT – Permite usar chroot

CAP_SYS_MODULE – Permite carregar e descarregar módulos de Kernel

CAP_SYS_NICE – Permite redefinir a “importância” (ou prioridade) de processos (nice, setpriority)

CAP_SYS_PACCT – Permite usar acct

CAP_SYS_PTRACE – Permite realizar um “trace” em um processo usando ptrace e transferir dados de e para a memória de um processo usando process_vm_readv e process_vm_writev

CAP_SYS_RAWIO – Permite realizar operações de I/O reservadas

CAP_SYS_RESOURCE – Permite operações como usar espaços reservados em ext2, realizar ioctls em ext3, etc

CAP_SYS_TIME – Permite alterar o relógio do sistema

CAP_SYS_TTY_CONFIG Permite usar vhangup e outras operações em terminais virtuais

CAP_SYSLOG – Permite operações privilegiadas de syslog

CAP_WAKE_ALARM – Permite criar condições que “despertarão” o sistema

Como isso funciona na prática?

Como expliquei, com “capabilities” é possível dividir funções específicas que eram reservadas ao superusuário sem necessitar entregar permissão completa de superusuário. Imagine, por exemplo, que seja necessário que um processo qualquer consiga manipular o relógio do sistema, mas que não consiga manipular “UIDs” ou fazer chamadas “IOCTLs” privilegiadas? Então o administrador poderia dar apenas essa permissão com CAP_SYS_TIME e setcap desta forma:

setcap “cap_sys_time+ep” arquivo

Este comando define que o “arquivo” terá acesso para alterar o relógio (cap_sys_time) de forma “efetiva” e “permitida”, mas não poderá realizar nenhuma outra função privilegiada.

 Mas espera. Efetiva e Permitida? Isso!

Capacidade Efetiva, Herdada e Permitida

Capacidades Efetivas (e – effective) são aquelas que o processo pode realmente realizar! Por exemplo, um processo não pode criar um “raw socket” se não tiver efetivamente uma capacidade de “cap_net_raw”.

Capacidades Permitidas (p – permitted) são limitadores para capacidades efetivas. O “man” do Linux diz que se uma capacidade não for “permitida”, ainda que a tenha efetivamente, “pode nunca readquiri-la”.

Capacidades Herdadas (i – inheritable) são capacidades preservadas através de um “execve”.

Além disso é possível usar flags “=”,”+” e “-“.

O operador “=” significa que todas a capacidade é resetada em todos os modos e então definido apenas na especificada. Por exemplo “cap_chown=e” tira a capacidade de mudar UIDs e GUIs de arquivos de forma efetiva, permitida e herdada e ativa novamente apenas de forma efetiva.

Os operadores “+” e “-“, diferente do operador “=”, apenas adicionam um retiram especificamente as capacidades especificadas sem alterar os outros modos que possam ter.

Capacidades podem “abaixar” um privilégio

Para demonstrar isso, localizei onde estava o “tar” e copiei para um usuário limitado, sem permissão de sudo.

copiando tar para usuário limitado

Se eu tentar compactar um arquivo que eu não tenha permissão, por exemplo o “shadow”, eu não conseguirei porque meu tar não tem permissão nem capacidade para isso.

Tentando compactar “shadow” com “tar”

Porém se eu mudar para um usuário com permissão de rodar comandos como superusuário (sudo), alterar o “dono” deste tar para root e dar bit suid e permissão 755, meu usuário restrito conseguirá arquivar arquivos restritos e até rodar um shell privilegiado (escalação de privilégios por SUID File clássico).

Escalação de Privilégios com Tar setado bit SUID

E se eu retirar as “capacidades”, mesmo com o bit SUID, o tar não conseguirá arquivar! Para isso vou rodar o comando:

setcap “all-eip” ./tar
Retirando capacidades do Tar com bit SUID

Veja que o meu “tar” continua pertencendo ao “root” e continua com o bit suid. Mas mesmo assim, não é mais possível abrir o “/etc/shadow” porque meu tar perdeu essa capacidade de forma “efetiva”, “permitida” e por “herança”.

Capacidades podem elevar privilégios (privilege escalation)

Assim como é possível limitar privilégios com “capabilities”, também é possível elevar privilégios de arquivos sem privilégios! Ainda no “tar”, vou alterar o dono para o usuário restrito porém darei capacidade efetiva e permitida para contornar qualquer verificação de leitura, escrita e execução (CAP_DAC_OVERRIDE).

CAP_DAC_OVERRIDE no Tar limitado

Veja que o tar está limitado, porém ao dar capacidade de ler, editar e executar qualquer arquivo, é possível compactar arquivos restritos! O arquivo gerado “shadow.tar” terá a permissão do usuário atual. Então eu posso descompactar este arquivo, os arquivos filhos herdarão a permissão e, assim, eu tenho acesso ao arquivo “shadow” que eu não teria acesso normalmente!

Conseguindo leitura do arquivo “shadow” pelo Tar

Conseguindo shell privilegiado com “python” e “cap_setuid”

Neste momento copiei o interpretador Python para a pasta home do usuário restrito. As permissões estão definidas como meu usuário restrito. Ao tentar elevar meu “UID” (ID de usuário) para zero (ou seja, para root) e rodar um shell, eu tenho a permissão negada porque meu Python não tem esta capacidade.

Tentando elevar privilégios com Python limitado

Agora vou dar capacidade de setuid (CAP_SETUID) para meu interpretador Python e mesmo sem bit SUID, conseguirei um shell privilegiado:

Conseguindo shell privilegiado com “CAP_SETUID” e Python

Procurando arquivos com “capacidades” em todo o sistema

Agora que vimos que “capacidades” podem ser um importante meio de elevação de privilégios, precisamos descobrir como procurar todos os arquivos com “capacidades” em um sistema. Ainda bem que isso é bem fácil fazer. Basta digitar o comando:

/usr/sbin/getcap -r / 2>/dev/null

Esse comando irá procurar recursivamente em todo o sistema todos os arquivos que tenham alguma capacidade e mostrará. Os erros de permissão que eventualmente se tenha, serão enviados para “/dev/null” (na prática equivale dizer: não me mostre nenhum erro).

Procurando todo executável com “capacidades”

Observe capacidades: “cap_setuid” (mudar UID), “cap_dar_override” (ler, editar e executar qualquer coisa), “cap_chown” (mudar dono e grupos de arquivos) e outras que julgar interessante da lista acima.

Abraços e até a próxima

One Comment

Leave a Comment

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *