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/09/28

Nerdearla 2022 Open de todo, la previa

El taller en realidad no es tan taller, ¿cuántas personas del ámbito de nerdearla tienen una edu-ciaa-fpga, el entorno armado e interés en hacer un taller de esto? Mmmh, poquita. En realidad es una charla larga, es que hay mucho tema pero aprovecho para que quien tenga la edu-ciaa-fpga y ganas, pueda ir probando en el momento, tipo taller.

Tal como he contado mi experiencia en https://seguridad-agile.blogspot.com/2021/09/h4ck3d-2021-configuracion-basica.html, el proceso para poder generar el bitstream es larguísimo. Para facilitar la vida de quien lo haga, he tomado la virtual que uso habitualmente y le apliqué un proceso de limpieza, sanitización y compresión para ahorrar ancho de banda por un lado y para ahorrar espacio en el disco de quien la instale por el otro.


En mis últimos proyectos similares he utilizado para las virtuales Ubuntu Server con xorg y openbox, pero puede ser demasiado minimalista para otras personas, así que en lugar de rehacerlo con Ubuntu Server, reduciendo aún más el tamaño de la imagen, me concentré en quitar. El proceso de limpieza fue eliminar toda aplicación superflua, caches, logs, los repositorios utilizados para la construcción de las toolchains, lo que sea, esto quizás lo detalle en otro post uno de estos días.

Las precauciones que he tomado al exportar es cambiar la contraseñas y fundamentalmente eliminar de .ssh la key que uso para github. Tras el proceso de zerofill y compactación, no debería quedar ningún rastro forense, pero como no tengo garantías, de todos modos también eliminé la key en github.

Reformulando, eliminé la key en github para no tener ningún problema de robo de credenciales y de modo secundario la purgué en la imagen para que nadie que no ha leído esto la encuentre y piense que fuí descuidado. Y fundamentalmente para predicar con el ejemplo.

El repo consideré borrarlo también y que hicieras git clone, pero de un modo u otro tenías que bajarlo, así que lo dejé.


Durante la charla/taller lo que iré mostrando es el proceso asumiendo que ya tenés todo instalado y funcionando, comprenderás que no voy a poder en ese momento resolver ningún problema. Para poder participar del taller probando los ejemplos, es necesario que ejecutes la siguiente secuencia de operaciones, que terminaría en la grabación del bitstream a la placa y como control deberías tener algunos leds cambiantes en la placa y en la terminal serial un menú.

 

Pasos

 

Asumo que si estás jugando con FPGA y más edu-ciaa-fpga, ya tenés bastante experiencia con linux y virtualización. Aún así, cualquier problema que tengas agregalo a los comentarios abajo e iré completando el instructivo.

 

El anfitrión

 

Tenés que agregar tu usuarios a estos grupos:

$ sudo addgroup "$USER" vboxusers

$ sudo addgroup "$USER" dialout

 

Instalá el Extension Pack si no lo tenés.


La imagen

 

La imagen exportada a OVA ocupa unos 3GB y está en un drive.

La virtual importada ocupa al menos 9.3 GB, con el uso no debería crecer mucho, pero considerá que la partición es de 30 GB. Es un Linux Mint 19 o 20, lo cual provée un entorno gráfico agradable.

Desde VirtualBox elegí "File", "Import Appliance"

Yo la uso con 8GB de RAM, pero seguro que anda con menos, mucho menos, tipo 3GB.

Configurá networking en modo bridge 

 

Arranque


Luego la arrancás, el usuario es "Charly", la clave "educiaa", abrís una terminal y averiguás la IP:

$ ip a

El repo está en:

$ cd ~/Desktop/repo/github/cpantel/evilcodesequence

 

El bitstream

 

$ make PROGRAM=fulldemo system 

 

El flasheo

 

Para evitar tener que conectar la placa a la virtual, que es bastante sencillo pero puede ser fuente de inconvenientes, el flasheo se hará desde el anfitrión si es linux, si es windows, vas a tener que hacerle funcionar el USB y flashear desde la VM, vemos luego.

En el anfitrion, ejecutar una sola vez:


$ scp charly@192.168.1.xx:/usr/local/bin/iceprog .


Luego, para cada nueva regeneración del bistream:


$ scp charly@192.168.1.xx:/home/charly/Desktop/REPO/github/cpantel/evilCodeSequence/BUILD/top.bin .

$ ./iceprog top.bin

 

si dice 

 

./iceprog: error while loading shared libraries: libftdi.so.1: cannot open shared object file: No such file or directory

 

Es por que te falta

 

$ sudo apt install libftdi1


Si optaras por conectar directamente la placa a la VM


$ make PROGRAM=fulldemo flash


Considerá que flashear desde el anfitrión que es MUCHO MUCHO más rápido.

Luego, usando tu programa favorito a /dev/ttyUSB1 con velocidad 9600, tendrías que ver algo como esto:

 

Menu
Menu

Jugá con las opciones, mejor la (1) LEDS pues el resto está a medio implementar en la imagen.

Contactame ANTES del taller si algo no te funciona, durante el taller no va a haber tiempo.

Hay otras maneras de obtener un entorno equivalente, ya sea que lo hagas vos de cero o que uses docker, es irrelevante siempre y cuando puedas compilar el programa, construir el bitstream y flashearlo, proveo la virtual como una facilidad.



2022/07/19

Recuperación fallida pantalla bangho, premio consuelo webcam

Me habían regalado una bangho b-n0x1, que tenía de interesante dos slots MiniPCIE, (creo), uno ocupado por WiFi, el otro libre. La prendí, tenía un windows roto, la olvidé. Meses despues la quise prender y nada, murió algo y pasé a modo carroñero.

Disco ok, memoria veremos, teclado se me soltó la tecla de enter, lo más interesante la pantalla, a su lado una webcam...

 

Recuperación fallida


Gracias a un cierto esfuerzo y la generosa colaboración de Pablo Llanos en este hilo de embebidos, pasé de no saber absolutamente nada a saber porqué no puedo usar la pantalla, resumo:

La pantalla es una HannStar HSD100IFW1-A00, que se comunica con LVDS. Por medio de tres pares de cables se transmite:


g[0], r[5], r[4], r[3], r[2], r[1], r[0]
b[1], b[0], g[5], g[4], g[3], g[2], g[1]
de,   vs  , hs  , b[5], b[4], b[3], b[2
]


 
siendo supongo de Display Enable, vs Vertical Sync y hs Horizontal Sync. No importa mucho el detalle pero cuento mi idea, que era, a la usanza de los primeros video juegos, tener algo así como un Video Sync Generator y mediante lógica combinacional generar algo. Pero la frecuencia es de 45MHz, multiplicada por esos 7 bits de más arriba, 315 MHz, completamente fuera de mi alcance generar, tratar adecuadamente, medir o diagnosticar.
 
Luego pensé que si la disposición hubiese sido:
 

de,  g[0], r[5], r[4], r[3], r[2], r[1]
vs,  b[1], b[0], g[5], g[4], g[3], g[2]
hs,  b[5], b[4], b[3], b[2], r[0], g[1]


con las señales de control separadas, podrían haber posibilidades de trabajar a 90MHz, pero eso es en un universo alternativo.

En realidad no es que no sabía nada, estuve adaptando unos ejemplos de verilog que generan VGA, me he hecho un PMOD VGA e implementé un render de VGA en TCL para la salida de una simulación de FPGA, pero de esto nuevo no tenía ni la menor idea.

 

Premio consuelo


Me quedó la cámara web, con un chip que dice ser Aveo AV301W, una datasheet aparentemente compatible que dice "Delock industry USB 2.0 CMOS Kameramodul 1.3", no recuerdo el camino de navegación que me llevó hasta ahí, pero creo recordar que fue por la imagen.

 

Aveo AV301W
Aveo AV301W

 

Este módulo implementa comunicación USB, asi que tomé un cable USB roto, aposté a que la falla estaba cerca del conector del lado del dispositivo, corté, agregue un PCB para poder disociar la soldadura de la correcta conexión, miré los pinouts fijo, soldé y listo.

 

Del lado del cable, elegí "imágenes" en https://www.google.com/search?q=usb+pinout. Dejo como referencia con ASCII Art, viéndolo desde arriba:

 - D+ D-  +

[] [] [] []

 4  3  2  1


En el módulo:


Pin#Signal Name
1+5v
2USB_D-
3USB_D+
4BTN
5GND


BTN es un botón opcional para disparar capturas, no me molesté en conectarlo

Lo enchufé en una vieja Sarmiento y nada.

Superado por tanta derrota, abandoné el proyecto.

Semanas despues, reviví el proyecto.

El motivo de este resucitamiento fue una confluencia de astros: por un lado alguien ofreció hardware en embebidos32, lo que me llevó a cybercirujas, que me puso nuevamente en sintonía con el modo recuperador. Por el otro, con motivo a un proyecto candidato a H4CK3D 2022, estaba viendo una excelente clase de USB a cargo de Pablo Gómez y ví en un diagrama que D+ va con D+ y D- con D-, no como en UART que Rx va con Tx y Tx con Rx y me pregunté si lo había conectado bien. Al revisar, estaba bien conectado, pero no había soldado correctamente el pin de alimentación. 

Corregí, volví a conectar la cámara a la vieja Sarmiento y listo, anda.

Para llevar la sinergía al máximo, hallé tirado en la calle hace meses, sino años, un gabinete de webcam, en perfecto estado.

 

A medio armar


Que de premio extra traía un micrófono:

 

Micrófono
Micrófono


Le hice unas ranuritas, pístola de plástico caliente y listo.

El único problema es que el cable es un poco corto y en la máquina donde más serviría conectarla, con un alargador no anda, en otra si.


2022-10-23, por si algún día retomo https://hackaday.io/project/179868-all-about-laptop-display-reuse/log/193081-common-lvds-laptop-panel-pinouts




2022/05/04

Parte de Flisol 2022

En esta oportunidad expuse un mezcladito de varios open:

Open HW/Core/SW: SoC ICICLE con CPU RISC-V en EDU-CIAA-FPGA

A mi propuesta original que incluía el ataque mostrado en H4CK3D 2021, el Profesor Matías me recomendó podarla para que sea menos técnica. Esa poda fué insuficiente, ya el título es bastante largo y complicado, a la mayor parte de la asistencia no era un tema que le interesara, no importa, para FLISoL 2023 tengo pensado algo más apropiado.

 

Mi idea fue ir evolucionando distintas implementaciones de la luz ondulante de K.I.T.T. hasta llegar a un softcore en FPGA, aprovechando el trabajo de un montón de gente:

 

Historia
Historia

 Lo rojito a la derecha era mi objetivo, lo expuesto en H4CK3D 2021

 

La primera versión es con componentes digitales, la hice hace casi 35 años, un registro de desplazamiento con unas puertas OR animadas a continuación, con un 555 para el clock, unos OR, un flip flop y algún capacitor para  inyectar el primer bit.

Ese bit entra en la primera posición del registro de desplazamiento y en cada tick del clock se va moviendo, con la salida conectada a la entrada con un OR al flip flop que salvo en el arranque siempre está en cero, lo tenemos para siempre. Yendo hacia los leds, con los OR de la derecha transformamos el movimiento en un aparente ida y vuelta.

K.I.T.T. con compuertas digitales
K.I.T.T. con compuertas digitales

 

Comparando precios, el costo es similar a implementarlo con un microcontrolador. Ponemos un bit en uno y lo vamos desplazando para un lado hasta detectar que llegó al punto deseado, ahí invertimos el sentido del movimiento, para siempre.


K.I.T.T. con microcontrolador y lógica específica
K.I.T.T. con microcontrolador y lógica específica

El programa es corto pero complicado e inadaptable a otros patrones. Una versión mejor aunque te indigne desde el punto de vista de la programación es:

while (true) {
  gpio_A.out(1);
  delay(DELAY);
  gpio_A.out(2);
  delay(DELAY);
  gpio_A.out(4);
  delay(DELAY);
  gpio_A.out(8);
  delay(DELAY);
  gpio_A.out(16);
  delay(DELAY);
  gpio_A.out(8);
  delay(DELAY);
  gpio_A.out(4);
  delay(DELAY);
  gpio_A.out(2);
  delay(DELAY);
  gpio_A.out(1);
  delay(DELAY);
}

¿Por qué me atrevo a incluir esta manera? Pues por que es el precursor para esta version más linda, en lugar de código hardcodeado, la información está en un array:

unsigned int out[]={1,2,4,8,16,8,4,2,1};
int pos = 0;
int limit = sizeof(out)/sizeof(out[0]);

while ( true) {
  gpio_A.out(1);
  delay(DELAY);
  ++pos;
  if (pos == limit) {
    pos = 0;
  }
}

y esto se parece mucho a la implementación nuevamente con componentes digitales.

K.I.T.T. con contador y memoria
K.I.T.T. con contador y memoria
 

Ahora, tanto en hardware como en software, podemos con gran facilidad mostrar otros patrones manipulando la memoria o el array según corresponda:

 

K.I.T.T. con contador y memoria y patrones arbitrarios
K.I.T.T. con contador y memoria y patrones arbitrarios

 

En la charla acompañando a esta evolución también fui contando como funciona una computadora a un nivel más bajo, que me cuesta mucho convertir a este formato, quizás haga un video en algún momento, lamentablemente no pude grabar la sesión.


Eso llevó a la explicación de FPGA y RISC-V, desembocando en el tema que me interesaba, la implementación primero en Verilog de la versión con lógica, como dispositivo incluido en el SoC icicle:

https://github.com/cpantel/evilCodeSequence/blob/master/kitt.sv

module kitt #( parameter BASETIME) (
    input clk,
    input reset,
    output [4:0]display_out,
    /* memory bus */
    input [31:0] address_in,
    input sel_in,
    //input read_in,
    //output logic [31:0] read_value_out,
    input [3:0] write_mask_in,
    input [31:0] write_value_in,
    output logic ready_out
);

    logic [25:0]q;
    logic direction;
    logic [4:0]display;

    assign ready_out = sel_in;
    assign display_out = display;

    always_ff @(posedge clk) begin
        if (reset) begin
            display <= 1;
            direction <= 1;
        end else if ( q > ( BASETIME / 1000 * 300 ) ) begin
            q <= 0;
            if (direction ) begin
                 if ( display[4] ) begin
                     direction = ~ direction;
                     display <= display >> 1;
                 end else
                     display <= display << 1;
            end else begin
                 if ( display[0] ) begin
                     direction = ~ direction;
                     display <= display << 1;
                 end else
                     display <= display >> 1;
            end 
       end else begin
            q <= q + 1;
            display <= display;
       end
    end

endmodule

 

Y por software, de modo concurrente y absolutamente independiente, ejecutándose en la CPU:

 

/*
  This program implements a SW kitt
*/

#include <stdint.h>
#include "../memmap.h"
#include "../uart.h"
#include "../delay.h"


int main() {
    uart_init();

    uart_puts("KITT starting\r\n");
    for (;;) {
        LEDS = 1;
        delay();
        LEDS = 2;
        delay();
        LEDS = 4;
        delay();
        LEDS = 8;
        delay();
        LEDS = 4;
        delay();
        LEDS = 2;
        delay();
        uart_puts("KITT .\r\n");
    }
}

 

 

Si algo entendés de Verilog, te darás cuenta que ese dispositivo como que está en vano conectado a los buses, ya que no hay nada con lo que el programa en la CPU pueda interactuar. Es que me quedé sin tiempo, querría al menos haberle permitido cambiar la velocidad.

En una próxima entrega espero no muy lejana, mostraré la implementación de un nuevo dispositivo que he de llamar "sequencer", que consistirá en una lógica que lea un trozo de memoria y lo exponga en los leds (vía PMOD como es ahora kitt) y que desde el programa se pueda arrancar, detener, pausar, cambiar la velocidad y modificar esa memoria.


 

 



2022/04/29

Buscando capacitación introductoria de SQL

En el marco de las cosas que estoy haciendo de IOT, andaba necesitando hallar capacitación gratuita de SQL para recomendar y lo primero que se me ocurrió fue buscar en Oracle, ya que tiene OracleDB y también MySQL. De paso busqué en Udemy filtrando con free, esta es mi experiencia. Aclaro que mi visión de todos estos cursos es un tanto limitada pues yo ya sé SQL, como que sólo puedo decir más o menos que tan completos o comprensibles son, destacando cuando hay algo interesante.

 

Oracle

El curso que hallé es https://devgym.oracle.com/pls/apex/dg/class/databases-for-developers-foundations.html dice que se puede hacer en unas 6 horas. Al comienzo me agarró una sensación de que aunque simpático era medio inusable, recién en el tercer bloque entré en sintonía. y empecé a considerarlo útil.

Tenés que darte de alta en:

  • https://www.oracle.com/index.html
  • view accounts
  • Oracle account
  • Create account

no hace falta cloud account, se puede usar gmail.

 

Tuve algunas dificultades con el SSO pero creo que fué más de capa ocho. Utilicé el método de preparar el mejor mensaje de consulta posible, esto es revisar a conciencia cada paso imaginándo qué me iban a preguntar y llegué a que tenía mal puesta la dirección en el keepass, lo cual me daba un comportamiento errático porque a veces copiaba esta dirección y a veces la llenaba a mano, muy confuso y difícil de diagnosticar.

Seguramente el comportamiento errático fue 100% por lo mío, pero como quedé medio traumatizado,  hago el login en oracle.com y luego voy a cada subsistema.

Cada módulo tiene varias secciones:
 

El video

 
Es muy simpático y aparentemente superficial, pero si prestás antención son muy didácticos.
 

Take live sql tutorial

 
Para los ejercicios tenés tres opciones, copio y pego:
 
 
 
Sólo probé la última. Cuando entrás en la sección  arriba a la derecha te ofrece login al laboraratorio
 
login
login

 
 
Luego a la derecha te replica los enunciados que tenías, asi no tenés que estar yendo y viniendo de tab.
 
enunciados
enunciados


 
Algunos tiene un botón de prerequistos. Todas las instrucciones las podés copiar y pegar o enviar directamente al editor, yo te recomiendo que las transcribas, es una manera de ir memorizando.
 

Further study

 
Respecto a esta sección, si estuviera corto de tiempo y tuviera que priorizar, les prestaría atencion a estos:
 

https://blog.jooq.org/say-no-to-venn-diagrams-when-explaining-joins/
https://blog.jooq.org/a-beginners-guide-to-the-true-order-of-sql-operations

 
En general, cuando te referencia a From Oracle Database 11g Release 2 Documentation Library y From Oracle-BASE son algo heavy, es el manual.
 

No relacionales

 
Menciona modelos no relacionales como Document Storage pero medio para apalearlos, obviamente son los amigos relaciones.
 

Si tu objetivo es el mismo que yo exploré, que es tener una idea de cómo operar sin meterte en detalles finos como los distintos tipos de bases de datos, o sea, si con
  • create table
  • insert
  • select
  • update
  • delete
  • una idea básica de cómo modelar y normalizar
te contenta y no partís completamente de cero, te puede servir. No le prestaría mucha atención al módulo de multi insert. Si lo tomás por favor dejame un comentario.

Cursos de Udemy


Udemy no es gratis, pero hay algunos cursos en algunos momentos que lo son, paso a detallar mi experiencia.

A beginner's guide to MySQL


https://www.udemy.com/course/mysql-basics

Media hora, inglés no nativo, mediocre.

Me hizo notar un detalle, que si no estás en embebidos ni se te pasa por la cabeza:

Para ejecutar MySQL necesitás un sistema operativo, al igual que con Erlang. Resultaría interesante saber que opciones hay para un sistema embebido baremetal o con FreeRTOS. Es difícil de buscar pues "database server bare metal" te lleva a la definión en el contexto de bases de datos que es tener el sistema operativo y nada más que el servidor de base de datos.
 
Otra dificultad es que al buscar "embedded database" ser refiere a un servidor que se puede incluir en la aplicación, por ejemplo para un servidor web en java existe  Jetty, https://github.com/cpantel/boxControl.

Busquemos entonces con "sqlite freertos" y tras varios saltos llegamos a https://sqlite.org/custombuild.html, mmh, podría... hacerlo otra persona, olvidemos el asunto pero sin olvidar que existe una opción comercial https://www.ittia.com/products/ittia-db-iot que parece interesante.

Volviendo al curso, empieza horrible, leyendo las presentación, luego mejora, va mostrando ejemplos de operaciones sin entrar en mucho detalle conceptual.


Lo que más me sirvió de toda esta experiencia es que repasé que para comparar con NULL es no es valor = NULL sino isnull valor, que de algún modo asocié en clase de Testing de Sistemas IoT que alguien había puesto en javascript:

if (value != NaN)

y cuando falló le pude sugerir que era

if ( isNaN(value) )



Me quedaron pendientes para otra vida:


2022/03/21

ESP32 con BMP280

En el marco del mínimo sistema IoT que he preparado para la futura materia Implementación de IoT, mientras se confeccionaba la lista de materiales para la carrera completa, hubo discusión acerca de si usar DHT11 o BMP280, ambos sensores de temperatura.


  • El DHT11 es más barato, usa un solo pin, pero es menos preciso.
  • El BMP280 usa I2C, dos pines y se deduce de la frase anterior que es más caro y preciso.

 

Lo que no se deduce es que el primero mide temperatura y humedad y el segundo además presión, salvo el modelo que he conseguido que no mide humedad.

Al DHT11, dependiendo de la presentación hace falta agregarle un resistencia de entre 5 a 10 K, le he puesto unas SMD rescatadas de unas viejas placas de una central telefónica hallada en un volquete en el centro cerca del trabajo.

 

DHT11 con resistencia SMD en los pines
DHT11 con resistencia SMD en los pines

 

Había implementado todo para DHT11 pero entre que las otras materias no lo iban a usar y que para ESP32c3 no funcionó, incorporé el BMP280 al ESP32c3 y luego al ESP32, llegando al punto de poder retirar al DHT11 de la lista de materiales, discusión resuelta. De todos modos quedó en el repo disponible.


Para la adaptación no hay ningún sufrimiento, hay que tomar la implementación con DHT11, borrar lo específico y reemplazarlo con el código de ejemplo de UncleRus, que es básicamente un include, elegir los pines, armar una estructura, inicializar y leer.

 

Respecto a los pines, a diferencia de DHT11 que usa un protocolo serial OneWire por software y se puede implementar en cualquier pin GPIO, BMP280 usa I2C por hardware, supuse que debía ser un subconjunto bastante menor.


Busqué en esp32-wroom-32_datasheet_en.pdf y nada. Por suerte luego hallé un tutorial https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/ que decía que:

 

the SDA line may also be labeled as SDI and the SCL line as SCK.

 

y luego que se podían mapear a casi cualquier pin, supuse mal.

 

Alguna líneas interesantes del código, en estas se determina que chip es: 


bool bme280p = dev.id == BME280_CHIP_ID;
ESP_LOGI(TAG, \
    "BMP280: found %s\n", bme280p ? "BME280" : "BMP280");

 

Luego se manifiesta en los valores que se pueden completar:


if (bmp280_read_float( \
          &dev, \
          &temperature, \
          &pressure, \
          &humidity) != ESP_OK) {
  ESP_LOGI(TAG, "Temp./press. reading failed\n");
} else {
  ESP_LOGI(TAG, \
    "Press: %.2f Pa, Temp: %.2f C", pressure, temperature);
 

//if (bme280p) {
    sprintf(send_buf, REQUEST_POST, temperature , humidity );
//} else {
//    sprintf(send_buf, REQUEST_POST, temperature , 0);
//}

 

Lo dejé comantado pues la verdad es que me dá lo mismo mandar un cero hardcodeado que uno proveniente de la lectura, pero es incorrecto, debería no enviar el valor y/o agregar un campo con el tipo de sensor, para diferenciar el cero de cero humedad del cero de cero lectura.

Este sistema está todo hecho así, una reducción muy básica con múltiples oportunidades de completar y mejorar. Si te viene interesando, podés implementarlo siguiendo las instrucciones y luego:

  • Agregar campos para reportar errores.
  • Agregar timestamp, pensá donde...
  • Enviar JSON en lugar de x-www-form-urlencoded.
  • Implementar algún DNS para usar nombres en lugar de IPs. 
  • Usar https en lugar de http.
  • Envíar vía MQTT en lugar de HTTP-POST.

Truquito, en el router fijá la MAC address del servidor a una IP y te va a facilitar la vida.

Se supone que quizás viste todo esto antes de llegar hasta acá:


https://seguridad-agile.blogspot.com/2022/03/ejemplo-de-esp8266-con-lectura-de-dht11planB.html


https://seguridad-agile.blogspot.com/2022/02/ejemplo-de-esp32-con-lectura-de-dht11.html


https://seguridad-agile.blogspot.com/2022/02/primer-contacto-con-esp32.html




 



2022/03/19

Ejemplo de ESP8266 con lectura de DHT11: Plan B

Venimos de un momentáneo fracaso.

 

Plan B

 

La gente que viene de sistemas embebidos siente un cierto desprecio por ArduinoIDE debido al alto nivel de abstracción, te pasaste años estudiando como funciona una CPU, un microcontrolador, viendo como se configura bit a bit cada dispositivo y ArduinoIDE te lo reduce a un .setup() y obviamente en situaciones anormales no tenés recursos y probablemente hayas perdido el RealTime.

Se parece al desprecio que sentimos los que venimos del otro lado al ver como con cualquier gestor de Cloud cualquier iletrado puede armar cosas bastante complejas, completamente inconcientes de cómo instalar y configurar un sistema operativo, base de datos, servidor de lo que sea, optimización y hardening. No importa, no quiero ninguna flame war.


Te bajás ArduinoIDE de 

https://www.arduino.cc/en/software
 
Descomprimís:
 
tar -xf ../Downloads/arduino-1.8.19-linux64.tar.xz 

Primero no hice el install.sh pues mirándolo por encima no parecía aportar nada, luego al ver que no aparecía el programmer en tools, ejecuté arduino-linux-setup.sh, pero no era por eso, el flash se hace directamente.

Para ejecutar:

./arduino

Hay que agregar el board con 

  • File
    • Preferences
      • Additional Boars Manager URLs: 

ahí ponés

http://arduino.esp8266.com/stable/package_esp8266com_index.json

 

Luego vás a 

  • Tools 
    • Board
      • Board Manager
        • search: esp8266
          • esp8266 by ESP8266 Community
            • Install
    • Board
      • ESP8266 Boards
        • ESP Generic  Module
    • Port 
      • /dev/ttyUSB0
    • Manage Libraries
      • filtrar por dht
        • DHT Sensor Library for ESPx 
          • install


Para el DHT quise apoyarme en lo aprendido antes, pero no me sirvió, lo que hice fue incorporar DHT Sensor Library for ESPx
 
 
 
Y funcionó ok con el siguiente programa, que es una mezcla entre los ejemplos:
  • File
    • Examples
      • Examples for Generic ESP8266 Module
        • ESP8266HTTPClient
          • PostHTTPClient
      • Examples for Custom Libraries
        • DHT_sensor_library_for_ESPxDHT_ESP8266


#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

#include "DHTesp.h"
 
#define DEVICE_ID "61"
#define SERVER_IP "192.168.0.100:8080"

#define STASSID "" <- recordá no versionar
#define STAPSK  "" <- recordá no versionar
 
DHTesp dht;

float humidity = 0.0;
float temperature = 0.0;

void setup() {
  delay(10000);

  Serial.begin(115200);

  Serial.println("ESP8266 DHT HTTP POST");
 
  dht.setup(2, DHTesp::DHT11);
  delay(dht.getMinimumSamplingPeriod());

  Serial.println(dht.getStatusString());
  humidity    = dht.getHumidity();
  temperature = dht.getTemperature();
  Serial.print("Temperature : ");
  Serial.println(temperature);
  Serial.print("Humidity : ");
  Serial.println(humidity);

  WiFi.begin(STASSID, STAPSK);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  // wait for WiFi connection
  if ((WiFi.status() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;

    Serial.print("[HTTP] begin...\n");
    // configure traged server and url
    http.begin(client,
"http://" SERVER_IP "/measurement"); //HTTP http.addHeader("Content-Type", "application/x-www-form-urlencoded"
    );

    Serial.print("[HTTP] POST...\n");
    // start connection and send HTTP header and body
    String post("id=");
    post += DEVICE_ID;
    post += "&t=";
    post += temperature;
    post += "&h=";
    post += humidity;
    int httpCode = http.POST(post);

    // httpCode will be negative on error
    if (httpCode > 0) {
      Serial.printf("[HTTP] POST... code: %d\n", \
           httpCode);

      // file found at server
      if (httpCode == HTTP_CODE_OK) {
        const String& payload = http.getString();
        Serial.println("received payload:\n<<");
        Serial.println(payload);
        Serial.println(">>");
      }
    } else {
      Serial.printf( \
           "[HTTP] POST... failed, error: %s\n", \
           http.errorToString(httpCode).c_str());
    }

    http.end();
  }

  delay(10000);
}

 
El código bastante parecido está en github en la carpeta esp8266-arduino. En esp8266 dejé la fallada con esp-idf.
 
Nos quedó asi:
 
~/esp/
     /esp-idf
     /esp-idf-lib
     /ESP8266_RTOS_SDK
     /arduino-1.8.19
     /ceiot/
           /esp32
           /esp32c3
           /esp32s2
           /esp8266
           /esp8266-arduino 




Ejemplo de ESP8266 con lectura de DHT11

Hace ya un tiempo exploré como lidiar con el entorno de desarrollo de ESP8266. Mientras incorporaba esa arquitectura a un proyecto educativo que consiste en leer un sensor de temperatura DHT11 y transmitirlo por HTTP-POST, me encontré con que las instrucciones que tenía quizás ya no son vigentes.

El proceso es similar a cómo se hace con ESP32 y acá lo mostraré adaptado. 

 

No tomes este camino

Si no tenés curiosidad por mis desgracias, andá directo al Plan B más abajo.

Si lo tomás, tené en cuenta que te rompe la instalación de esp-idf.

 

Plan A

La estructura de archivos que es esta:

~/esp/
     /esp-idf
     /esp-idf-lib
     /ESP8266_RTOS_SDK
     /ceiot/
           /esp32
           /esp32c3
           /esp32s2
           /esp8266

Resaltado lo que vamos a agregar.

esp-idf es la SDK para ESP32, esp-idf-lib son componentes de un tal RusLand.

Vamos a suponer que al haber instalado previamente todo lo necesario para esp-idf, si siguieras los siguientes pasos en una máquina limpia quizás no alcanzaría.


$ git clone https://github.com/espressif/ESP8266_RTOS_SDK.git
$ cd ESP8266_RTOS_SDK.git
$ git checkout origin/release/v3.4
$ sudo apt install python3-pip python-setuptools libncurses5-dev
$ /usr/bin/python3 -m pip install --user -r requirements.txt
$ ./install.sh
$ . export.sh



Mirando por encima requirements.txt, que es lo que consume install.sh apreciarás que hay poca superposición.

 
export.sh te genera un entorno para que funcionen los make posteriores y se debe ejecutar en cada terminal que abrás. Si te falla por que no encuentra python, la primera tentación es ponerse a modificar las referencias a python por python2 o python3 en mi caso, primero en export.sh y luego en otras partes. Mala idea, lo mejor, recordando que tengo armada una virtual sólo para esto, es:
 

sudo ln -s /usr/bin/python3 /usr/bin/python

El problema de hacer esto es que te rompe luego lo que tengas para ESP32.

Así que tenés que estar alternando con:

sudo rm /usr/bin/python

Como no pienso hacer mucho es ESP8266, alternaré. Si luego se me ocurre algo mejor o alguien lo tiene, me lo pasa y lo pongo.
 
Si prestaste atención a cómo se hace en ESP32, habrás notado que acá no existe el paso para determinar que chip usas:
 
idf.py set-target esp8266

Esto es porque hay múltiples ESP32, como ESP32, ESP32c3, ESPs2 para mencionar algunos y sólo hay un ESP8266.

Listo para el build. Pero antes, incorporemos el proyecto, lo que hay uno tiene la tentación de hacer es (no hacer):
 
 
mkdir esp8266
cd esp32
cp CMakeLists.txt -r main/ Makefile ../esp8266
cd ../esp8266
 
 
Pero no, equivocado, lo que hay que hacer es:
 
cp -r ../ESP8266_RTOS_SDK/examples/wifi/getting_started/station .
mv station esp8266
# modificar el programa tal como con ESP32
 
 
Para la configuración de los componente, en este caso credenciales de WiFi:
 
make menuconfig

 
No te olvides de borrarlas al versionar .

Finalmente, para que funcione la parte del DHT11, hay que tocar el Makefile:

EXTRA_COMPONENT_DIRS += $(IDF_PATH)/../esp-idf-lib/components


Y ahora si

make 
make flash
make monitor


No tan fácil...

Habían varios errores simultáneos que me confundieron. Algunos relacionados con la inclusión de archivos, otros quizás relativos a los branches de cada repositorio, en una conversación en embebidos quedó registrado parte de esto, no aporta que lo repita acá.
 
Lo más significativo de esa conversación es que si hubiera leido el manual quizás hubiera detectado que hay componentes no soportados de esp-idf-lib en ESP8266 y que hay que excluirlos del proceso de compilación.

La receta resultante es, por ahora:
 
Usar los tags v3.4 y v0.8.2 (esp-idf y esp-idf-lib respectivamente)
 
En el Makefile, para que incluya esp-idf-lib:
 
EXTRA_COMPONENT_DIRS += $(IDF_PATH)/../esp-idf-lib/components
 
para que excluya los componentes no soportados:

EXCLUDE_COMPONENTS := max7219 mcp23x17 led_strip max31865 ls7366r hts221
 
 
Aún así, aunque compila no funciona:
 
 
...a ver...


Reconectando...
Reconectando...


 
Mmmh, fijate que intenta conectar a como dé lugar, habría que agregar un mensajito de log tal como he resaltado:

static void on_wifi_disconnect(void *arg, 
                        esp_event_base_t event_base,
                        int32_t event_id,
                        void *event_data){
  system_event_sta_disconnected_t *event =
     (system_event_sta_disconnected_t *)event_data;
 
  ESP_LOGI(TAG, 
            "Wi-Fi disconnected reason %d\n\r",
            event->reason);   

  ESP_LOGI(TAG,"Wi-Fi disconnected, trying to reconnect...");
  if (event->reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT){
      /*Switch to 802.11 bgn mode */

      esp_wifi_set_protocol(
         ESP_IF_WIFI_STA,
         WIFI_PROTOCOL_11B | 
         WIFI_PROTOCOL_11G |
         WIFI_PROTOCOL_11N);
  }
  ESP_ERROR_CHECK(esp_wifi_connect());
}


Si querés ver que hace esp_wifi_connect, no existe, me parece que está implementado en ROM o similar en el chip.

Ahora dice:

phy_version: 1163.0, 665d56c, Jun 24 2020, 10:00:08, RTOS new
I (415) phy_init: phy ver: 1163_0
I (426) example_connect: Connecting to thebox...
I (3217) wifi:state: 0 -> 2 (b0)
I (4217) wifi:state: 2 -> 0 (200)
I (4218) example_connect: Wi-Fi disconnected reason 2

I (4220) example_connect: Wi-Fi disconnected, trying to reconnect...
I (6286) example_connect: Wi-Fi disconnected reason 205




Las event-reasons están en components/esp8266/include/esp_wifi_types.h, son un montón y se llaman wifi_err_reason_t.

WIFI_REASON_AUTH_EXPIRE       = 2
WIFI_REASON_CONNECTION_FAIL   = 205 

 
¿Qué si probé con reiniciar el router? ¡Claro! antes de usar linux usaba windows...

Probé con
 
make menuconfig -> 
   Component config  --->
    Wi-Fi  --->
[*] Enable WiFi debug log (ESP8266_WIFI_DEBUG_LOG_ENABLE)
 
 
Pero no hallé como acceder o interactuar con ese log.
 

 
Me pasé al ejemplo más básico, station, para reducir variables, probé todo lo que sigue:
 
  • ESP8266_PHY_MAX_WIFI_TX_POWER, ya está en 20, pasé a 21Cambié de canal en el AP, del 11 al 1 y al 6 
  • Puse modo B only
  • Puse modo G only
  • Puse modo N only
  • AES en lugar de TKIP + AES
  • a 30 centímetros del AP
  • Branches v3.3 y v3.3-rc1
  • Cambié de router
  • Probé con 20 y 40 MHz de ancho

 
No encuentro más recursos, sólo esta pista:

WiFi.hostname("ESP-host"); before WiFi.begin(ssid, password);

Pero eso es con ArduinoIDE.

Me quedaría armar un Access Point para diagnosticar desde ese lado o buscar como hacer sniffing, quedará para otra vez.



2022/03/03

Por qué IoT y sistemas embebidos si trabajás en un banco

...o cualquier trabajo que aparentemente no tenga sistemas embebidos ni nada que ver con IoT.

 

Buena pregunta, un banco es el terreno del mainframe rodeado de bases de datos y servidores diversos que atienden vía web en el home banking, en las aplicaciones mobile, por terminales diversas a empleados, en ATM, en encoladores, dispensadores de tarjetas y ahí ya te estoy contestando un poco, pues todos estos últimos vienen a ser el terreno de los SSEE.

Que un sistema esté implementado con "commodity hardware", off-the-shelf cómo le dicen, es una cuestión completamente táctica, no afecta su esencia.

Tenemos a grandes rasgos que si una computadora lo que más hace es operaciones específicas atendiendo quizás multitud de orígenes, le decimos servidor. Puede tener pantalla y teclado, es irrelevante. Puede ser una raspberry-pi, su función es servidor. Si tenemos un montón dependiendo de como estén organizadas, son cloud, farms, supercomputadoras.

Tenemos que si tiene KVM (Keyboard Video Mouse - Teclado Video Mouse) y es de uso general, ya sea en formato laptop o desktop, le decimos "Estación de Trabajo", la compu, una PC.

Si en lugar de KVM tiene una pantalla táctil y un par de botones, funciona con batería, entra en el bolsillo y tiene wifi y pegada una línea de teléfono somos lo suficientemente smart para denominarlo "mobile".

Una y otra vez, no dejan de ser computadoras.

Cuando tenemos una computadora que tiene un teclado loco o ni tiene, que anda en batería encima de un poste o bajo tierra, que maneja a una máquina, que es tan chica que apenas le entra un hello world, que la mayor parte del tiempo se la pasa durmiendo, se despierta unos milisegundos, mide un sensor, lo transmite y vuelve a dormir, que desde que se prende ejecuta el mismo conjunto de programas en lugar de ir ejecutar programas arbitrarios, que en realidad son varias distintas haciendo lo mismo y comparando que estén haciendo realmente lo mismo, que es tán... lo que sea, estamos en el terreno de los SSEE.

Si no tiene nada salvo un montón de conexiones de red, como un switch, un router, un firewall, balanceador de carga, es equipamiento de comunicaciones, SE.

Entonces, una PC común dentro de un ATM, un sistema de dispensador de turnos o de reconocimiento facial, no es una PC, es un SE. Para contrastar, una raspberry-pi a la cual le conectás KVM y no usas los GPIO (los cablecitos para leer botones y prender leds) para mi deja de ser un SE y pasa a ser una PC.

No es lo mismo sin embargo un SE que nace como tal y se usa como SE que usar una PC con el mismo propósito. Esto es en parte por el hardware, que en la PC es de uso general, debe funcionar lo mejor posible en situaciones muy distintas. Contrastando, los SSEE acostumbran usar hardware especializado para lo que van a hacer, pueden estar optimizados para bajo consumo, tiempo real, mínima latencia, infernal paralelismo, ínfimo precio, obviamente no todos a la vez, es como la regla del PM: rápido, barato, bueno, elegí sólo dos.

En el motor de un auto debe ir inevitablemente un SE, pues una PC no soporta las vibraciones, temperaturas y ruido eléctrico ni los requerimientos de tiempo real de que la chispa ocurra en ese preciso instante.

En un equipo médico de soporte vital debe ir un SE, pues no puede colgarse ni ponerse a hacer otra cosa que la que está haciendo.

En un ATM, será más lenta la PC o consumirá más que el SE, pero no hay actividades críticas a nivel de hardware. En realidad si hay pero a nivel de cada dispositivo, el lector de la autenticación, el lector de cheques, el expendedor, que  tienen su propio SE, orquestados por la PC. Es por eso que en un ATM se puede usar una PC, por que las actividades especiales no las lleva adelante la PC, si no estos SSEE específicos.

No es nada novedoso, incluso dentro de la PC hay SSEE, como la controladora de disco rígido, ya he lidiado con eso al intentar rescatar un microcontrolador 8051 de un disco. El teclado tiene un microcontrolador, es un SE.

Siguiendo por el resto del banco, de modo directo tenemos esos SSEE y de modo indirecto, de soporte tenemos cámaras IP, sistemas de alarmas, control de acceso, la controladora de los ascensores si los hay, aire acondicionado.

Si por algún motivo se pudiera saltar de la red de las cámaras IP o cualquier otro sistema de soporte a las otras redes, entonces la seguridad de esas redes nos interesa tanto como la propia del "negocio".

Este salto puede ser por compartir la red aunque esté segregada de modo lógico (buscá VLAN), puede haber un componente con una patita en cada red, pueden tener un almacenamiento o servidor común en Cloud.

 

Falta IoT

 

IoT parece ser un montón de dispositivos (evidentemente SSEE) comunicándose entre ellos o con servidores, recolectando información y actuando. Por ejemplo ese coso que se llama Alexa que le decís "quiero escuchar música de ascensor" y te pasa esa música por el SmartTV, o que controles algún automatismo de tu casa desde el SmartPhone o que si bajó el nivel de humedad de las macetas y no hay pronóstico de lluvia cercano, se abra una válvula y haya riego.

La clave que diferencia o mejor dicho lo que extiende SSEE a IoT es la comunicación. Un lavarropas por mucho microcontrolador que tenga, si no tiene conexión a algo, no es IoT. Y claramente la comunicación no es un mero capricho de la gente de marketing, es para poder controlar el lavaropas remotamente y/o poder obtener telemetría.

Un componente con un protagonismo no del todo evidente en todos esos ejemplos es que buena parte de la inteligencia no está en los dispositivos, está en algún servidor o conjunto, ya sea en Cloud o en un servidor local. Y lo interesante es que la complejidad y extensión de estos servidores es probablemente siempre superior a la de los dispositivos. Y quizás fundamentalmente, los datos y el control están en esos servidores.

En el caso de Alexa, el dispositivo probablemente sea un microcontrolador con un parlante, un micrófono, una conexión wifi y otra bluetooth. El código seguramente sea un loop que va comprimiendo y transfiriendo el audio a Cloud, donde es reconocido y se generan los comandos que luego se envían al SmartTV, sistema un poco más complicado pero no por el aspecto IoT, la parte IoT es sólo que ejecute una acción que normalmente se hace manualmente. De hecho, si se usara siempre con Alexa, se podría simplificar, ser menos Smart.

 

Visión IoT vs SSEE
Visión IoT vs SSEE

 

Este gráfico es una simplificación extrema, las formas tan pronunciadas son para no entrar en discusiones de detalles de cuál sería la verdadera forma, si más redonditas. Pensá que SSEE en principio no tiene nada que ver con los servidores de la izquierda, pero para comprender bien el funcionamiento de estos tenés que saber de arquitectura de computadoras y eso claramente no es terreno de IoT, si de SSEE, pues una vez que comprendiste un ARM o un RISC-V estás a centímetros de comprender un x86, si es que los servidores no son ARM.

Entonces, el eje del conocimiento de IoT termina siendo en realidad el conocimiento de la infraestructura de soporte, condimentado con los casos de Edge Processing, donde la inteligencia vuelve al dispostivo, esto es por ejemplo cuando se transmite un video sólo cuando se detecta un evento complejo como el reconocimiento de que hay una cara. Se envía al servidor la foto y este reconoce la identidad de la cara. Reconocer que hay una cara no es tarea menor y ahorra un montón de ancho de banda.

O un vehículo autónomo, a dónde va a ir se lo dice el sistema central, quizás más o menos por dónde, pero el cómo, el evitar chocar lo va a resolver por si mismo.

Otra característica que mueve el eje es cuando hay condiciones "especiales", para llamarlas de alguna manera, esto es, por ejemplo cuando hay distancias apreciables y la fuente de alimentación es restringida, lo cual te obliga a usar protocolos de bajo consumo, ya no es entonces uso WiFi cero cerebro, hay que estudiar un poquito mejor el asunto.

Y a lo que se está yendo, pero me parece que aún no es tan importante, es la coordinación autónoma entre los dispositivos. Por ahora es más sencillo que el sensor de humedad le diga al servidor que la maceta está seca y éste le diga a la válvula de riego que se abra. Es que ni el sensor ni la válvula saben cual es el pronóstico para las próximas horas. Y un auto claramente puede negociar mucho mejor el cruce en una calle sin semáforo comunicándose con los autos cercanos, pero no puede anticipar una congestión un kilómetro más adelante así.

Volviendo a un banco, tenemos que aunque un poco distintos, con respecto a las estaciones de trabajo, notebooks y SmartPhones al menos, se tiene un problema similar al de IoT respecto al inventario, tracking, actualización de imagen en el caso de IoT más básico, del sistema operativo y aplicaciones en no IoT, autenticación de los dispositivos.

Respecto a los ATM el aspecto de desatendido y que se protejan de ataques físicos, no sólo físicos físicos, para eso está el blindaje, sino para que no se les haga escupir billetes conectándole un cable en el expendedor.

Asi que aunque en mi caso lo que prima es mi interés natural por SSEE e IoT, a cualquier persona técnica lo que aprenda de arquitecturas y seguridad le servirá de modo directo pues no dejemos de ver que los ATM son los que entregan la plata y aunque parezcan PCs adornadas, son SSEE. El resto forma parte de la superficie de ataque y en todo caso servirá de modo indirecto pues se aprende mucho al cruzar campos de conocimiento.

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.