Las implementaciones de IoT siguen creciendo y una parte de ese crecimiento significativo está compuesto por millones de sensores LPWAN (red de baja potencia de área amplia) desplegados en cientos de ciudades (ciudades inteligentes) en todo el mundo, también en industrias y hogares. Una de las tecnologías LPWAN más utilizadas es Lora para la cual Lorawan es el estándar de red (capa MAC). Lorawan es un protocolo seguro con cifrado incorporado, pero los problemas de implementación y las debilidades afectan la seguridad de la mayoría de las implementaciones actuales.
Este proyecto tiene la intención de proporcionar una serie de herramientas para crear, analizar, enviar, analizar y descifrar un conjunto de paquetes Lorawan para auditar o acumular la seguridad de una infraestructura de Lorawan.
A continuación, la estructura de este repositorio:
|-- tools
|-- UdpSender.py
|-- UdpProxy.py
|-- TcpProxy.py
|-- lorawan
|-- BruteForcer.py
|-- MicGenerator.py
|-- PacketCrafter.py
|-- PacketParser.py
|-- SessionKeysGenerator.py
|-- Loracrack (https://github.com/matiassequeira/Loracrack/tree/master)
|-- utils
|-- DevAddrChanger.py
|-- Fuzzer.py
|-- FileLogger.py
|-- auditing
|-- datacollectors
|-- MqttCollector.py
|-- UdpForwarderProxy.py
|-- analyzers
|-- LafProcessData.py
|-- bruteForcer
|-- LafBruteforcer.py
|-- keys
|-- dataanalysis
|-- LafPacketAnalysis.py
|-- printer
|-- LafPrinter.py
|-- db
|-- __init__.py
|-- Models.py
|-- Service.py
|-- lorawanwrapper
|-- LorawanWrapper.py
|-- utils
|-- jsonUnmarshaler.go
|-- lorawanWrapper.go
|-- micGenerator.go
|-- sessionKeysGenerator.go
|-- scripts
|-- gateway_channel_changer
|-- LoRa-GW-Installer.sh
|-- Continuous-Channel-Switch.sh
|-- LoRa-GW-Channel-Setup.sh
Proporcionamos diferentes opciones para que su marco de auditoría de Lorawan esté en funcionamiento:
tools/ Dir, para evitar problemas con el mapeo de puertos Docker.localhost . Vea las instrucciones a continuación para configurar Docker.Estas instrucciones le darán una copia del proyecto y sus dependencias en su máquina local. Los comandos a continuación son para un entorno basado en Debian:
Clone Este repositorio: git clone --recurse-submodules https://github.com/IOActive/laf.git
Instalar python3:
sudo apt-get updatesudo apt-get install python3.6Descargar e instalar dependencias de Python:
sudo pip3 install paho-mqtt && sudo pip3 install sqlalchemy && sudo pip3 install psycopg2-binary &&sudo pip3 install python-dateutilEstablecer pythonpath y medio ambiente
cd laf && export PYTHONPATH=$(pwd) && export ENVIRONMENT='DEV'Instalar y configurar Golang:
cd ~/Downloadssudo tar -C /usr/local -xvzf YOUR_GOLANG_FILEexport PATH=$PATH:/usr/local/go/binexport GOPATH="$HOME/go"Compilar la biblioteca Go:
cd laf/lorawanwrapper/utilsgo build -o lorawanWrapper.so -buildmode=c-shared jsonUnmarshaler.go lorawanWrapper.go micGenerator.go sessionKeysGenerator.go hashGenerator.goDependiendo de qué DB le gustaría usar:
a. POSTRESQL: Siga las instrucciones 'Instalar LAF usando Docker' hasta el tercer paso.
b. Sqlite:
cd laf/auditing/db__init__.py con su editor de texto preferido y comente las líneas que se utilizarán con Postgres (variables de entorno de conexión y entorno de DB) la línea que se utilizará con SQLite.¡Y eso es todo!
Este enfoque evita lidiar con la instalación de dependencias e iniciar un DB PostgreSQL donde las herramientas guardan paquetes y datos. Contenedores:
Pasos:
git clone https://github.com/IOActive/laf.gitcd laf/docker-compose up --builddocker exec -ti laf_tools_1 /bin/bashPuede verificar los datos en DB usando PGADmin:
Primero, acceso a Pgadmin:
Luego, debe agregar el servidor:
Aquí hay una descripción de los directorios y las herramientas / función dentro de ellos.
El objetivo principal de las herramientas proporcionadas en este directorio es aliviar la ejecución de una prueba de penetración a una infraestructura de Lorawan.
Esta herramienta está destinada a enviar paquetes de enlace ascendente (al servidor de red o Gatewaybridge, dependiendo de la infraestructura) o los paquetes de enlace descendente (al paquete-avance). Opcionalmente, los paquetes se pueden borrar y se puede calcular un micrófono válido.
Argumentos opcionales:
-h, --help show this help message and exit
--lcl-port LCL_PORT Source port, eg. --lcl-port=623.
--timeout TIMEOUT Time in seconds between every packet sent. Default is
1s. In this time, the sender will listen for replies.
--repeat Send message/s multiple times
--fuzz-out FUZZ_OUT [FUZZ_OUT ...]
Fuzz data sent to dest port (see fuzzing modes in
utils/fuzzer.py), eg. --fuzz-out 1 2.
--key KEY Enter the key (in hex format, a total of 32 characters
/ 16 bytes) to sign packets (calculate and add a new
MIC). Note that for JoinRequests it must be the
AppKey, and the NwkSKey for Data packets. This cannot
be validated beforehand by this program. eg.
00112233445566778899AABBCCDDEEFF
-a DEVADDR, --devaddr DEVADDR
DeviceAddress to impersonate, given in hex format (8
characters total), eg. AABB0011.
--fcnt FCNT The frame counter to be set in the given data packet.
This wouldn't work in a JoinRequest/JoinAccept since
this packets don't have a fCnt
Argumentos requeridos:
--dst-ip DST_IP Destination ip, eg. --dst-ip 192.168.3.101.
--dst-port DST_PORT Destination port, eg. --dst-port 623.
--data DATA UDP packet. It can also be added more packets in
"data" array at the end of this script. The packet
must be a byte string (you will have to escape double
quotes). ***EXAMPLE*** with the packet_forwarder
format: --data "b'x02xe67x00xb8'xebxffxfezx80
xdb{"rxpk":[{"tmst":2749728315,"chan":0,"rfch
":0,"freq":902.300000,"stat":1,"modu":"LORA",
"datr":"SF7BW125","codr":"4/5","lsnr":9.5,"r
ssi":-76,"size":23,"data":"AMQAAAAAhQAAAgAAAAAAA
ACH9PRMJi4="}]}'" ***EXAMPLE*** using the gatevice
[GV] format sending in inmediate mode, in BW125 and
freq 902.3 is "b'{"tx_mode": 0, "freq": 902.3,
"rfch": 0, "modu": 16, "datarate": 16,
"bandwidth":3, "codr": 1, "ipol":false,
"size": 24, "data":
"QOOL8AGA6AMCnudJqz3syCkeooCvqbSn", "class": 2}'"
Ejemplo:
Para enviar un solo paquete cada 2 segundos a (Localhost, 10001) desde el puerto 10000 Fuzzing al azar el micrófono y el fcounter:
python3 UdpSender.py --lcl-port 10000 --dst-ip 127.0.0.1 --dst-port 10001 --timeout 2 --fuzz-out 4 5 --data "b'x02xe67x00xb8'xebxffxfezx80xdb{"rxpk":[{"tmst":2749728315,"chan":0,"rfch":0,"freq":902.300000,"stat":1"modu":"LORA","datr":"SF7BW125","codr":"4/5","lsnr":9.5,"rssi":-76,"size":23,"data":"AMQAAAAAhQAAAgAAAAAAAACH9PRMJi4="}]}'"
Este proxy UDP está destinado principalmente a colocarse entre una puerta de enlace (paquete_forwarders) y un servidor de red o puente de puerta de enlace dependiendo de la infraestructura que se evalúa. También ofrece la posibilidad de confundir los datos en la dirección deseada (enlace ascendente o enlace descendente)
Argumentos opcionales:
-h, --help show this help message and exit
--collector-port COLLECTOR_PORT
Packet forwarder data collector port, eg. --collector-
port 1701. See
auditing/datacollectors/PacketForwarderCollector.py
--collector-ip COLLECTOR_IP
Packet forwarder data collector ip. Default is
localhost. eg. --collector-ip 192.168.1.1. See
auditing/datacollectors/PacketForwarderCollector.py
--fuzz-in FUZZ_IN [FUZZ_IN ...]
Fuzz data sent to dst-port in the given modes (see
fuzzing modes in utils/fuzzer.py), eg. --fuzz-in 1 2
...
--fuzz-out FUZZ_OUT [FUZZ_OUT ...]
Fuzz data sent to (source) port in the given modes
(see fuzzing modes in utils/fuzzer.py), eg. --fuzz-out
1 2 ...
-k KEY, --key KEY Enter a device AppSKey (in hex format, a total of 32
characters / 16 bytes) to decrypt its FRMPayload and
print it in plain text. You can also enter the AppKey
if you wish to decrypt a given Join Accept. eg.
00112233445566778899AABBCCDDEEFF
-p PATH, --path PATH Filepath where to save the data. If not given, data
will not be saved.
--no-log Do not print UDP packages into console
--no-parse Do not parse PHYPayload. If this option is selected,
Golang librarys from /lorawanwrapper/ won't be
imported (golang libs compiling is not required)
Argumentos requeridos:
--port PORT The local port to listen, eg. --port 623.
--dst-ip DST_IP Destination host ip, eg. --dst-ip 192.168.3.101.
--dst-port DST_PORT Destination host port, eg. --dst-port 623.
Ejemplo:
Para enviar paquetes recibidos en el puerto 1234 a (Localhost, 1235) y Vicecersa. Los paquetes recibidos en el puerto se borrarán (el Devnonce se cambiará randonly) y se reenviará a (Localhost, 1235).
python3 UdpProxy.py --port 1234 --dst-ip 127.0.0.1 --dst-port 1235 --fuzz-in 9
Este proxy TCP está destinado principalmente a colocarse entre el servidor de red y los corredores MQTT. También ofrece la posibilidad de confundir los datos.
Argumentos opcionales:
-h, --help show this help message and exit
--fuzz-in FUZZ_IN [FUZZ_IN ...]
Fuzz data sent to dst-port in the given modes (see
fuzzing modes in utils/fuzzer.py)
Argumentos requeridos:
--lcl-port LCL_PORT The local port to listen, eg. --lcl-port=623.
--dst-ip DST_IP Destination host ip, eg. --dst-ip=192.168.3.101.
--dst-port DST_PORT Destination host port, eg. --dst-port=623.
Ejemplo:
Enviar y recibir datos de (Localhost, 1884) y (Localhost, 1883)
python3 TcpProxy.py --lcl-port 1884 --dst-ip 127.0.0.1 --dst-port 1883
Este directorio contiene una serie de guiones para analizar, artesanía, Bruteforcer, etc. Lorawan A paquetes.
Este script recibe un Joinacept o JoinRequest en Base64 e intenta descifrar su AppKey con un conjunto de claves posibles que se pueden proporcionar en un archivo o que se pueden generar en la marcha.
Argumentos opcionales:
-h, --help show this help message and exit
-k KEYS, --keys KEYS File containing a list of keys, separated by n. Will
use /auditing/analyzers/bruteForcer/keys.txt by
default
--dont-generate Select this options if you don't want to generate keys
on the fly with the following combinations: 1- Combine
the first byte and the last fifteeen bytes. eg.
AABBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 2- Combine even and
odd bytes position equally. eg.
AABBAABBAABBAABBAABBAABBAABBAABB 3- The first 14 bytes
in 00 and combine the last 2. eg.
0000000000000000000000000000BA01
Argumentos requeridos:
-a ACCEPT, --accept ACCEPT
Join Accept in Base64 format to be bruteforced. eg. -a
IHvAP4MXo5Qo6tdV+Yfk08o=
-r REQUEST, --request REQUEST
Join Request in Base64 format to be bruteforced. eg.
-r AMQAAAAAhQAAAgAAAAAAAADcYldcgbc=
Ejemplo:
Cruce una Request de unión con un conjunto de claves de My-Keys.txt y también genere Aprox. 200000 más dinámicamente.
python3 BruteForcer.py -a IHvAP4MXo5Qo6tdV+Yfk08o= -r AMQAAAAAhQAAAgAAAAAAAADcYldcgbc= -k ./my-keys.txt
Este scripts recibe un paquete PhyPayLoad en Base64 y una clave que puede ser el NWKSKEY de la AppKey dependiendo del tipo de paquete y genera el nuevo micrófono.
Argumentos opcionales:
-h, --help show this help message and exit
--jakey JAKEY [JoinAccept ONLY]. Enter the key used to encrypt the
JoinAccept previously (in hex format, a total of 32
characters / 16 bytes). This cannot be validated
beforehand by this program. eg.
00112233445566778899AABBCCDDEEFF. A valid key sample
for the JoinAccept "IB1scNmwJRA32RfMbvwe3oI=" is
"f5a3b185dfe452c8edca3499abcd0341"
Argumentos requeridos:
-d DATA, --data DATA Base64 data to be signed. eg. -d
AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU=
-k KEY, --key KEY Enter the new key (in hex format, a total of 32
characters / 16 bytes) to sign packets (calculate and
add a new MIC). Note that for JoinRequest/JoinAccept
it must be the AppKey, and the NwkSKey for Data
packets. This cannot be validated beforehand by this
program. eg. 00112233445566778899AABBCCDDEEFF
Ejemplo:
Firme el PhyPayLoad dado con el AppKey 00112233445566778899aabbcccddeeff.
python3 MicGenerator.py -d AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU= -k 00112233445566778899AABBCCDDEEFF
Este script recibe un paquete Lorawan JSON y lo transforma a Base64. Hace lo inverso como PacketParser.py, por lo que la salida de ese script se puede usar aquí y viceversa.
Argumentos opcionales:
-h, --help show this help message and exit
-k KEY, --key KEY Enter a device AppSKey or AppKey (in hex format, a
total of 32 characters / 16 bytes) to encrypt the
FRMPayload or a Join Accept. eg.
F5A3B185DFE452C8EDCA3499ABCD0341
--nwkskey NWKSKEY Enter the network session key if you'd like to
generate a data packet with a valid MIC.
Argumentos requeridos:
-j JSON, --json JSON JSON object to parse. eg. -j '{"mhdr":
{"mType":"JoinRequest","major":"LoRaWANR1"},"macPayloa
d":{"joinEUI":"55d239ac716f234d","devEUI":"b827eb891cf
50003","devNonce":51639},"mic":"7005c4a5"}'
Ejemplo:
Obtenga una Request JoinRequest en Base64 con administrado en el JSON con los valores que se le pasan.
python3 PacketCrafter.py -j '{"mhdr":{"mType":"JoinRequest","major":"LoRaWANR1"},"macPayload":{"joinEUI":"55d239ac716f234d","devEUI":"b827eb891cf50003","devNonce":51639},"mic":"7005c4a5"}'
Este script analiza e imprime un solo datos de Lorawan PhypayLoad en Base64. Hace lo inverso como paquetes de paquete.py, por lo que la salida de ese script se puede usar aquí y viceversa.
Argumentos opcionales:
-h, --help show this help message and exit
-k KEY, --key KEY Enter a device AppKey or AppSKey depending on the
packet to be decrypted (join accept or data packet).
Must be in hex format, a total of 32 characters / 16
bytes. eg. 00112233445566778899AABBCCDDEEFF
Argumentos requeridos:
-d DATA, --data DATA Base64 data to be parsed. eg. -d
AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU=
Ejemplo:
Obtenga la Request Join en formato JSON del ejemplo anterior.
python3 PacketParser.py -d AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU=
Este script recibe un Joinacept y una Request Join en Base64, y una aplicación para generar las claves de sesión. Un ejemplo del uso:
Argumentos opcionales:
-h, --help show this help message and exit
Argumentos requeridos:
-a JACCEPT, --jaccept JACCEPT
JoinAccept payload in base64
-r JREQUEST, --jrequest JREQUEST
JoinRequest payload in base64
-k KEY, --key KEY Enter a device AppKey (in hex format, a total of 32
characters / 16 bytes). eg.
00112233445566778899AABBCCDDEEFF
Ejemplo:
Obtenga el AppSkey y NWKSKey con los siguientes datos de unión.
python3 SessionKeysGenerator.py -r AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU= -a IB1scNmwJRA32RfMbvwe3oI= -k f5a3b185dfe452c8edca3499abcd0341
Estas son funciones auxiliares utilizadas por UdpSender.py y UdpProxy.py . En Fuzzer.py puede ver modos de fuzzing implementados.
El propósito general de este directorio es recolectar paquetes de Lorawan y analizar diferentes aspectos del tráfico, así como probar un conjunto de claves para tratar de acumular la appía.
Este directorio contiene un conjunto de scripts que reciben paquetes de Lorawan de diferentes fuentes (es decir, paquete de puerta de enlace, la red de cosas, etc.) y los guardan en archivos, con un formato estándar. El script /auditing/analyzers/LafProcessData.py debe obtener estos archivos más tarde para ejecutar diferentes sub-marineras.
Este script se conecta al corredor MQQT, recupera todos los temas y guarda mensajes en un archivo en el campo especificado. El nombre de archivo está compuesto por la fecha en que se inició este script.
Argumentos opcionales:
-h, --help show this help message and exit
--collector-id COLLECTOR_ID
The ID of the dataCollector. This ID will be
associated to the packets saved into DB. eg. --id 1
--organization-id ORGANIZATION_ID
The ID of the dataCollector. This ID will be
associated to the packets saved into DB. eg. --id 1
--topics TOPICS [TOPICS ...]
List the topic(s) you want to suscribe separated by
spaces. If nothing given, default will be "#.
Argumentos requeridos:
--ip IP MQTT broker ip, eg. --ip 192.168.3.101.
--port PORT MQTT broker port, eg. --port 623.
Ejemplo:
Conéctese a MQTT el corredor con IP 200.200.200.200 en el puerto predeterminado (1883).
python3 GenericMqttCollector.py --ip 200.200.200.200 --port 1883
Este script se conecta a un corredor Loraserver.io MQQT y guarda mensajes en el DB. Debe especificar un colectorid único y puede especificar los temas a los que desea sospechar.
Argumentos opcionales:
-h, --help show this help message and exit
--port PORT MQTT broker port, eg. --port 623. Default 1883.
--collector-id COLLECTOR_ID
The ID of the dataCollector. This ID will be
associated to the packets saved into DB. eg. --id 1
--organization-id ORGANIZATION_ID
The ID of the dataCollector. This ID will be
associated to the packets saved into DB. eg. --id 1
--topics TOPICS [TOPICS ...]
List the topic(s) you want to suscribe separated by
spaces. If nothing given, default will be "#.
Argumentos requeridos:
--ip IP MQTT broker ip, eg. --ip 192.168.3.101.
Este script recibe paquetes UDP del proxy UDP en el formato Gateway Packet_Forwarder y los persiste.
Argumentos opcionales:
-h, --help show this help message and exit
--collector-id COLLECTOR_ID
The ID of the dataCollector. This ID will be
associated to the packets saved into DB. eg. --id 1
--organization-id ORGANIZATION_ID
The ID of the dataCollector. This ID will be
associated to the packets saved into DB. eg. --id 1
Argumentos requeridos:
-n NAME, --name NAME Unique string identifier of the Data Collector. eg.
--name semtech_collector
-p PORT, --port PORT Port where to listen for UDP packets. --port 1702.
Ejemplo:
Registre datos entre una puerta de enlace que envía al puerto local 1700 y una red XServer que escucha (Localhost, 1701). Guarde los datos en ./ Directorio.
python3 PacketForwarderCollector.py --name semtech_collector --port 1700
Este script lee A desde un archivo o archivos o stdin y ejecuta diferentes sub-marineras. Dependiendo de la opción seleccionada, puede ejecutar un análisis del tráfico de Lorawan, intentar con brutoforce el AppKey o analizar todos los paquetes recibidos. Estas opciones se pueden combinar.
Argumentos opcionales:
This script reads retrieves packets from DB and executes different sub-tools.
Then, each sub-tool will save output data into the DB. See each option for
more information.
optional arguments:
-h, --help show this help message and exit
-a, --analyze Collect and analyze different aspects from traffic. If
Bruteforcer (-b) is activated, results will be
corelated
-b, --bforce Try to bruteforce the AppKeys with JoinRequests and
JoinAccepts payloads
-k KEYS, --keys KEYS [Bruteforcer] Filepath to keys file. If not provided,
"bruteForcer/keys.txt" will be used
--no-gen [Bruteforcer] Don't generate keys, only try keys from
files
-p, --parse Parse the PHYPayload into readable information
--from-id FROM_ID Packet ID from where to start processing.
--to-id TO_ID Last packet ID to be processed.
Ejemplo:
Procese los paquetes en el DB a partir de la ID de paquete 1000, ejecute un análisis de tráfico e intente descifrar las appas que se dan en my-keys.txt, pero no genere dinámicamente más teclas.
python3 LafProcessData.py -a -b -k my-keys.txt --no-gen --from-id 1000
Estos scripts proporcionan la funcionalidad orquesta por lafprocessdata.py. A continuación, las alertas que implementan LafPacketAnalysis.py y LafBruteForcer.py :
| IDENTIFICACIÓN | Título | Analizador | Nivel de riesgo | Descripción | Acción recomendada |
|---|---|---|---|---|---|
| LAF-001 | Devnonce repetido | Lafpacketanalysis.py | Bajo | Los devnonces para cada dispositivo deben ser lo suficientemente aleatorios como para no colisionar. Si el mismo devnonce se repitió en muchos mensajes, se puede inferir que un dispositivo está bajo un ataque de repetición. Este es, un atacante que capturó una Request de uniones y está tratando de enviarlo nuevamente a la puerta de enlace. | Compruebe cómo se generan DevNonces: la función que los genera debe implementarse utilizando una biblioteca aleatoria. Además, debe asegurarse de que el servidor verifique las devnonces históricas (deben persistir en DB), para no aceptar una Request Válida Válida enviada previamente por el dispositivo y, por lo tanto, generar una nueva sesión. |
| LAF-002 | Deveuis compartiendo el mismo devaddr | Lafpacketanalysis.py | Información | A dos dispositivos diferentes podrían haberse asignado el mismo DevadDR. Esta no es una amenaza de seguridad. | Si el dispositivo está activado por aire (OTAA): verifique la lógica utilizada para asignar DevadDRS y asegúrese de que el servidor no asigne el mismo DevadDR a diferentes dispositivos. Si el dispositivo se activa mediante personalización (ABP): verifique el DevadDR configurado en el firmware de un dispositivo es único en la red Lorawan. |
| LAF-003 | Unirse a la repetición | HACER | Medio | Se detectó un paquete de solicitud de unión duplicada, lo que puede implicar que el servidor Lorawan está bajo un ataque de repetición. Este es un atacante que puede haber capturado un paquete de solicitud de unión anterior y lo está enviando nuevamente al servidor Lorawan, para tratar de generar una nueva sesión. | Compruebe cómo se generan DevNonces: la función que los genera debe implementarse utilizando una biblioteca aleatoria. Además, debe asegurarse de que el servidor verifique las devnonces históricas (deben persistir en DB), para no aceptar una Request Válida Válida enviada previamente por el dispositivo y, por lo tanto, generar una nueva sesión. |
| LAF-004 | Reproducción de paquetes de datos de enlace ascendente | HACER | Medio | Se detectó un paquete de enlace ascendente duplicado, lo que puede implicar que el servidor Lorawan está bajo un ataque de repetición. Este es un atacante que puede haber capturado un paquete de enlace ascendente (enviado desde el dispositivo) y lo está enviando nuevamente al servidor Lorawan. | En los dispositivos activados por el aire (OTAA): asegúrese de que las claves de sesión se vuelvan a generar después de que cada dispositivo se restablece o se desborde para evitar cualquier efecto de este ataque. Con dispositivos activados por personalización (ABP) de Lorawan V1.0.*, No se puede hacer nada para evitar un ataque de repetición, excepto cambiar el dispositivo a OTAA. |
| LAF-005 | Reproducción de paquetes de datos de enlace descendente | HACER | Alto | Se detectó un paquete de enlace descendente duplicado. El servidor está respondiendo a un ataque de repetición o está generando un tráfico atípico a los dispositivos | Verifique los registros de los servidores y verifique que se implementen la acción recomendada anterior |
| LAF-006 | Posible dispositivo ABP (reinicio de contador y sin unir) | Lafpacketanalysis.py | Alto | Si el contador se restableció (volvió a 0), el DevadDR se mantiene igual, y no se detectó ningún proceso de unión previo, puede implicar que el dispositivo se activa mediante personalización (ABP). La implementación de los dispositivos ABP se desaconseja porque no se realiza ningún proceso de unión, lo que significa que las claves de sesión se mantienen igual para siempre. Un dispositivo que no cambia sus claves de sesión es propensa a diferentes ataques, como Eaveasdrop o Replay. | Todos los dispositivos activados por personalización (ABP) deben reemplazarse para dispositivos activados por aire (OTAA) si es posible. Se desaconseja la implementación de dispositivos ABP. |
| LAF-007 | Recibió un mostrador más pequeño de lo esperado (distinto de 0) | Lafpacketanalysis.py | Medio | Si un atacante obtiene un par de claves de sesión (por haber robado la AppKey en dispositivos OTAA o el AppSkey/NWKSKey en dispositivos ABP), podría enviar datos válidos falsos al servidor. Para que el servidor acepte mensajes falsificados, se requiere que el FCNT (contador de cuadros) del mensaje sea más alto que el FCNT del último mensaje enviado. En un escenario en el que el dispositivo falsificado original sigue enviando mensajes, el servidor comenzaría a descartar mensajes (válidos) ya que tendrían un FCNT más pequeño. Por lo tanto, cuando se reciben mensajes con un valor FCNT más pequeño que el esperado por el servidor Lorawan, es posible inferir que se estableció una sesión paralela. | Si el dispositivo está sobre el dispositivo activado por aire (OTAA), cambie su aplicación de appLa porque probablemente se vio comprometido. Si se activa por personalización, cambie su Key y NWKSKey. Además, asegúrese de que el servidor Lorawan esté actualizado y no acepte mensajes duplicados. |
| LAF-008 | Contraseña agrietada con JoinRequest | Lafbruteforcer.py | Alto | Era posible descifrar un mensaje de Request Join utilizando una aplicación conocida. | Use diferentes appokeys que las proporcionadas por los proveedores o use más claves aleatorias. |
| LAF-009 | Contraseña agrietada | Lafbruteforcer.py | Alto | La aplicación del dispositivo se encontró intentando con una cadena bien conocida o no aleatoria. Fue descifrado usando un par de mensajes de unión (solicitar y aceptar). | Use un generador de claves aleatorios para AppKey en lugar de usar los proporcionados por los proveedores. Además, no establezca la misma aplicación de la aplicación en más de un dispositivo y no genere AppKeys utilizando una lógica predecible (por ejemplo, valores incrementales, voltee ciertos bytes, etc.) |
| LAF-010 | Gateway cambió de ubicación | Lafpacketanalysis.py | Medio | Si no se supone que la puerta de enlace cambie su ubicación. Puede haber sido robado, movido o una puerta de entrada falsa puede estar tratando de hacerse pasar por la puerta de enlace legítima. | Asegúrese de que la puerta de enlace no fuera manipulada, tanto física como lógicamente. |
Este directorio proporciona un conjunto de envoltorios para la biblioteca https://github.com/brocaar/lorawan/, que está escrito en Golang. Estas funciones son implementadas por las herramientas.
Aquí encontrará una serie de scripts destinados a automatizar diferentes tareas. Asegúrese de darles permiso de ejecución si es necesario ( chmod +x your_script para Linux/MacOS).
Configure fácilmente su puerta de enlace y cambie sus canales con fines de olfateo. Para obtener más información sobre cómo usarlos, puede ver el ReadMe en este directorio.
Este script se utiliza para instalar todos los paquetes de software necesarios en una Raspberry Pi para construir una puerta de enlace de Lorawan junto con un concentrador de lora conectado (IC980-SPI, RHF0M301-SPI, RAK831-SPI o cualquier otro por configuración manual).
Dado que no es posible saber en qué frecuencias están funcionando los dispositivos LORA, hemos creado un script que puede cambiar los canales de Gateways de las bandas de frecuencia US915 y EU868 para fines de olfato. Aunque hay puertas de enlace profesionales y costosas que admiten 32 o 64 canales, la mayoría de las puertas de enlace admiten hasta 8 canales. Este script está destinado a ejecutarse en este tipo de puertas de enlace.
Al menos en la banda de frecuencia de US915, los primeros 8 canales son los más utilizados. Pero hay implementaciones bien conocidas que usan otro grupo de canales, como por ejemplo las redes de cosas, que usan el segundo grupo (8-15) de los canales para la comunicación del enlace ascendente.
Actualmente no apoyamos otras bandas de frecuencia, pero, con pocos cambios en estos scripts, podría hacerlo por su cuenta :).
Subimos un video de este marco en acción (el mismo escenario presentado en Blackhat 2019): https://youtu.be/mm6a2rvnocs. Los pasos detallados de la demostración están en la descripción del video de YouTube.
HACER
Este proyecto tiene licencia bajo la licencia de cláusula BSD-3.