Estou implementando alguns desafios do CTF. Os sinalizadores estão em alguns arquivos de texto, que são lidos nos programas. Para proteger os flags mudei o dono dos arquivos, mas configurei os setuid
executáveis para poder ler os arquivos. Funciona quando executo meus programas fora do gdb e os sinalizadores são lidos, mas dentro do gdb recebo Permission denied
. Estou executando os exercícios dentro de uma máquina virtual Linux no VirtualBox. Eu criei um usuário normal que não está no arquivo sudoers e os arquivos de sinalizadores pertencem ao root.
-rwsr-xr-x 1 root user 15260 Mar 13 13:22 exercise6
-rw-r--r-- 1 user user 3270 Mar 13 06:10 'Exercise 6.c'
-rwsr-xr-x 1 root user 15700 Mar 14 03:28 exercise7
-rw-r--r-- 1 user user 4372 Mar 13 06:10 'Exercise 7.c'
-rwS------ 1 root root 28 Mar 13 06:10 admin_flag.txt
-rwS------ 1 root root 20 Mar 13 06:24 exercise1.txt
-rwS------ 1 root root 27 Mar 13 06:24 exercise2.txt
-rws------ 1 root user 18 Mar 13 10:34 exercise3.txt
-rwS------ 1 root root 22 Mar 13 06:24 exercise4.txt
-rwS------ 1 root root 19 Mar 13 06:10 user_flag.txt
O contrato de segurança do setuid¹ é que ele concede privilégios extras ao programa executável. Esses privilégios são concedidos apenas ao programa. Eles não devem permitir que o usuário invocador faça algo que o programa não faça.
Isso torna o setuid incompatível com o rastreamento (a
ptrace
chamada do sistema na maioria das variantes do Unix). Se o usuário invocador puder observar o funcionamento interno do programa, isso lhe dará acesso a quaisquer dados confidenciais aos quais o programa tenha acesso. Mas podem ser dados confidenciais que o usuário não deveria ter permissão de ver, que o programa normalmente não revela. Talvez mais obviamente, se o usuário invocador puder alterar o que o programa está fazendo (tambémptrace
), isso poderia permitir que ele tivesse todos os privilégios do usuário setuid, o que anula completamente o objetivo de conceder permissão apenas para executar um programa específico. Rastreamento é a funcionalidade que um depurador como o GDB usa para inspecionar e controlar a execução do programa.Como exemplo, considere o programa
unix_chkpwd
, cuja função é verificar a senha do usuário invocador. Este programa deve ser capaz de ler dados confidenciais (o banco de dados de hash de senha). Mas o usuário invocador não deve ter permissão para ler todo o banco de dados. O usuário invocador só deve ser capaz de consultar a entrada desse usuário e apenas com uma resposta sim/não (sem extração do próprio hash da senha) e com uma limitação de taxa para evitar quebra de força bruta. Se você pudesse executargdb unix_chkpwd
e imprimir o conteúdo do banco de dados hash de senha, isso quebraria completamente a segurança desse banco de dados.Para manter a segurança:
¹ Isso também se aplica ao setgid, setcap ou qualquer outro mecanismo semelhante para executar um programa com privilégios elevados.