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.