Aula 02 - Gerenciamento de usuários I 1.1 - Conceitos O Linux, como qualquer Unix, é um sistema multiusuário. Isso implica que podem existir vários usuários para uma mesma estação. Quando isso acontece, uma preocupação para os administradores dessa estação é o gerenciamento dos recursos de cada usuário em particular. Afinal, como garantir uma configuração individualizada de acesso a essa estação? Outra questão importante é a de como garantir a privacidade dos dados de cada usuário. Em sistemas monousuários, fazer esse gerenciamento é uma tarefa extremamente complicada. Um usuário de um computador com Windows 98, por exemplo, pode ter seus documentos alterados ou apagados sem dificuldade alguma por qualquer pessoa que tenha acesso ao computador. A menos, é claro, que se esteja utilizando programas comerciais de terceiros com essa finalidade. Em sistemas Unix/Linux, a solução encontrada para esse tipo de problema foi o uso de contas de usuários. Essa filosofia permitem que vários usuários acessem a mesma máquina, inclusive ao mesmo tempo em ambiente de rede, sem interferir diretamente no ambiente de outro usuário. 1.2 – Contas de usuários Uma conta pode ser vista como uma entidade a nível do sistema operacional que armazena informações do tipo: - nome do usuário; - identificador do usuário no sistema; - grupo (ou equipe) do usuário; - diretório pessoal do usuário (onde ele armazena suas informações); - interpretador de comandos que o usuário utiliza; - credenciais ou senhas do usuário; - permissões do usuário. Essas informações vão indicar ao sistema operacional como o usuário deve ser tratado durante o uso da estação. Obviamente, cada sistema operacional irá tratar esses dados de uma forma particular. Ainda: alguns sistemas operacionais (como o Linux) irão permitir que esses dados possam ser armazenados e obtidos de diversas maneiras. Assim, uma conta é a maneira com a qual o usuário é reconhecido pelo sistema. Em um banco, por exemplo, o cliente é identificado pelo número de sua conta corrente (seu identificador no sistema) e sua senha (sua credencial no sistema). Em um sistema multiusuário, é óbvio que uma estratégia parecida tem que ser adotada. Em Unix,/Linux o usuário é identificado pelos seguintes dados: - username ou login: armazena o nome associado ao usuário no sistema. Apesar de não haver limites a nível de sistema operacional para isso, geralmente o login possui no máximo oito caracteres e é escrito todo em minúsculo. 1 - senha (password): a credencial usada pelo usuário para poder utilizar o sistema. Existem várias formas de se armazenar a senha do usuário e mesmo a possibilidade de utilizar senhas nãotextuais. - ID ou UID (User Identification): um número de identicação exclusivo associado ao usuário. A nível de implementação o sistema operacional associa ao login o respectivo UID. Os arquivos e processos do usuários são, então, identificados por esse UID. Esse número, na maioria das implementações, vai de 0 a 65634. - GID (Group Identification): grupo ao qual o usuário pertence. Em Unix, o usuário pode pertencer a vários grupos. Nesse caso o GID refere-se a seu grupo nativo. Um grupo é basicamente um conjunto de usuários. Geralmente ele é criado quando se deseja que vários usuários tenham permissão restrita a arquivos em comum. - Dados do Usuário: a maioria dos sistemas de armazenamento dos dados do usuários em Unix/Linux possuem um campo denominado GECOS (General Eletric Comprehensive Operating System field). Esse nome se dá por razões históricas. Esse campo é utilizado para relatórios de informações do usuários (ex: resposta ao comando finger). Em geral, contém o nome completo do usuário, mas não se limita a isso, podendo armazenar número de telefone, endereço, etc. - Diretório Pessoal: informa a localização do diretório pessoal do usuário, onde são armazenados seus arquivos e configurações individuais. Geralmente é um subdiretório do diretório /home. - Interpretador de Comandos (Shell): informa ao sistema operacional qual o interpretador de comandos do usuário. Um interpretador de comandos é um programa que recebe comandos do usuário e executa-os internamente ou repassa-os ao sistema operacional ou a outros aplicativos instalados. 1.3.2 – O arquivo /etc/passwd A maioria dos sistemas Unix armazena os dados do usuário no arquivo /etc/passwd. O exemplo abaixo mostra uma linha do arquivo desse arquivo. Pode ser verificado, neste exemplo, que os dados do usuário são separados por ‘:’. jpsilva:x:1111:100:Joao Pedro da Silva,, , ,:/home/jpsilva:/bin/bash O primeiro campo do arquivo /etc/passwd é o login do usuário. Esse login está associado diretamente à sua caixa postal eletrônica. Considerando-se, por exemplo, que a estação de trabalho possuidora do arquivo apresentado no exemplo acima esteja ligada à internet, tenha por nome host.domain.com e seja servidora de e-mail, então é de se esperar que o usuário jpsilva possua uma conta de e-mail dada por [email protected] ou por [email protected], dependendo da configuração utilizada na máquina. Essa ligação do login ao e-mail chama a atenção do administrador e do próprio usuário para a escolha de logins significativos. Assim, geralmente o login é construído a partir do nome do usuário. Devem ser evitados apelidos ou termos que criem constrangimento quando o usuário, por exemplo, for enviar um currículo ou um documento da empresa. 2 Recomenda-se que o login tenha no máximo oito caracteres e seja composto apenas de letras minúsculas, principalmente para usuários que terão acesso direto à máquina. Caso o usuário vá usar apenas os serviços de e-mail da máquina, a restrição de tamanho pode ser afrouxada. A maioria das distribuições Linux permitem logins com até 32 caracteres e até mesmo o uso de caracteres especiais. Caso um usuário insista em ter uma conta de e-mail com mais de oito caracteres, a melhor solução é usar apelidos de sistema (aliases). Assim o usuário jsilva poderia ter uma conta de e-mail jose.silva adicionando-se ao arquivo /etc/aliases uma linha com o texto jose.silva: jsilva. O segundo campo do arquivo /etc/passwd é a senha do usuário. Apesar do que se diz comumente, a senha do usuário não é criptografada, e sim codificada (hashed). O algoritmo utilizado pelo Linux para codificar as senhas é um algoritmo de hash, implementado na função crypt( ). Esse algoritmo, em geral, implementa uma modificação do algoritmo DES ou o algoritmo MD5, como pode ser visto na figura abaixo: A vantagem desse processo é que isso praticamente inviabiliza qualquer tentativa de descriptografar a senha de qualquer usuário. Durante o processo de codificação, se utiliza uma seqüência de caracteres aleatória para aumentar a segurança do processo. Essa seqüência de caracteres é geralmente chamada de "sal”, pois melhora (tempera) o processo de codificação das senhas. A figura acima apresenta uma comparação entre duas senhas codificadas por DES e MD5. É possível verificar na figura abaixo, que no DES a senha é armazenada com 13 caracteres, sendo que os dois primeiro representam o "sal" e o restante a senha codificada. Já no MD5, a senha ocupa 34 caracteres e sempre inícia com "$1$". Os oito caracteres entre o segundo e o terceiro "$" armazenam o sal utilizado na codificação e os 22 caracteres restantes são usados para a senha codificada. Existem vários aplicativos para trocar a senha, mas o mais usado é o comando passwd. Chamado em sua forma tradicional, sem nenhuma opção, ele irá permitir a troca da senha do usuário que invocou o comando. Para isso, ele pedirá a senha atual do usuário. Caso a senha confira, ele 3 pedirá que o usuário digite duas vezes a senha pretendida. Ele só alterará a senha, caso a senha pretendida seja digitada da mesma forma nas duas tentativas. Além disso, e possível configurar o comando passwd para verificar se o usuário não está escolhendo uma senha demasiado fraca. Ele pode chegar senhas demasiadamente curtas ou de fácil descoberta por terceiros. Uma opção forma de uso do comando passwd é mostrado na figura abaixo, que permite ao administrador do sistema (o usuário root) verificar se uma dada conta possui senha e qual o tipo de codificação usado: $ passwd -S jsilva Password set, MD5 crypt. O processo de decodificação da senha, apresentado na Figura 6.6 consiste basicamente em: 1) obter a senha do usuário; 2) codificar a senha do usuário usando o "sal" armazenado no arquivo de senhas; 3) comparar a senha codificada nesse processo com a que está armazenada no arquivo de senhas. Se essas senhas conferem, o usuário é autenticado pelo sistema. O terceiro e o quarto campos do arquivo /etc/passwd são, respectivamente, o UID (número de usuário - User ID) e o GID (número de grupo - Group ID). São usados, principalmente, para identificar o usuário no sistema e controlar as permissões individuais e grupais desse usuário. O quinto campo do /etc/passwd é o campo GECOS, comentado anteriormente. Em várias situações, contém apenas o nome do usuário. Quando contém outras informações, essas entradas são separadas por vírgulas. Apesar de poder armazenar qualquer coisa, o aplicativo finger espera que as informações do usuário estejam na seguinte ordem: - nome completo; - localização do escritório; - telefone do escritório; - número de telefone residencial. O exemplo abixo mostra um usuário com o campo GECOS completo (a) e a execução do comando finger para esse usuário (b), confirmando a informação anterior. Os dois últimos campos informam, respectivamente, o diretório pessoal e o interpretador de comandos do usuário. Em geral, o 4 diretório pessoal encontra-se em algum ponto na árvore do /home. Os interpretadores de comandos mais utilizados são o bash (/bin/bash) e o tcsh (/bin/tcsh). Uso do Campo GECOS pelo finger: (a) Trecho do Arquivo /etc/passwd aARL:x:1111:1111:Aluno ARL,DCC - 8,1123,2811-1111:/home/aARL:/bin/bash (b) Execução do comando finger $ finger aARL Login: aARL Name: Aluno ARL Directory: /home/aARL Shell: /bin/bash Office: DCC - 8, x1123 Home Phone: 2811-1111 Never logged in. No mail. No Plan. 1.3.3 – Escolha de senhas Uma boa senha é aquela que o usuário consegue se lembrar com facilidade, mas que nenhuma outra pessoa consiga descobrir. Assim, devem ser evitados, a qualquer custo o uso de datas significativas para o usuário, números de contas, nomes e sobrenomes de pessoas próximas, entre outros. Além disso, para dificultar o processo de alguém tentar descobrir a senha, é importante que a senha tenha ao menos dois dos seguintes itens: - mistura de letras maiúsculas e minúsculas; - uso de caracteres especiais (como espaço, ‘@’, ‘%’, ‘#’, etc.); - uso de numerais. A mistura desses itens dificulta imensamente qualquer tentativa de quebra de senha e permite a construção de senhas fáceis de se lembrar. A importância de uma senha de fácil memorização é evitar o imenso perigo de se anotar as senhas em papéis, agendas, etc. Nesse sentido, uma das grandes vantagens do MD5 sobre o DES na codificação de senhas é que ele permite, a princípio, que o usuário escolha uma senha de qualquer tamanho. O uso do DES na codificação das senhas limita o tamanho dessa senha a oito caracteres. Dessa forma, o uso do MD5 deve ser preferido, por permitir senhas mais fáceis de memorizar e com maior dificuldade para a quebra das mesmas. Uma regra utilizada e sugerida pelos autores deste texto é a utilização de frases sem sentido aparente (nonsense), mas que seja de fácil memorização pelo usuário. Essa estratégia também é defendida em (NEMETH, 2001). Um exemplo de frase nonsense que inspira uma boa senha é: "O macaco do Tibet no telhado". Troca-se algumas letras por caracteres especiais ou números (ex.: ‘a’ por ‘@’, ‘o’ por ‘0’, etc.) e tem-se uma frase que poderia ser excelente senha, se já não tivesse sido escrita nesta apostila: "O mac@c0 do Tibet no t&lhad0". 5 Caso se utilize DES, estando limitado a oito caractes, pode-se tentar resumir a frase imaginada, usando partes da frase nonsense. Assim, a frase acima poderia gerar as seguintes senhas, por exemplo: "Om@nTnt&" e "m@n0Tnt&". São senhas que, se não estivessem aqui escritas, poderiam ser consideradas perfeitas. A melhor regra para se escolher uma boa senha portanto é: usar a imaginação para construir senhas inimagináveis por terceiros. 1.3.4 - Senhas sombreadas Considerando-se que as senhas não são criptografadas, só existem três formas de um invasor descobrir a senha de um dado usuário: 1. obter a senha do usuário no tráfego da rede, através de técnicas de sniffing; 2. obter a senha através de tentativas simples baseadas em informações do usuário; 3. obter a senha através de um ataque de dicionário; 4. usar a força bruta, fazendo várias tentativas - essa alternativa é improvável, dado o grande número de combinações possíveis, mas é possível. A obtenção de senhas através do tráfego na rede pode ser evitada através do uso de conexões criptografadas. Maiores informações sobre sniffing, bem como estratégias para evitar problemas causados por ele irão ser abordadas em próximas lições. O invasor também pode tentar logar-se como um usuário utilizando senhas potencialmente inseguras. Assim, para um usuário chamado João da Silva Pereira, nascido em 22/11/1960, com RG 353.223, esse invasor tentaria, entre outras, as seguintes senhas: "jsilva", "jpereira", "silva", "pereira", "22-11-60", "22.11.1960", "353223" Daí a importância de uma boa escolha da senha, como já comentado anteriormente. O "ataque de dicionário", por sua vez, consiste em comparar palavras de um dicionário com a senha do usuário. Para isso, o invasor utiliza um programa que pega palavras em um dicionário de palavras (o termo certo seria "lista de palavras"), codifica cada uma das palavras utilizando vários tipos possíveis de "sal" e compara com a senha armazenada no arquivo de senhas. Assim, esse invasor precisa, em um momento inicial desse processo, conseguir as senhas dos usuários pretendidos para o ataque de dicionário. Inicialmente o ataque de dicionário não era um problema grave, devido ao limitado poder computacional dos equipamentos. Entretanto, isso hoje é um sério risco à segurança dos sistemas. Um primeira solução seria negar a leitura do arquivo /etc/passwd por outros usuários do sistema que não o administrador. O problema é que, como inicialmente ataque de dicionário não era enxergado como risco sério, o arquivo /etc/passwd precisa ter permissão de leitura para todos os usuários do sistema. Caso essa permissão seja retirada, vários serviços, como o finger ou o e-mail, deixarão de funcionar em suas configurações padrões. A alternativa encontrada para esse problema foi a de manter o arquivo /etc/passwd apenas para os dados de acesso e esconder a senha. Assim, em sistemas mais recentes, geralmente se utiliza o recurso de senhas "sombreadas" (shadowed passwords). Nesse caso a senha é armazenada em 6 um arquivo à parte, geralmente o /etc/shadow. Esse arquivo só pode ser lida pelo usuário root, que detém os poderes administrativos sobre o sistema. Assim, o campo destinado à senha no arquivo /etc/passwd é marcado com um " x ", como ilustrado nas Figura 6.2 e Figura 6.7. Essa senha é mantida no arquivo /etc/shadow, apresentado no exemplo abaixo. Como o arquivo /etc/passwd, esse arquivo possui campos separados por " : ". jsilva:$1$IeC1G.D7$mC/h(g7TYHh12jGÇ8VáDU0:11850:0:99999:7::: O primeiro campo é o login do usuário, tal qual como no arquivo /etc/passwd. Na realidade essa é a única ligação entre os dois arquivos. O segundo campo é a senha codificada. No caso do exemplo acima, a senha foi codificada usando MD5. O terceiro campo é usado para calcular o dia a senha foi alterada pela última vez. Para ser mais exato, ele informa quantos dias se passaram entre 1o de Janeiro de 1970 e a data da última alteração da senha. Essa é, na verdade, uma forma padrão de se indicar datas absolutas em UNIX/Linux. No caso do exemplo acima, o usuário alterou a senha pela última vez em 12 de Junho de 2002. O quarto campo é, sob o ponto de vista da segurança, praticamente inútil: ele indica o número mínimo de dias para que um usuário altere sua senha. Isso pode ser altamente perigoso, caso o usuário tenha sua senha alterada por terceiros. Esse campo só faz sentido em contas com as quais não se quer mudança de senha antes de um dado prazo, ex.: contas administrativas e de sistemas. Caso contrário, deve ser deixado em branco ou com o valor ‘0’. O quinto campo é exatamente o inverso do anterior: indica o número máximo de dias que o usuário pode ficar sem alterar a senha. Apesar de que as regras para uma boa segurança apontam para a necessidade de se trocar as senhas após um dado período, essa técnica não é, em geral, recomendada. Isso porque obrigar o usuário a alterar sua senha constantemente pode forçá-lo a reaproveitar senhas antigas ou anotar a nova senha e isso retiraria toda a vantagem do processo. O uso de "99999" nesse campo indica que as senhas nunca "caducam". Ainda assim, caso o administrador resolva fazer uso desse recurso de "caducidade de senhas", ele irá fazer uso do sexto campo. Esse campo indica quantos dias antes do prazo fatal para a alteração da senha o usuário deva começar a ser avisado pelo programa de login. Outra alternativa é utilizar o sétimo campo. Esse campo informa quantos dias após a expiração da senha o sistema deva considerar a conta desabilitada. Caso se pretenda utilizar o quinto para para desabilitar um usuário, esse uso é incorreto. O oitavo campo indica justamente quando o usuário deve ser desabilitado. Da mesma forma que no terceiro campo, ele informa o número de dias entre 1o de Janeiro de 1970 e a data da desabilitação da conta. Para contas normais, esse campo é deixado em branco. O nono campo existe, mas ainda não é usado. É reservado para usos futuros. Para simplificar o processo de alteração das informações do terceiro ao oitavo campo do arquivo /etc/shadow, geralmente se faz uso do comando “chage”. Quando chamado com a opção ‘-l’, informa os dados do usuário: 7 $ chage -l jsilva Minimum: 0 Maximum: 99999 Warning: 7 Inactive: -1 Last Change: Jun 12, 2002 Password Expires: Never Password Inactive: Never Account Expires: Never O comando chage pode ser usado de forma interativa, quando chamado com na forma chage jsilva. Nesse caso, ele irá pedir que o administrador informe os novos valores dos campos ou confirme os anteriores, como mostra o exemplo a seguir. Entretanto, ele pode ser chamado de forma não interativa. Por exemplo: chage -E 2003-08-01 jsilva faria com que a conta do usuário jsilva expirasse em 1° de Agosto de 2003. Para maiores informações, consulte a página de manual desse comando: man chage. $ chage jsilva Changing the aging information for jsilva Enter the new value, or press return for the default Minimum Password Age [0]: Maximum Password Age [99999]: Last Password Change (YYYY-MM-DD) [2002-06-12]: Password Expiration Warning [7]: Password Inactive [-1]: Account Expiration Date (YYYY-MM-DD) [1969-12-31]: 8