Mostrando entradas con la etiqueta security. Mostrar todas las entradas
Mostrando entradas con la etiqueta security. Mostrar todas las entradas

2024/01/29

Análisis de entrega de material ciberciruja

Un poco como actualización de wipe, donde explico cómo disponer de modo seguro y eficiente de medios magnéticos y señalo lo ineficiente que me resultó donar material de computación, cosa sobre la cual reflexiono y vuelvo a recalcar en cyberciruja 2023, a raiz de la experiencia del domingo 2024-01-28, reviso un poco esas ideas.


Por motivos personales tuve que hacer una purga y disponer de bastante material, calculo que un tercio de metro cúbico, detallado en material cyberciruja (Listado de la purga 2024/01/28)

 

Parte del lote
Parte del lote

 


El método consiste en preparar el lote (algún detalle extra más abajo en "Actividad común a cualquier metodología de donación"), coordinar con el grupo cyberciruja ubicación y fecha/hora, conseguir transporte, solicitar la ayuda de una o dos personas, llevar todo, explicar a quien manifieste interés por cada pieza qué es, para qué sirve y su estado y listo.


En comparación a experiencias anteriores, resultó muy eficiente. Para cada pieza  de wipe calculo que le habré dedicado dos horas promedio pese a que cada una podía ser más interesante que cualquiera del lote actual y llevó meses en tiempo bruto. En este caso mi esfuerzo invertido fué más o menos este:

 

Tiempo bruto

 

Desde que me decidí hasta que ocurrió dos semanas, pero pudo haber sido una.

 

Tiempos netos

 

Menos de 10 horas, incluyendo la disposición segura

 

Conseguir cajas

 

20 minutos repartido en varios días

 

Elegir que purgar

 

2 horas, la clave es elegir poco, si hay algo que es muy interesante, como por ejemplo una dataset de commodore o unas netbooks del gobierno de las primeras y hace falta hacer el borrado seguro, descartar y dejar para otra oportunidad.

 

Coordinar en el grupo

 

menos de 2 horas, es avisar "tengo todo esto, ayúdenme, cuándo podemos?"

 

Llevar todo al parque

 

1 hora, depende de la distancia y el volumen de cosas....

 

Explicar y repartir

 

2 horas, compartido por las personas presentes. Primero hay que atender al cyberciruja. Segundo hay que avisarle a quien pasa que el material está disponible y sus condiciones de gratuitidad. En ambos casos, explicar lo que sepas de la pieza en cuestión, si funciona, si es a probar o reparar.

 

Actividad común a cualquier metodología de donación


Y ahí es dónde entra al seguridad, es el tema de que los medios magnéticos no deben contener información. Esto implica borrado "seguro" o destrucción.

En este caso hubo un solo borrado de un ide de 80GB.

Tenía unos diez discos rígidos que no funcionaban asi que no se podían borrar, pero al ignorar que información tenían, no podía tampoco entregarlos. Puede parecer medio estúpido pero así funciona mi mente.

Lo que hice fué desarmarlos (de ahí salió "montón boards de discos rígidos") para quedarme con los platos, los motores y los imanes. Esto me llevó unas dos horas.

Los imanes suelen estar pegados a una chapita, basta con retorcer la chapita con dos pinzas para que el adhesivo falle y quedarse con el imán. Estas chapas junto a las carcazas se las entregué en mano a un cartonero con carrito en cualquier otro momento.

Respecto a cd/dvd, entregué todos los que tenían drivers o programas, un poco confiando en que los grabados por mí no tuvieran información. De todos modos los únicos que suscitaron interés fueron los "impresos", tipo encarta 2000.

De souvenir exclusivo para cybercirujas, repartí unos discos ópticos locos, confiando en que no tenían nada y que nadie tiene el lector.

Los diskettes elegí que no tuvieran etiquetas o estuvieran en blanco, confiando....


Anécdotas


Una persona estaba muy interesada en recuperación de componentes electrónicos, en particular motores, se llevó entre otras cosas:

  • componente lectora triple de cd
  • componente dual deck

 

Gran interés tuvieron:

  • trafo original atari 110v
  • gabinete de la alarma casera
  • tablet coby
  • dock thinkpad con fuente y llave
  • tv philips 40 tocado por un rayo

 

Este tipo de evento, aunque en esta ocasión tuvo un fuerte protagonismo de una persona, puede ser más "cada uno lleva un poco". De hecho algunas personas trajeron alguna cosita y el encuentro también sirvió para intercambiar cosas que estaban esperado a cambiar de manos.

 

Conclusión

 

Aunque quizás no séa óptima la reutilización por componente, capaz que alguien se llevó un componente útil para sacarle el cobre, el método presentado, entre los extremos posibles, es más eficiente para quien se está deshaciendo de material que la donación pieza por pieza con seguimiento por un lado y por el otro, probablemente genere menos residuos tirados en la calle que tirar todo en la basura.


El equipo desde un árbol
El equipo desde un árbol




2023/10/08

Un poco de history

En esta ocasión, algunas ideas y tips relativas al comando history.

Provee la funcionalidad de registrar los comandos ingresados para consulta o reejecución.

Repecto a la concurrencia, tiene la particularidad de que a medida que se van cerrando las sesiones se van guardando, cada una con su estado y sobreescribiendo las otras. En otras palabras, gana la última que escriba y eso vale para las abiertas que no tenés a la vista como accesos vía ssh o terminales en otras workspaces.

El registro está en ~/.bash_history, se puede editar.

Con el comando 

history -d N

eliminar la línea N.

Si no querés que se salve

unset HISTFILE && exit

y este que es más lindo, pero no cierra la ventana si estás en un entorno gráfico

kill -9 $$ 

y la verdad que no sé que hace en un entorno no gráfico.

Un truquito que se me ocurrió hace muchos años, incluso me lo pagaron en la revista Linux Journal, lo llamé "disposable alias", me había matado con el texto y lo redujeron a casi nada:

 

tech tip
tech tip

 

Consiste en agregar un comentario al final de los comandos que querés ejecutar varias veces pero no vale la pena hacer un script o un alias y querés recuperar con control-R:

comando ; # tag

Por ejemplo:

find . -iname "*borrar* -exec ls -l {} \;" ; # listar_a_borrar

Si pensás que con control-R borrar podés lograr el mismo efecto, considerá que cerca va a estar lleno de cosas como:

view borrar.txt

rm borrar2.txt

mkdir TRASH

mv borrar3.txt TRASH

y así...

 

La joya


Todo esto que escribí es solo para entrar en tema, ¿qué pasa si ejecutaste algo como esto?

export HTTP_PROXY=http://user:password@server:port
 
Te ha quedado en history la clave del proxy, para que la vea cualquiera que pueda acceder a tu history.
 
Tenés que hacer history | less para encontrar el número y luego history -d N.
 
Según ví en man history, hay toda una serie interminable de opciones para hacer... ni entendí bien qué, tomar un comando, reemplazarle una parte y ejecutarlo, me parece un poco bloatware.

 
Hay una manera mucho más sencilla 
 

Escondida en la documentación, hay una joyita que Mar Fer comentó en una conversación cyberciruja. Si tocás una cierta variable de la configuración, podés evitar que queden registrados los comandos de las líneas que inicies con espacios.

 

 
HISTCONTROL

A colon-separated list of values controlling how commands are saved on the history list. If the list of values includes ‘ignorespace’, lines which begin with a space character are not saved in the history list.

 

Cuando Mar Fer contó, me fijé en man history y nada dice, casi que parecía un bug, pero no, it is a feature.


Perspectiva de seguridad

 

Debido a la destrucción producto de la concurrencia, la facilidad de eliminar, editar o incluso suprimir todo, history sirve de modo muy incompleto para análisis forense. Si realmente necesitás trazabilidad, andá por el lado de auditd.

Respecto a comentar que existe lo de HISTCONTROL, un atacante que lo conozca podría en el medio de una serie de comandos normales que no llamarían la atención, ejecutar sin que quede registrado alguno malicioso en particular.

Mantener oculto lo de HISTCONTROL sólo contribuiría a una falsa sensación de seguridad mientras que el hacerlo conocido ayuda a que hayan menos datos sensibles en history, gana comentarlo.


2023/09/29

Cómo pegar texto sin portapapeles

Supongamos estos escenarios:


Tenés una VM recién instalada sin entorno gráfico y hay que ejecutar algunas instrucciones muy largas. Como no tenés portapapeles, a tipear.

Estás haciendo login en una terminal o aplicación que no soporta copiar y pegar y terminás bloqueándote porque tenés una clave tipo "1lI0OG68B".

Estás llenando un campo en una página web que por algún perverso motivo tiene

 <input  type="text" onpaste="return false" /> 

Seguro te ha ocurrido cuando te piden un mail y en la verificación no te deja pegar.

La generalización del problema es:

 

Quiero pegar texto y el portapapeles no funciona.


Entonces pensás. Si hiciste ataque del "falso pendrive" en el cual pusiste un microcontrolador que se registra como un teclado y envía texto, ¿se podría hacer algo parecido con software? ¿Un programa que envíe el texto a la ventana como si fuera el teclado?

Pues existe y si usás X11, no Wayland, se llaman xdotool.

Para saber si usás X11, ejecutás:

$ echo "$XDG_SESSION_TYPE"

o

$ env | grep -E -i 'x11|xorg|wayland'

Para instalar xdotool en Debian y derivados

$ sudo apt install xdotools

Luego, tenés que ejecutar esta secuencia:

  • Encontrar la ventana
  • Seleccionar la ventana
  • Enviar el texto

Por ejemplo:

xdotool search "Virtual" windowactivate --sync type "ls"

¿Fácil? Nada lo es. Si mirás 

$ man xdotool

verás que es una herramienta superpower, pero quedémonos con lo más básico y veamos los detalles

 

Encontrar la ventana


El search viene a ser un /.*PATTERN.*/i

Otra, hay ventanas embebidas, por ejemplo para firefox, te trae todas las solapas:

$ xdotool search "Firefox" | wc -l
Defaulting to search window name, class, and classname
94

 

Seleccionar la ventana


Es hacerla activa y el --sync es para que espere a que ocurra

 

Enviar el texto


Esto no debería tener sorpresas hasta que lo probás y el teclado de un host no corresponde con el de destino.

Se debe a que en realidad no se están enviando letras sino keycodes, que es exactamente lo mismo que pasa con el microcontrolador.

O cambiás la disposición del teclado en el destino o tenés que hacer alguna conversión del texto que vas a enviar. Un tr nunca viene mal, hasta que intentás hacerlo y te recomiendo cambiar la disposición.


Si no podés hacerlo y no hay mucho que enviar, te recomiendo que lo mandes como está y luego edites y corrijas, perdí un montón de tiempo con tr

 

Retrospectivamente, lo mejor sería escribir un programita que haga el proceso inverso, obtener el keycode de las teclas que habría que mapear y que genere el texto apropiado pero ya es todo un proyectito.


Ponele que no podés cambiar la disposición del teclado, aún queda el Plan Base64.

Primero la falla y luego con base64
Primero la falla y luego con base64

Después de haber fallado:

  1. Pasás el texto a base64
  2. Preparás el comando y ponés el cursos entre las comillas ""
  3. Enviás el texto
  4. Ejecutás falla porque el "=" no se transmite...
  5. Lo arreglás a mano y volvés a ejecutar
  6. Mostrás el contenido correcto

 

Ideas adicionales


En una terminal no X de una VM, instalando gpm se puede copiar y pegar localmente, pero aún con VboxAdditions y el portapapeles activado no pude pegar entre entornos. Igual no me maté mucho probando.

Lo de los campos a los que no se les puede pegar, que el ejemplo más básico sería una página que abrís directamente del sistema de archivos con este contenido:

<form>
  <input type="text" /><br/>
  <input type="text" /><br/>
  <input type="text" onpaste="return false" />
</form>

lo podés burlar muy fácilmente quitando lo marcado en amarillo desde el navegador con Developer Tools, ahí fué la seguridad de Client Side Validation...

Estos métodos pueden parecer rehacking pero si mirás atentamente sólo estás introduciendo texto, no hay fuga de información, cosa que sí habría en caso de funcionar el portapapeles.

Una idea para facilitar la transcripción de credenciales cuando todo lo demás falla, es  que tengan la forma ???_???_???_???, no disminuye la fortaleza y facilita la copia humana.

Finalmente, si usás estos métodos con claves, no te olvides de borrar en el historial de comandos...

Bonus: gzalo me avisó que la mayoría de los password managers tiene esta función, en el caso particular de KeePassXC es botón derecho sobre la cuenta, "Perform Auto-Type", que le envía la clave a la última ventana a la que le hayas hecho foco. Probalo con una cuenta inútil y un editor de texto hasta que lo entiendas bien.

Bonus: lo de usar un microcontrolador para almacenar claves es la idea que todos tuvimos pero solo mar fer realizó.


Dejo pegados acá los comandos:

 

xdotool search "ventana" windowactivate --sync type "txt"

 

xdotool search "ventana" windowactivate --sync type $( echo "txt" | base64 ) 

cmd=$( echo "" | base64 -d )

 

xdotool search "ventana" windowactivate --sync type $( base64 script.sh) 

echo "" | base64 -d > script.sh




2023/07/09

MD5 como IOC apesta

Qué es un IOC

Cuando hay ataque, en sus distintas etapas, se van generando acciones y artefactos, que deberían quedar registradas en algún lado y que son detectables.

Por ejemplo, te envían un link malicioso, para que te descargues un archivo, que al ejecutarse accede a una url para bajar componentes adicionales, exfiltrar información o recibir órdenes. Además, se escribe en el disco como persistencia y agrega una clave en el registro para reiniciarse cuando el sistema lo haga, ¿qué tenemos?

  • Una url maliciosa
  • Un archivo malicioso
  • Más archivos maliciosos
  • Más urls
  • Claves en el registro

Si vos ves este ataque, podés tomar nota de identificadores de cada una de estas piezas y luego, ante cada intento de acceder a urls comparar con las maliciosas, al bajar, escribir o leer un archivo hacerlo con los maliciosos y revisar el registro buscando claves.... maliciosas.


El caso particular del archivo no es muy práctico tomarlo como referencia pues puede ser grande, lo mejor es calcularle un hash y guardar ese Indicator Of Compromise.

 

Pequeña pieza de recomendación

 

Lamentablemente, incluso entre la gente técnica, la falta de conocimiento detallado hace que se cometan errores de concepto, por ejemplo el que paso a reportar, pues lo he visto varias veces con varias personas.

Ponele que tenés dos herramientas que entienden IOCs, el DNS y el proxy saliente.

Te llega este IOC, ¿dónde lo ponés?

https://3984274.aws.com

Muy bien, en cualquiera o ambos.

¿Y este?

https://3984274.aws.com/api/service/34

Si tuvieras la tentación de decir lo mismo, antes mirá este:

https://www.afip.gob.ar/api/service/34

Hay personas que han dicho:

"Pongamos en ambos"

Hay dos problemas, el de seguridad y el conceptual técnico.

El de seguridad es que si para bloquear  

https://www.afip.gob.ar/api/service/34

ponés  "www.afip.gob.ar" en el DNS, generás una denegación de servicio a todo afip sólo por una ruta comprometida. Podría ser válido, razonando "si tiene esa ruta comprometida, puede estar todo el resto, no interactuemos en absoluto con afip hasta que corrijan", ok, es una decisión.

En la conversación de esa decisión es cuando detecté el problema conceptual técnico:

El DNS no entiende ni "https://" ni "/api/service/34"

La única manera de bloquear sin "daños colaterales" es en el proxy.

Sigamos....

 

Qué es MD5


Hashing es una operación que se hace sobre un dato y devuelve un hash, que es un número largo y en teoría cambia ante cualquier modificación sobre el dato. Si calculás un hash de un dato, modificás un bit, recalculás, te da otro hash.

Por alguna falta de visión, pues esto de los IOCs es relativamente reciente, se utilizan como IOCs de archivos hashes MD5, que se diseñó en 1991 y ya desde 1993 se le han hallado problemas criptográficos que en el mejor de los casos, parecería que ya desde 2010 se considera deprecado.

Digo falta de visión pues si buscamos en wikipedia IOC, el artículo nace en 2013, como que ya existían varios SHA para ese entonces, pero seguro que lo de los IOC con MD5 entraron de la mano de gente de seguridad no técnica y programadores sin conocimientos de seguridad que buscaban ahorrar espacio y tiempo de ejecución.

Ojo, siempre es fácil señalar los errores del pasado desde el futuro, pero bueno.

 

La colisión "accidental"

 

Una colisión de hash es cuando dos datos distintos dan el mismo hash. Las colisiones son esperables pues la variedad de datos es infinita y los hashes son números, en el caso de MD5 entre 0 y 2 a la 128, que aunque es un número grande, claramente es muy muy muy inferior a infinito.

 

Se podría argumentar que dada la baja probabilidad de colisión y la ventaja del ahorro de espacio y tiempo de ejecución no importa, aunque ya tenemos al menos un caso conocido.

 

Dice este reporte que no sé de dónde saqué, pero se parece a la situación habitual de malware, en este caso Trojan.Win64.CoinMiner, un minero:

https://itsafety.net/report/20200515-65ade21dc82c01972891285581d85866-servermanager-exe_process-partofthreat

Trojan.Win64.CoinMiner
Trojan.Win64.CoinMiner


Fijate que dice que la mayor parte de los antivirus no lo detecta, ¿por qué será?

Dice Microsoft, que respecto a windows debe tener una cierta autoridad

https://learn.microsoft.com/en-us/windows-server/administration/server-manager/server-manager

Microsoft
Microsoft


Puede ser que estemos hablando de distintas piezas, pero si buscás en virustotal ese hash (65ade21dc82c01972891285581d85866), te trae

 

VirusTotal
VirusTotal

De paso observá que el hash que te muestra es un SHA256, correcto.

No tengo las ganas de buscar cada versión legítima del archivo hasta encontrar el que coincide con esa firma, para demostrar fehacientemente el punto pues su demostración pasa por otro lado.

 

La colisión a propósito


Desde hace años en mis charlas muestro este ejemplo:


angel devil
angel devil

Vemos que dos programas generan distinto output, miden lo mismo, tienen la misma longitud pero son distintos, con sha256 eso no pasa.

 

sha256
sha256


La verdad verdad, no sé bien de dónde lo saqué, tampoco importa muchísimo pues se trata de criptoarqueología y no hay nadie que discuta que MD5 no sirve.

Es un programa en C con un buffer. En ese buffer hay un valor, se compila y al ejecutar se comprueba que sea ese valor. En este caso se ejecuta angel().


Luego, con fastcoll y longEgg se manipula ese buffer en la copia de angel llamada devil hasta que da el mismo hash MD5. Al ejecutar y fallar la comprobación, se ejecuta devil().

 

int main() {
  if (strcmp(dummya, dummyb) != 0) {
    return angel();
  } else {
    return devil();
  }
}



Lo que importa, es que probablemente se puedan tomar dos programas de la misma longitud, manipular una parte y hacerles concidir los hashes, con lo cual para cada ejecutable legítimo del sistema

Digo probablemente pues como script kiddie todo esto parece fácil, pero no lo he comprobado.

Me pregunto por qué no se hace y apuesto a que no vale la pena, es demasiado fácil contrarestar, leyendo el archivo de atrás para adelante para el MD5 o tomando otro SHA cualquiera basta para detectar correctamente, salvo en las herramientas más precarias, para decirles de alguna manera....

lectura invertida
lectura invertida


Para qué puede servir MD5

 

MD5 es útil en situaciones sin adversarios. Por ejemplo, tenés dos archivos del mismo tamaño y no sabés si son iguales. Si están en la misma máquina corrés cmp y listo, te lo dice. Pero si están en distintas máquinas, tendrías que copiar uno a la otra o montar en una una carpeta de otra.... mucho trabajo. El MD5 de cada archivo te puede confirmar si son distintos, no tanto que sean iguales, pero ya dije, sin adversarios.

Me ha servido para hacer unas pruebas con FPGA, tal cual relato en un montón de entradas....

Y por supuesto sirve para demostrar lo inseguro que es.

2023/07/04

Reflexiones sobre rbash

Supongamos que tenemos un linux al cual se accede por ssh. La situación normal es que a nivel de permisos tenemos root y el resto.

El usuario root puede hacer todo, listo.

Dentro de ese resto, manejando grupos y permisos podríamos más o menos manejar algún tipo de restricción. Una medida común es utilizar sudo, que habilita  una lista de acciones que podrá ejecutar quien tenga los permisos.

Pero, ponele que en lugar de estar viendo como le permitimos a los usuarios hacer algunas tareas administrativas, estamos buscando restringir lo que ya pueden hacer. Si el usuario en realidad es una cuenta para que un script pueda ejecutar algunas consultas sobre el sistema, no hay motivo para que pueda ejecutar ningún otro comando que no corresponda a lo que va a hacer.

Para este requerimiento, se puede usar rbash.

Si, si, ahí los del fondo, escuché que existe selinux y apparmor, pero esas son palabras mayores, quedémonos con lo sencillo.


Lo que hace rbash es empezar por desabilitar un montón de comportamiento provisto por bash, acá está la lista completa, lo más importante es que no permite cd ni cambiar la ruta de invocación de comandos.

Además:

The restricted shell mode is only one component of a useful restricted environment. It should be accompanied by setting PATH to a value that allows execution of only a few verified commands (commands that allow shell escapes are particularly vulnerable), changing the current directory to a non-writable directory other than $HOME after login, not allowing the restricted shell to execute shell scripts, and cleaning the environment of variables that cause some commands to modify their behavior (e.g., VISUAL or PAGER). 


Sumado a eso, en .bashrc o similar hay que setear el PATH a una carpeta con symlinks a los ejecutables permitidos, según he visto que se hace.


Luego, se debe considerar que:

When a command that is found to be a shell script is executed (see Shell Scripts), rbash turns off any restrictions in the shell spawned to execute the script.

Estoy citando pues como tengo casi nula experiencia con rbash, me siento irresponsable. Pero mi ínfima experiencia algo me ha hecho pensar.

 

Vamos ahora al escenario concreto, quiero:

  • que exista una cuenta
  • que tenga shell restringido
  • a la que sólo se pueda acceder vía ssh
    • esto implica no login por consola ni "desplazamiento lateral" tipo su o login

Este comando lo hace:

$ sudo adduser  --shell /usr/bin/rbash --disabled-login  prueba

Si estás modificando un usuario existente, editás /etc/password para que tenga el shell correcto y /etc/password para deshabilitar el login.

También se hace con 

$ sudo passwd -l prueba

Que le agrega a "!" al password existente.

De un modo u otro lo controlás con:

$ sudo grep prueba /etc/passwd /etc/shadow
/etc/passwd:prueba:x:1001:1001:,,,:/home/prueba:/usr/bin/rbash
/etc/shadow:prueba:!:19542:0:99999:7:::

Solo vía ssh, hay que habilitar la key ya que se trata de clientes script, no de personas ingresando claves, aunque con la key un usuario puede entrar.

$ ssh-keygen -f prueba.key -t ecdsa

En la carpeta del usuario prueba, hay que crear .ssh con rwx------ y el archivo authorized_keys con permisos rw------- y el contenido de prueba.key.pub.

 

rbash en acción
rbash en acción

El problema que hay acá es que si ejecutás:

$ ssh prueba@localhost -t bash

sshd ignora el shell de /etc/passwd y te da un shell irrestricto.

 

rbash bypass
rbash bypass

Se arregla de dos maneras, una global y otra específica para cada usuario.


La global es poner en sshd_config esta línea, que no la probé:

ForceCommand rbash

Tiene la ventaja de restringir a todos por si alguno se te escapa, pero si querías tener uno que haga de administrador, vas a tener que ponerle específicamente que pueda ejecutar sudo.
 
La específica para cada usuario es poner no-pty  en  .ssh/authorized_keys
a la key con la que se autentica.Queda algo asi:


no-pty ssh-ed25519 AAAAC3NzaC1....

El problema es que perdés el prompt y bash completion, algo completamente irrelevante para un script.

 
rbash con no-tty en authorized_keys
rbash con no-tty en authorized_keys

 

no login
no login

Mis reflexiones

 

Porque no password al azar

Se podría poner un password al azar, pero al ser un password existente hay una increíblemente remota posibilidad de que alguien le acierte. También que al azar sea un password en un diccionario. O que en el momento de la creación haya leak.

Es mejor poner "!" antes que usar azar pues es un indicador visual y fácil de controlar de modo automático que luego no cambie la situación.

Es mejor dejar solo "!" pues agrega que no haya ninguna posibilidad de login.


Porque no ForceCommand rbash

Si la idea es que en ese equipo no haya ningún usuario remoto sin rbash, de acuerdo con ForceCommand rbash. Pero eso implica que al menos a algún usuario hay que habilitarle que pueda ejecutar sudo, además de las reglas de sudoers.

Me parece más sencillo configurar no-pty en .ssh/authorized_keys para cada usuario a restringir.

Igual en este aspecto mi opinión no es tan fuerte como con el punto anterior. De hecho, mientras escribo esto, no puedo dejar de notar que ForceCommand rbash + sudo responde más a la política de denegar todo y luego permitir de a uno, como que cambiaría de idea muy fácil... listo, ya cambié de idea.

Igual mi instinto algo me dice a favor de no-pty, por el lado de evitar una denegación de servicio. Si vuelvo a cambiar de idea, lo registraré.

Mi posición actual es, depende del perfil de uso del equipo, si es de uso general y hay que restringir a un usuario de servicio, no-pty, si nadie debería acceder salvo ciertas tareas de mantenimiento, ForceCommand rbash + sudo.

 

Disclaimer

No tomes este post como ninguna autoridad de cómo implementar correctamente rbash, no he investigado la parte de las variables de entorno ni sometido a pruebas exhaustivas.

 

 

2023/04/14

Preguntar bien para trabajar

Este artículo es el resultado de la aplicación del concepto, técnica, modalidad o como lo quieras llamar que había registrado antes, en ese momento fue ponerle una descripción a lo que hacía de modo intuitivo y medio inconsciente.

Tras todos estos años, ya de modo conciente de aplicarlo, también lo he extendido desde el aprendizaje al trabajo y hace unos pocos días tuve un evento muy ilustrativo que me disparó escribir esto como actualización.

 

Lo que había dicho en la otra oportunidad se podría resumir así:

Estoy con un problema, hago una pregunta y antes de enviarla, me pongo en el lugar de quien podría contestarla y me imagino que me va a pedir que complete. Lo hago, vuelvo a mirar y cuando ya no puedo hacer nada más, lo envío.

Lo interesante es que cerca de tres de cada cuatro veces, no necesito enviar pues el problema queda resuelto.

 

Lo último que ha ocurrido, está relacionado algo que no es de estudio o hobby pero tampoco es de trabajo, llamemoslo de "responsabilidad profesional", mi colaboración el el proyecto CIAA.

En pocas palabras por si no conocés, es un proyecto de Open Source Hardware y Software (Open de Todo) en el cual vengo colaborando, últimamente en arreglar el sitio cuando algo falla.

La última falla fue por una migración automática que produjo una catarata de dependencias. Estando yo con poco tiempo y sabiendo muy poco de la aplicación solicité ayuda en embebidos.

Fuí muy escueto a propósito, estaba filtrando, buscando más alguien que supiera de antemano que alguna persona solidaria que me ayudara a investigar, no quería pasarle el muerto a algiuen en mi misma situación.

Tres minutos más tarde una persona me contestó en privado, Daniel C.B.

En mi borrador de mail primero expliqué qué había ocurrido y cómo había roto, en este caso la esencia del problema era que php había sido actualizado, entonces tiraba unos deprecated.

Cómo había ido solucionando algunos aspectos, armé un listado tipo problema/solución para ir relatándole lo ya hecho y el bloqueo actual.

Luego noté que había estado aplicando de modo desordenado los pasos de migración [*]. Por completitud entonces comprobé los había hecho y completé los faltantes, que igual, como sospechaba y por eso no los había respetado mucho, no hacían mucha diferencia.


Me puse entonces en el lugar de la persona y pensé, si le paso esto como está, aún con este lindo mail, lo mato. Evalué que para poder hacer un mail mejor, me iba a llevar el mismo o más tiempo que quizás arreglarlo. No estamos hablando de veinte minutos, de hecho me llevó varias horas y un esfuerzo mental considerable.

Pero, magia, otra vez, al estar conforme con las dependencias del mail, el problema ya estaba solucionado... en su mayor parte, ahora quedan algunos detalles de terminación.

Pasamos de la perspectiva de "tomá este sitio que no se puede exponer a Internet" a "¿te podrías fijar que parece que quedó un plugin sin instalar o mal configurado?

 

Lo nuevo


Durante todos estos años extendí la técnica debido a las cadenas de mail de trabajo. Estas suelen ir ampliando su audiencia ("sumo a tal que se encarga de ese aspecto") y a veces se extienden durante varios días sino semanas.


Esto provoca dos cosas: que hay gente nueva en la conversación a la que se le obliga a leer toda la cadena con sus idas y vueltas. Las otras personas, si ha pasado algún tiempo y como todo el mundo lleva siempre varios temas adelante, o no recuerdan o les cuesta.

 

Entonces, una práctica que me autoimpongo y recomiendo es cada tanto hacer un resumen e incluso, borrar las partes superfluas de la conversación del cuerpo principal, sí dejarla por si tengo un error de interpretación que pueda ser detectado.

Quedan entonces uno o dos párrafos diciendo el problema es tal, tal persona sugirió esta causa, la otra otra, tal esta solución y estamos más o menos así.


Como ejemplo tengo reciente que gestionando una vulnerabilidad ocurrió esto:

Se estaba reportando que estaba TLS 1.1 activo y había LUCKY13. El problema es que al revisar el sistema, TLS 1.1 ya no estaba activo y LUCKY13 era potencial debido a unas ciphersuites débiles, que de todos modos eran un defecto por si mismo.

Habían personas que retomaban la cadena con el reporte original, lo cual me producía increibles confusiones.

Entonces, el reporte actualizado, es: hay ciphersuites débiles, su eliminación producirán como efecto colateral la desaparición del potencial LUCKY13

Lo que agrego en esta oportunidad es:

No asumir que todos estamos prestando la misma atención a la conversación ni sabemos lo mismo, hacer frecuentes resúmenes y actualizaciones para no retroceder ni confundir.


Nota:


[*] No es el tema, pero esto me recuerda algo que ocurrió en uno de los cursos que doy. Usamos una VM con unos pasos a seguir en la instalación. Uno de los alumnos en lugar de seguir los pasos next->next->next para configurarla e instalarla se buscó algún video en internet y por supuesto luego no le anduvo, argumentó que "Admito que me salí del manual porque no lo sentí tan practico", lo cual, considerando que cerca de 60 personas lo habían transitado previamente y que cada vez está más refinado, es un tanto subjetivo.

Eh, pero es justo lo que vos hiciste, me vas a decir, ¿por qué no respetaste a rajatabla el procedimiento de migración?

Bueno, la verdad es que en uno de los intentos sí lo había respetado, pero el problema es que procedimiento contempla pasar de una versión a la siguiente, no como era este el caso de... no voy a decir cuántas, muchas... demasiadas...

Quizás el paso más crítico que no respeté, ni lo voy a hacer, es leer el historial de cambios, no me alcanza la vida. Usé mi instinto y sumándole la metodología expuesta, funcionó.







2023/03/06

VirtualBox con Secure Boot

Hago esta nota más para no tener que buscar y recordar. Tomé todo de [1] y [2] y le pongo un poco de mi sabor, pues tengo mezcla con otro tema. De paso queda en spanish.


Tengo una máquina en modo dual boot con Windows 10 y bitlocker por un lado y Ubuntu 22 por el otro. En Windows 10, aparentemente por bitlocker, las virtuales con VirtualBox cada tanto le hacen tirar un BSOD. Mitiga un poco bajar en Execution Cap (de la virtual a usar, Settings -> System -> Processor -> Execution Cap) hasta el piso de lo verde, evitar hacer operaciones intensivas de disco y darle mucha memoria para que evite swappear, pero no alcanza, no puedo tener un BSOD en medio de una charla o taller.

Cuando instalé VirtualBox en Ubuntu, me encontré con un diálogo que nunca había visto, debido a que tiene activado Secure Boot.

No tomé nota bien de qué ofrecía o pedía, algo de una clave para UEFI o similar. Le dije que no, probablemente cancelé cerrando la terminal pues no me dejaba de otra manera. Luego, aun desinstalando y volviendo a instalar no volvió a ofrecerlo, así que no pude documentar.

 

Como efecto colateral me hizo reingresar la key de bitlocker al reiniciar, eso es, tras arruinarme el grub, de ahí en más, arranca directo con Windows.

Esto no es gran problema, cuando quiero arrancar con linux invoco el menú de boot del firmware que reconoce la partición UEFI Ubuntu, con eso se carga el grub y de ahí Ubuntu o si quisiera Windows.


Yendo a lo importante, al intentar ejecutar VirtualBox falla con un mensaje parecido a

 

modprobe vboxdrv failed. Please use 'dmesg' to find out why.
 

dmesg dice:

 

kernel: Lockdown: modprobe: unsigned module loading is restricted; see man kernel_lockdown.7

 

Buscando en internet llegué, tras varios artículos y respuestas diciendo "desactivá Secure Boot", que estupidéz, a uno que aunque bastante viejito es correcto.

Lo que dice es que si tenés Secure Boot, el kernel no te va a dejar insertar módulos que no estén firmados y brinda una manera de firmarlos. No voy a intentar explicar el detalle por que tengo una intuición pero no claridad.

Mi intuición es, para que un módulo esté firmado, hay que hacerlo con un secreto. Ese secreto hay que cargarlo en alguna zona protegida.

 

Esto genera el secreto:

 

$ openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj "/CN=VBox Cert/"

 

Esto firma el módulo con el secreto:

 

$ sudo /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 ./MOK.priv ./MOK.der $(modinfo -n vboxdrv)

 

En mi caso la expansión es:

 

$ sudo /usr/src/linux-headers-5.15.0-48-generic/scripts/sign-file sha256 ./MOK.priv ./MOK.der /lib/modules/5.15.0-48-generic/updates/dkms/vboxdrv.ko

 

Lo mismo para hay que hacer para vboxnetflt.

Esto inicia el proceso de guardar el secreto en la zona protegida, es registrar la key con Secure Boot, te pide un secreto que establece la cadena de confianza rumbo al siguiente paso:

 

$ sudo mokutil --import MOK.der

 

Reiniciás:

 

$ shutdown -r now

 

Todo lo que sigue es la finalización del proceso de guardar el secreto.

Te aparecen unas pantallas ascii azul con un menú sencillo, en este elegís qué vas a hacer

 

Perform MOK management

+-----------------------+
|     Continue Boot     |
|      Enroll MOK       |
| Enroll key from disk  |
| Enroll hash from disk |
+-----------------------+

 

Te permite ver el secreto a registrar o continuar, continuar


[Enroll MOK]

+------------+
| View key 0 |
|  Continue  |
+------------+

 

¿Está usted seguro?

 

Enroll the key(s)?

+---+
|No |
|Yes|
+---+

 

Te pide el password que ingresaste previamente:


Enroll the key(s)?

+-------------------+
| Password:         |
+-------------------+

 

Listo

 

The system must now be rebooted

+--+
|OK|
+--+

 

Con esto se puede comprobar si está enrolado:

 

$ mokutil --test-key MOK.der
MOK.der is already enrolled
 

Con esto listás las keys:

 

$ mokutil --list-enrolled | grep -e "\[key" -e Issuer


[key 1]
        Issuer: C=GB, ST=Isle of Man, L=Douglas,
        O=Canonical Ltd.,
        CN=Canonical Ltd. Master Certificate Authority
[key 2]
        Issuer: CN=mint Secure Boot Module Signature key
[key 3]
        Issuer: CN=VBox Cert




Ese MOK.priv lo podés borrar del sistema tras resguardarlo, por ejemplo dentro del mismo keepass donde guardás las otras claves, en el campo de comentario. Al DER lo pasás antes a ascii con base64.




[1] https://askubuntu.com/questions/760671/could-not-load-vboxdrv-after-upgrade-to-ubuntu-16-04-and-i-want-to-keep-secur

[2] https://sourceware.org/systemtap/wiki/SecureBoot

2023/01/18

La asimetría entre una campaña de EH y un control de seguridad.

En Nerdearla 2022 tuve el privilegio de dar dos charlas, una mía personal que más que un taller era una charla larga, una versión extendida de lo presentado en Flisol 2022 relativa a open hardware, cores y software y otra, en representación de mi trabajo, ésta si una charla de verdad, nacida de una combinación de necesidades y oportunidades, de la aplicación de ML a un problema de seguridad.


El proyecto expuesto trata de cómo hallar información sensible en diversos almacenamientos, en particular credenciales en texto plano en archivos de texto plano en sistemas de archivos utilizando técnicas de ML. Claramente todas estas ideas pueden extenderse otra información sensible en más tipo de archivos (pdf, documentos con formato, planillas) en diversos sistemas (repositorios, páginas web, comprimidos), pero no de modo sencillo ni automático.

 

Sin embargo, el aspecto que quiero destacar en esta entrada no es tanto el diseño  técnico y la arquitectura del sistema, que vendrían a incluir aspectos como lidiar con diversos encodings, realizar la exploración en determinados horarios para no impactar en la disponibilidad de los sistemas a examinar, actualizar el modelo y las reglas de inclusión y exclusión de búsqueda tanto de archivos como de patrones de palabras clave de modo relativamente dinámico para poder aplicarlos durante la ejecución y no tener que esperar a que finalice, considerá que quizás estás recorriendo millones de archivos a lo largo de semanas. De este tema tengo muchísimo elaborado pero poco testeado y además no he revisado soluciones existentes para comparar.


Lo que me interesa y tema de esta entrada nace de esta frase:

 

"(A) Vinieron unos pentesters y revisaron en cierto lugar y (B) encontraron un archivo con una clave que aunque no era la actual  mostraba el patrón de generación (C) lo cual permitió acceder a un sistema donde se encontraron otras credenciales.(D) Tenemos que hacer un control para prevenir esta situación".


Ok, nos gustaría mucho que no ocurra que hayan credenciales en texto plano en primer lugar, para ello existen técnicas de autenticación para evitar que hayan claves en los scripts y concientización para que no hayan claves fuera de los almacenes seguros tipo keepass, pero esto se trata justamente de detectar cuando alguien no las respeta.


Aunque a primera vista no lo parezca, el salto que hay desde (A) unos pentesters... a (D) hacer un control... es abismal y más si pasamos por (B) y (C), veamos el detalle y el contraste:


  • El éxito de una campaña de pentesting se puede alcancar ante el primer hallazgo importante o cuando se alcanza al tiempo límite de ejecución asignado.
  • Ésta campaña, aunque pueda tener mucha asistencia de automatización, es esencialmente manual e interactiva, no hay foco en optimizar aspectos como que un humano no tenga que revisar más de 5.000 líneas, por decir un número para mí razonable. Esto significa que:
    • si el humano se tiene que pasar una tarde mirando una lista de 100.000 líneas candidatas, lo va a hacer.
  • La búsqueda no es exhaustiva, se pueden buscar archivos con nombres clave tipo "claves.txt", con hallar uno alcanza.
  • La frecuencia puede ser tal que sea una o dos veces por año, quizás cada dos años.


 

Contrastemos con un control:

  • La ejecución del control se completa cuando recorre todo el conjunto de activos a revisar y emite su reporte, el cual puede ser contínuo, no hace falta que sea al final.
  • El éxito se alcanza cuando recorre todo y halla todo lo que podría hallar.
  • Debe ser esencialmente automático, el humano sólo debería intervenir para una decisión final acerca de los positivos y realimentar la lógica.
    • En mi experiencia, completamente personal, no debería examinar más de 10.000 líneas. Y pensá que esto hay que repetirlo periódicamente, es esencial que sean pocas líneas.
  • Debe ser permanente, no bien termina de ejecutarse debe comenzar otra vez.
  • Considerando (B) clave pista y (C) que conduce a otro lado, esto es imposible en un control, se hace indispensable la intervención humana.

Esta intervención puede pasar a formar parte del control, pero hay que tener en cuenta que pueden haber mucho "candidatos", una cosa es mirar rápido y ver que "let password = "3234234" amerita contactar al dueño del sistema y otra es que cuando el dueño te contesta "esa clave no se usa más" confiar y seguir escarbando.

Otra es, si el hit fué "let password = $texto", tendrías que ir a ver dónde y cómo se definió $texto, pudo haber sido

let texto = "3234234"

que es un nivel de indirección que nuestro análisis difícilmente pueda interpretar, o peor aún:

let password = exec("proceso.exe", "id_sistema")

donde proceso.exe puede ni siquiera estar presente en el sistema que estamos examinando. No pongo las manos en el fuego pero consideraría esta una técnica válida, esa línea la encontraste en un repositorio y proceso.exe sólo existe en el sistema productivo donde se ejecutará el código.

Existen herramientas de análisis estático de código que son capaces de seguirle el rastro a una cadena de asignación de valores dentro del flujo de un programa, sólo sería cuestión de activarla cuando se detecta que es código fuente, pero bueno, es una complejidad adicional.

En síntesis, la idea está en concordancia con el concepto de la asimetría que hay entre atacante y el defensor, el EH respeta la visión del atacante y el Control la del defensor:

  • El atacante tiene toda la ventaja del tiempo, es lo único que hace.
  • El atacante tiene toda la ventaja de concentrarse en un único conocimiento, el de tal ataque en particular, mientras el defensor debe abarcar de modo obviamente superficial todo el conocimiento de todo lo que defiende.
  • Al atacante le alcanza con un éxito y en última instancia no importa mucho cómo lo consigue.

Entonces la idea es, no sencillo en general modelar un control a partir del resultado de un reporte de EH y en particular en el caso de la frase, probablemente imposible.











2022/10/25

Secure Boot con ESP32c3

Primero hay que leer atentamente la documentación y cuantos más clicks hagas en los links que tiene más vas a comprender todo, elegí para la v4.4. Puse ESP32c3 en el título pero probablemente aplica a Secure Boot V2, que incluye al menos ESP32s2.


El primer programa que se ejecuta es el que está en la ROM, también llamado FSB (First Stage Bootloader), que entre otras cosas se fija si el eFuse de secure boot está activado, ponele que sí. Luego busca el SSB (Second Stage Bootloader) y si tiene hasta 3 firmas agregadas. Utiliza las hasta 3 public keys que pueden haber en los eFuses y si alguna firma está ok, ejecuta el SSB.

 

Arranque normal
Arranque normal


Arranque seguro
Arranque seguro

 

Este hace lo mismo para cada imagen que haya en el resto de la memoria hasta encontrar una válida. Luego, de la aplicación, copia a memoria los datos y programa correspondientes y mapea a la memoria los datos y programas que vayan a quedar en la EEPROM. Por último ejecuta la aplicación.

Para poder llegar a esta situación, tenemos que hacer algunas cositas:

 

Generar las claves

 

En la carpeta de tu elección, pero luego el pem va en cada proyecto.

$ openssl genrsa -out secure_boot_signing_key.pem 3072

No te olvides de agregar un *.pem a tu .gitignore, si llegás a versionar esto, pensá que podrías revocar el certificado en el chip pero sólo tenés lugar para tres.

 

Toolchain


Bajar todo el entorno de esp-idf según las instrucciones del paso 4. Si ya lo tenías de antes, es conveniente que lo actualices.

$ cd ~/esp/esp-idf

$ git pull --recurse-modules

$ ./install.sh esp32,esp32c3,esp32s2

 

Tu proyecto


Para este ejemplo usé CIBS/esp32c3-secure-boot, que es lo mismo que esp32c3-pinout. De un modo u otro, activar el entorno

$ . export.sh

Ir a tu proyecto, si lo tenías ya construido, hacelo papilla con

$ rm -rf build

Para empezar de cero:

$ idf.py set-target esp32c3
$ idf.py menuconfig

# Security features
[*] Enable hardware Secure Boot in bootloader (READ DOCS FIRST)
   Select secure boot version (Enable Secure Boot version 2)  --->
   (X) Enable Secure Boot version 2
[*] Sign binaries during build (NEW)
   (secure_boot_signing_key.pem) Secure boot private signing key (NEW)

# Partition Table  --->
(0xa000) Offset of partition table

 

Ese 0xa000 en lugar del 0x8000 original podría ser opcional pero en mis pruebas dijo:


Bootloader binary size 0x8c30 bytes is too large for partition table offset 0x8000. Bootloader binary can be maximum 0x8000 (32768) bytes unless the partition table offset is increased in the Partition Table section of the project configuration menu.

La tentación es poner 0x8d00, pero tras varias iteraciones, mejor 0xa000, más que por ahí dice que debe ser múltipo de 0x1000.


$ idf.py build

En algún punto va a tirar dos mensajes, uno que gentilmente explica como agregarle firmas al bootloader:

To sign the bootloader with additional private keys.
    /home/iot/.espressif/python_env/idf4.4_py3.10_env/bin/python /home/iot/esp/esp-idf/components/esptool_py/esptool/espsecure.py sign_data -k secure_boot_signing_key2.pem -v 2 --append_signatures -o signed_bootloader.bin build/bootloader/bootloader.bin 

Y otro de cómo grabarlo, hay que hacerlo a mano, sólo cuando hay nuevas keys.


/home/iot/.espressif/python_env/idf4.4_py3.10_env/bin/python  /home/iot/esp/esp-idf/components/esptool_py/esptool/esptool.py --chip esp32c3 --port=(PORT) --baud=(BAUD) --before=default_reset --after=no_reset --no-stub write_flash --flash_mode dio --flash_freq 80m --flash_size 2MB 0x0 /home/iot/ceiot_base/CIBS/esp32c3-secure-boot/build/bootloader/bootloader.bin


¿Qué ponemos en PORT y BAUD?

PORT = /dev/ttyUSB0

BAUD = 115200


Ambos salen de haber visto alguna vez la salida de idf.py monitor:

--- idf_monitor on /dev/ttyUSB0 115200 ---


Luego

$ idf.py flash

$ idf.py monitor

 

Resultados


La primera vez, tal como dice la documentación, sirve para activar, hace falta un reset

Último arranque inseguro

Desde la próxima vez que arranque:


Primer arranque seguro

Notá tanto la diferencia del FSB (en negro) como la del SSB (en verde).

Este proceso en dibujitos:


Setup bootloader
Setup bootloader



Setup App
Setup App



A mi no me salió de una tán fácil, no encontraba la tabla de particiones, no había nada en ésta, horas...


Una de las tantas fallas...
Una de las tantas fallas...

2022/03/02

Vulnerabilidades masivas, continuación

Para quienes no les ha convencido mucho talento vs kpi y se resisten a la aplicación de parches de aplicaciones de terceros a escala, llamemosla, industrial, va un poco más de contexto relativo a cómo se descubren las vulnerabilidades y se puede reaccionar para mitigarlas.


A la hora de localizar vulnerabilidades, veo que hay como tres "zonas":


  • Aplicaciones y componentes de terceros, esto incluye sistemas operativos y aplicaciones de usuario tipo browsers, ofimática, entornos locales de desarrollo e IDEs.
  • Su uso y configuración.
  • Nuestras aplicaciones y componentes propios.

 

El tercero es el terreno del Pentesting, nuestro, lo primero es el Pentesting de sus respectivo creadores u otros interesados, que difícilmente tengan acceso a lo tercero, fin del asunto por hoy.

 

Hay varias maneras de "descubrir" las vulnerabilidades de modo (semi)automatizado, con las inevitables superposiciones, cada manera puede utilizar recursos de las otras.


Por inventario, implica un grado de madurez infernal, es saber que aplicación con qué componentes está desplegada en cada equipo.


Por revisión de repositorios y filesystems, mediante la inspección de maven o node. Te fijás en los entornos previos el código fuente y las dependencias. Por includes/requires, por greps. Por apt list --instaled, por yum list installed, rpm -qa, /var/log/packages, hashes de librerías vulnerables,  lo que sea.

Esta revisión se hace de dos maneras, mediante inspección de cada servidor por acceso remoto, tipo ansible con ssh. Se revisa qué componentes están presentes y las configuraciones. Puede ser una tarea manual, tanto rutinaria como exploradora que alimente a las automatizadas.

La otra manera es inspección de cada servidor por agente, esto es, hay un programa en cada equipo que recibe reglas y busca. Estas reglas se consiguen

La diferencia entre las maneras autenticada/agente radica en el impacto en la topología de la red, los agentes sólo requieren una conexión saliente, los accesos remotos entrante, quizas jump servers, pueden afectar la aislación que tan cuidadosamente habíamos armado.

Por revisión perimetral, banners y otros indicadores cuando no hay acceso autenticado como los dos anteriores.


Todas estas medidas aumentan la superficie de ataque: nuevos accesos de red, nuevos programas instalados, scripts que se ejecutan con privilegios que quizás no son tan bajos como desearíamos. Esos sistemas centralizadores pueden abrir la puerta a nuevos ataques y seamos francos, las aplicaciones de seguridad no necesariamente son seguras, son tan solo otras aplicaciones, pasan a engrosar nuestro inventario de activos sensibles.


La mayor parte de la investigación de seguridad sobre la primera zona es llevado adelante por terceros. Nuestro trabajo, que puede estar resuelto automáticamente, es tener el inventario para saber si y dónde aplicar aplicar los parches cuando aparecen. Ese "cuando aparecen" es crítico, pues si tomamos este ciclo de vida de una vulnerabilidad:

 

existencia | descubrimiento | parche | aplicado
           |<--      difusión     -->|


 

tenemos una ventana de oportunidad entre que se hace pública y apliquemos el parche en el mejor de los casos, si es que no se hace pública antes que el parche esté disponible.

 

existencia | descubrimiento | parche | aplicado
           |<--      difusión     -->|
           |             | workaround|

 

Mientras el parche no esté disponible podemos tomar medidas mitigatorias:

 

  • Desactivar componente
  • Cambiar configuración
  • Proteger en WAF/FW/IPS

 

Desde el mantenimiento del inventario centralizado hasta el salir en el momento a ver donde está tal componente, requiere un cantidad de esfuerzo, que puede no estar priorizado, recordemos que lo importante es que "el negocio funcione", los aspectos tecnológicos estan subordinados a ello y los de seguridad quedan como puro gasto.

Si tenés una política de mantenimiento actualizado, disminuye la necesidad del inventario preciso y pasa a tomar un mayor protagonismo la aplicación de protección perimetral (WAF, IPS, FW),  que es la más sencilla pero sólo se debe aplicar si hay componentes, pues introducen latencia y potenciales falsos negativos, cuanto más larga sea la lista de reglas, más va a demorar el mensaje en circular.

Quizás la mejor táctica sea aplicar toda nueva regla sin evaluar si la necesitás y luego ir viendo si conservarla. Esa purga podría traer el problema de que si a futuro se agrega un nuevo tipo de servicio, no estén las reglas y quede expuesto. Igual en teoría uno no agregaría servicios viejos, pero podría ser resultado de una migración de algo.


Lo que nos resta es el uso y configuración de los componentes de terceros, ahí es donde entra el Talento mencionado en la entrada anterior, donde aplica el "esta vulnerabilidad sólo está activa si está presente la configuración tal", que por un lado es un mitigante pues nos puede ahorrar tener que lidiar en lo inmediato con la vulnerabilidad, pero por el otro nos genera el trabajo de tener que evaluar si está presente la configuración tal y en caso de que estuviera y no se pudiera cambiar, de todos modos hay que aplicar la actualización, haciendo que esa evaluación haya sido trabajo perdido. Además, quizás ahora no está la configuración así, pero quién sabe como estará mañana. Por eso soy partidario de analizar menos y actualizar más.

2022/02/21

Talento vs KPI: Una muerte es una tragedia, un millón, estadísticas

Para lidiar con una vulnerabilidad hay que primero comprenderla, hacer una POC y que funcione, cuantificar cuál es su impacto teórico en términos de Confidencialidad, Integridad y Disponibilidad  y otras dimensiones, por ejemplo aplicando CVSS. Luego, desarrollar algún método de detección, que puede ser tan sencillo como comprobar la versión de una librería a un sofisticado script, programa o plugin de alguna herramienta de seguridad como NMAP o Metasploit que interactúe con el sistema y la explote, preferentemente sin generar efectos colaterales perjudiales. En caso de haber un payload involucrado, desde comprender su funcionamiento a desofuscarlo en caso de lenguajes interpretados hasta una dificilísima ingeniería inversa ya que se trata código de máquina, que puede estar cifrado y ofuscado y nos lleva al hostil terreno del assembly y el conocimiento íntimo del sistema operativo, sin dejar de lado un sencillo análisis de comportamiento en busca de IOCs para alimentar herramientas de detección y prevención.


Habíendo superado esta etapa, evaluar en nuestro despliegue actual según la situación perimetral, la topología de la red, el valor de la información, en otras palabras, un análisis complejo de amenazas para poder determinar el potencial efecto real de esa vulnerabilidad en los distintos puntos del sistema donde puede estar presente y elegir el mejor plan de mitigación, que puede ser eliminar funcionalidades o aplicaciones, aplicar parches o actualizaciones, cambiar valores de configuración, agregar o modificar reglas de IPS, WAF, AV y FW.


A todo esto lo considero Talento, tanto desde la actuación de la gente ciberseguridad en la primera etapa como en la segunda que se suma la de gente de desarrollo, sistemas y administración de seguridad.

 
Hay otro Talento, que es del lado de la arquitectura, diseño y programación de las aplicaciones y servicios. Desde ese punto de vista, hay una inteligencia y optimización orientada a no hacer esfuerzos innecesarios, a intentar comprender. 

Entonces si el reporte de vulnerabilidades dice que hay tal componente vulnerable, correctamente, en lugar de salir corriendo a actualizarlo, este Talento dice, veamos si lo estamos usando de modo tal que la vulnerabilidad se manifieste. Por ejemplo, con Log4Shell, este Talento pregunta, ¿estamos enviando mensajes que vienen desde el usuario al log? Por que si no es así, no hay vulnerabilidad concreta, por favor no me hagas perder mi magro tiempo actualizando algo que no hace falta.
 

En la confluencia entre ambos Talentos, para que ciberseguridad pueda realmente apreciar el impacto de una vulnerabilidad en los sistemas necesita un importante esfuerzo por parte de las demás áreas técnicas.
 

Ahora, imaginemos que no tenemos una sola vulnerabilidad sino que tenemos miles, si, miles, que combinadas con nuestros activos generan combinaciones de centenares de miles de instancias, quizás millones.
 

Poco podemos conservar de la visión enunciada, es como una herida abierta esperando a infectarse, hay que limpiar y proteger, rápido, luego vemos si antibiótico, vendas, reposo. Miles de heridas.
 

Mientras aplicamos las defensas perimetrales, por madurez podríamos intentar identificar esas instancias, pues se dice que es indispensable medir… tarde, ese tiempo es tiempo cedido al atacante.
 

Las vulnerabilidades propias de nuestros sistemas descubiertas por Ethical Hacking pueden esperar un poco, apelando a una falsa seguridad por oscuridad, al atacante le puede costar encontrarlas pues debe interactuar con nuestro sistema. Pero con las que corresponden a elementos de terceros no hacen falta sutilezas, descubrirlas es simplemente correr un script sin ningún pensamiento.
 

Eternal Blue es un ciberataque que encarnado en el ransomware Wannacry es la prueba viviente. En abril de 2017 The Shadow Brokers la publicó tras habérsela robado a la NSA, que la había descubierto cerca de cinco años antes. En mayo de 2017 fue la primera oleada de ataques de la mano del ransomware Wannacry. En marzo de  2017 Microsoft publicó el patch, advertidos por NSA. Casi dos meses transcurrieron desde la disponibilidad del parche hasta su explotación masiva. Una política proactiva de actualización la hubiese convertido en Wannabe.
 

No he oido de explotaciones masivas de Log4shell, algo se ha aprendido desde Wannacy, pues hasta donde he sabido las políticas han sido más o menos:
 

  • En el perímetro se detecta y bloquea cualquier intento de explotación y postexplotación, rápido.
  • Se dan de baja aplicaciones.
  • Se actualizan las librerías.
  • Se aplican mitigaciones por configuración.

 

Estas dos últimas medidas pueden parecer quizás un tanto desprolijas, pero para hacerla correctamente hay que usar Talentos, lo cual hubiese sido un desperdicio.

Hay que aplicar los parches con la única consideración de que los sistemas sigan funcionando, no si hace falta. No va más “si funciona no lo toqués”, ni siquiera hay que esperar a que se detecte que un componente tiene una vulnerabilidad para actualizarlo. Hay que hacerlo permanentemente, quizás no el mismo día que sale cada parche, pero si con una frecuencia muy alta.

Eso pulirá los mecanismos de los equipos de DevOps para afrontar cualquier actualización de urgencia real.
 
Se parece un poco al sistema Chaos Monkey de Netflix, donde a propósito se voltean al azar componentes en producción para forzar a que el sistema de conjunto sea resistente a fallas.

Una deuda, razonable y con paralelismo en Kanban es la de los vulnerabilidades de bajo impacto, equivalentes a las tareas de baja prioridad. En Kanban incluso existe un mecanismo de purga del backlog con el criterio de que si pasaron tantos meses y no se han resuelto ciertas tareas de baja prioridad, entonces no deben tener tanto valor y si lo tienen, renacerán pronto. La vulnerabilidades de bajo impacto que no son resultado de la construcción de nuestro sistema, o sea, las de librerías de terceros y sistemas operativos de soporte, del mismo modo persisten meses o años, pero tienen una diferencia, si se aplica al política de actualización permanente, simplemente disminuirán drásticamente de la mano de las importantes, sin que las hayamos atacado explícitamente.

No me gustan los KPIs, pienso que son dimensiones sacadas de la galera, yo elaboro unos, otra persona otros, seguramente incompatibles e incongruentes. Representan los intereses de distintos Product Owners que quizás estén en conflicto de intereses. No importa, los podemos poner a nuestro servicio, debemos tener menos de tantas vulnerabilidades por equipo, de acuerdo aunque desde el punto de vista del Talento parece ser una muestra de ceguera atroz. Una vez que se reducen los números, podemos recuperar el Talento y comenzar a pensar como atacar las vulnerabilidades más especiales.

El uso de los KPI y la aplicación de parches aparentemente con poca inteligencia, es economía de escala.