Redução de Privilégios em Programas Go para Aumentar a Segurança
Uma boa prática para aumentar a segurança de um sistema é reduzir os privilégios de execução de um programa. Idealmente, um programa deve rodar com o mínimo de privilégios possíveis.
Em sistemas UNIX-like, é possível alterar o usuário e o grupo em que um programa é executado. Vamos ver um passo a passo de como fazer isso em Golang.
Verificando se o Programa está Rodando como Root
Primeiro, verifique se o programa está sendo executado como root. Isso é importante porque usaremos chamadas de sistema que necessitam de privilégios de root. (Existem outras maneiras de conceder esses privilégios, mas abordaremos isso em outro artigo.)
No exemplo abaixo, usamos os.Getuid()
para verificar se o programa está rodando como root. Se não estiver, o programa é encerrado.
if os.Getuid() != 0 {
fmt.Println("execute como root")
return
}
Claro que você pode fazer exatamente o oposto, ou seja, inverter a condição para que o programa só rode se não estiver como root. Mas a ideia aqui é que o programa altere sozinho para outro usuário, então vamos continuar.
Verificando o ID do Usuário e do Grupo
Você pode verificar o ID do usuário e do grupo em qualquer momento usando as funções os.Getuid()
e os.Getgid()
.
fmt.Printf(
"executando como uid: %v, gid: %v\n",
os.Getuid(),
os.Getgid(),
)
Alterando para o Usuário “nobody”
Agora, vamos alterar nosso programa que está rodando como root para mudar para o usuário nobody. Primeiro, obtenha as informações do usuário nobody com a função user.Lookup
.
u, err := user.Lookup("nobody")
if err != nil {
fmt.Println(err)
return
}
Com as informações do usuário nobody, altere o ID do usuário e do grupo em que o programa está rodando usando as chamadas de sistema syscall.Setgid
e syscall.Setuid
.
uid, _ := strconv.Atoi(u.Uid)
gid, _ := strconv.Atoi(u.Gid)
// Ajusta o ID do grupo
err = syscall.Setgid(gid)
if err != nil {
fmt.Println(err)
return
}
// Ajusta o ID do usuário
err = syscall.Setuid(uid)
if err != nil {
fmt.Println(err)
return
}
A partir desse ponto, o programa está rodando com os privilégios do usuário nobody, ou seja, com o mínimo de privilégios. Você pode criar usuários específicos para cada serviço e rodar o serviço com o privilégio específico dependendo do serviço.
Nota: Reduzir privilégios é uma boa prática, mas não impede um ataque. O que ela faz é reduzir os danos de um ataque que explore uma falha no seu programa.
O código completo está disponível no GitHub.
Vídeo com a demonstração:
Até a próxima!