As implantações da IoT apenas continuam crescendo e uma parte desse crescimento significativo é composta por milhões de sensores LPWAN (rede de área larga de baixa potência) implantados em centenas de cidades (cidades inteligentes) em todo o mundo, também em indústrias e casas. Uma das tecnologias LPWAN mais usadas é a Lora para a qual Lorawan é o padrão de rede (camada MAC). Lorawan é um protocolo seguro com criptografia incorporada, mas questões e fraquezas de implementação afetam a segurança da maioria das implantações atuais.
Este projeto pretende fornecer uma série de ferramentas para criar, analisar, enviar, analisar e quebrar um conjunto de pacotes de Lorawan para auditar ou meditar a segurança de uma infraestrutura de Lorawan.
Abaixo, a estrutura deste repositório:
|-- 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
Fornecemos opções diferentes para que sua estrutura de auditoria de Lorawan em funcionamento:
tools/ diretor, a fim de evitar problemas com o mapeamento de porta do docker.localhost . Veja as instruções abaixo para configurar o Docker.Essas instruções receberão uma cópia do projeto e suas dependências em sua máquina local. Os comandos abaixo são para um ambiente baseado em Debian:
Clone este repositório: git clone --recurse-submodules https://github.com/IOActive/laf.git
Instale o python3:
sudo apt-get updatesudo apt-get install python3.6Faça o download e instale as dependências do Python:
sudo pip3 install paho-mqtt && sudo pip3 install sqlalchemy && sudo pip3 install psycopg2-binary &&sudo pip3 install python-dateutilDefinir Pythonpath e Environment
cd laf && export PYTHONPATH=$(pwd) && export ENVIRONMENT='DEV'Instale e configure Golang:
cd ~/Downloadssudo tar -C /usr/local -xvzf YOUR_GOLANG_FILEexport PATH=$PATH:/usr/local/go/binexport GOPATH="$HOME/go"Compilar biblioteca GO:
cd laf/lorawanwrapper/utilsgo build -o lorawanWrapper.so -buildmode=c-shared jsonUnmarshaler.go lorawanWrapper.go micGenerator.go sessionKeysGenerator.go hashGenerator.goDependendo de qual banco de dados você gostaria de usar:
um. POSTRESQL: Siga as instruções 'Instruções LAF usando o Docker' até a 3ª etapa.
b. Sqlite:
cd laf/auditing/db__init__.py com seu editor de texto preferido e comente as linhas a serem usadas com o Postgres (conexão de dB e variáveis de ambiente) um descomment a linha a ser usada com sqlite.E é isso!
Essa abordagem evita lidar com a instalação de dependências e iniciar um dB PostgreSQL, onde as ferramentas salvam pacotes e dados. Recipientes:
Passos:
git clone https://github.com/IOActive/laf.gitcd laf/docker-compose up --builddocker exec -ti laf_tools_1 /bin/bashVocê pode verificar os dados em dB usando pgadmin:
Primeiro, acesso a pgadmin:
Então, você precisa adicionar o servidor:
Aqui está a descrição dos diretórios e as ferramentas / função dentro deles.
O principal objetivo das ferramentas fornecidas neste diretório é facilitar a execução de um teste de penetração em uma infraestrutura de Lorawan.
Esta ferramenta destina-se a enviar pacotes de uplink (para o servidor de rede ou gatewaybridge, dependendo da infraestrutura) ou pacotes de downlink (para o forwarder de pacotes). Opcionalmente, os pacotes podem ser presos e um microfone válido pode ser calculado.
Argumentos opcionais:
-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 necessários:
--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}'"
Exemplo:
Para enviar um único pacote a cada 2 segundos para (localhost, 10001) da porta 10000 Fuzzing aleatoriamente o microfone e o 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="}]}'"
Esse proxy UDP pretende ser colocado principalmente entre um gateways da série (packet_forwarders) e um servidor de rede ou ponte de gateway, dependendo da infraestrutura que está sendo avaliada. Ele também oferece a possibilidade de difundir dados na direção desejada (uplink ou downlink)
Argumentos opcionais:
-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 necessários:
--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.
Exemplo:
Para enviar pacotes recebidos na porta 1234 para (localhost, 1235) e Vicecersa. Os pacotes recebidos na porta serão confusos (o DevNonce será alterado na Randonly) e encaminhado para (localhost, 1235).
python3 UdpProxy.py --port 1234 --dst-ip 127.0.0.1 --dst-port 1235 --fuzz-in 9
Esse proxy TCP deve ser colocado principalmente entre o servidor de rede e os corretores MQTT. Ele também oferece a possibilidade de os dados fuzz.
Argumentos opcionais:
-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 necessários:
--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.
Exemplo:
Envie e receba dados de (localhost, 1884) e (localhost, 1883)
python3 TcpProxy.py --lcl-port 1884 --dst-ip 127.0.0.1 --dst-port 1883
Este diretório contém uma série de scripts para analisar, artesanato, brutela, etc. Lorawan A pacotes.
Este script recebe um junção ou junção no Base64 e tenta descriptografar seu AppKey com um conjunto de teclas possíveis que podem ser fornecidas em um arquivo ou podem ser geradas em tempo real.
Argumentos opcionais:
-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 necessários:
-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=
Exemplo:
Rachine um junção-request com um conjunto de chaves do my-lheys.txt e também gerar aprox. 200000 mais dinamicamente.
python3 BruteForcer.py -a IHvAP4MXo5Qo6tdV+Yfk08o= -r AMQAAAAAhQAAAgAAAAAAAADcYldcgbc= -k ./my-keys.txt
Esses scripts recebem um pacote de phypayload no Base64 e uma chave que pode ser a chave nwks do AppKey, dependendo do tipo de pacote e gera o novo microfone.
Argumentos opcionais:
-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 necessários:
-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
Exemplo:
Assine o PhyPayload fornecido com o AppKey 001122334455566778899AABBCCDDEEFF.
python3 MicGenerator.py -d AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU= -k 00112233445566778899AABBCCDDEEFF
Este script recebe um pacote Lorawan JSON e o transforma em base64. Ele faz o inverso como packetparser.py, para que a saída desse script possa ser usada aqui e vice-versa.
Argumentos opcionais:
-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 necessários:
-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"}'
Exemplo:
Obtenha um phypayload de junção no BASE64 com dado no JSON com os valores passados para ele.
python3 PacketCrafter.py -j '{"mhdr":{"mType":"JoinRequest","major":"LoRaWANR1"},"macPayload":{"joinEUI":"55d239ac716f234d","devEUI":"b827eb891cf50003","devNonce":51639},"mic":"7005c4a5"}'
Este script analisa e imprime um único dados de phypayload de Lorawan no BASE64. Ele faz o inverso como packetcrafter.py, para que a saída desse script possa ser usada aqui e vice-versa.
Argumentos opcionais:
-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 necessários:
-d DATA, --data DATA Base64 data to be parsed. eg. -d
AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU=
Exemplo:
Obtenha o formato junção no JSON no exemplo acima.
python3 PacketParser.py -d AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU=
Este script recebe um JONCECT e um junção no Base64 e um AppKey para gerar as chaves da sessão. Um exemplo do uso:
Argumentos opcionais:
-h, --help show this help message and exit
Argumentos necessários:
-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
Exemplo:
Obtenha o Appskey e o NWKSKEY com os seguintes dados de junção.
python3 SessionKeysGenerator.py -r AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU= -a IB1scNmwJRA32RfMbvwe3oI= -k f5a3b185dfe452c8edca3499abcd0341
Essas são funções auxiliares usadas pelo UdpSender.py e UdpProxy.py . Em Fuzzer.py você pode ver os modos de fuzzing implementados.
O objetivo geral deste diretório é coletar pacotes de Lorawan e analisar diferentes aspectos do tráfego, além de tentar um conjunto de chaves para tentar forçar o AppKey.
Este diretório contém um conjunto de scripts que recebem pacotes de Lorawan de diferentes fontes (por exemplo, gateway packet_forwarder, The Things Network etc.) e salve -os em arquivos, com um formato padrão. Esses arquivos devem ser buscados posteriormente pelo script /auditing/analyzers/LafProcessData.py para executar diferentes sub-ferramentas.
Esse script se conecta ao corretor MQQT, recupera todos os tópicos e salva mensagens em um arquivo no campo especificado. O nome do arquivo é composto pela data em que esse script foi iniciado.
Argumentos opcionais:
-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 necessários:
--ip IP MQTT broker ip, eg. --ip 192.168.3.101.
--port PORT MQTT broker port, eg. --port 623.
Exemplo:
Conecte -se ao MQTT o corretor com IP 200.200.200.200 na porta padrão (1883).
python3 GenericMqttCollector.py --ip 200.200.200.200 --port 1883
Este script se conecta a um corretor Loraserver.io MQQT e salva mensagens no banco de dados. Você deve especificar um colectors exclusivo e pode especificar os tópicos que deseja suspender.
Argumentos opcionais:
-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 necessários:
--ip IP MQTT broker ip, eg. --ip 192.168.3.101.
Este script recebe pacotes UDP do proxy UDP no formato Gateway Packet_Forwarder e os persiste.
Argumentos opcionais:
-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 necessários:
-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.
Exemplo:
Registre os dados entre um gateway enviando para a porta local 1700 e uma rede XServer ouvindo (localhost, 1701). Salve os dados no diretório ./ .
python3 PacketForwarderCollector.py --name semtech_collector --port 1700
Este script lê A de um arquivo ou arquivos ou stdin e executa diferentes sub-ferramentas. Dependendo da opção selecionada, você pode executar uma análise do tráfego de Lorawan, tentar fortalecer o AppKey ou analisar todos os pacotes recebidos. Essas opções podem ser combinadas.
Argumentos opcionais:
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.
Exemplo:
Pacotes de processo no banco de dados a partir do ID do pacote 1000, execute uma análise de tráfego e tente quebrar os aplicativos fornecidos no My-Keys.txt, mas não gera dinamicamente mais chaves.
python3 LafProcessData.py -a -b -k my-keys.txt --no-gen --from-id 1000
Esses scripts fornecem a funcionalidade orquestada por lafprocessdata.py. Abaixo, os alertas que são implementados por LafPacketAnalysis.py e LafBruteForcer.py :
| EU IA | Título | Analisador | Nível de risco | Descrição | Ação recomendada |
|---|---|---|---|---|---|
| LAF-001 | DevNonce repetiu | Lafpacketanalysis.py | Baixo | O DevNonces para cada dispositivo deve ser aleatório o suficiente para não colidir. Se o mesmo DevNonce foi repetido em muitas mensagens, pode -se inferir que um dispositivo está sob um ataque de repetição. Isto é, um atacante que capturou uma junção e está tentando enviá -lo novamente para o gateway. | Verifique como o DevNonces é gerado: a função que os gera deve ser implementada usando uma biblioteca aleatória. Além disso, você deve garantir que o servidor verifique para o Devnonces Historic (eles devem ser persistidos no banco de dados), para não aceitar um antigo junção válido antigo enviado anteriormente pelo dispositivo e, assim, gerar uma nova sessão. |
| LAF-002 | Deveuis compartilhando o mesmo devaddr | Lafpacketanalysis.py | Informações | Dois dispositivos diferentes podem ter sido atribuídos o mesmo Devaddr. Esta não é uma ameaça à segurança. | Se o dispositivo estiver sobre o ar ativado (OTAA): verifique a lógica usada para atribuir Devaddrs e verifique se o servidor não atribui o mesmo Devaddr a dispositivos diferentes. Se o dispositivo for ativado pela personalização (ABP): verifique o Devaddr configurado no firmware de um dispositivo, é exclusivo na rede Lorawan. |
| LAF-003 | Junte -se a reprodução | PENDÊNCIA | Médio | Foi detectado um pacote de solicitação de junção duplicado, o que pode sugerir que o servidor Lorawan está sob um ataque de repetição. Isto é, um atacante que pode ter capturado um pacote de solicitação de junção anterior e está enviando -o novamente ao servidor Lorawan, para tentar gerar uma nova sessão. | Verifique como o DevNonces é gerado: a função que os gera deve ser implementada usando uma biblioteca aleatória. Além disso, você deve garantir que o servidor verifique para o Devnonces Historic (eles devem ser persistidos no banco de dados), para não aceitar um antigo junção válido antigo enviado anteriormente pelo dispositivo e, assim, gerar uma nova sessão. |
| LAF-004 | Pacotes de dados Uplink Replay | PENDÊNCIA | Médio | Foi detectado um pacote de uplink duplicado, o que pode sugerir que o servidor Lorawan está sob um ataque de repetição. Isto é, um invasor que pode ter capturado um pacote de uplink (enviado do dispositivo) e está enviando -o novamente ao servidor Lorawan. | Em dispositivos ativados por ar (OTAA): Verifique se as chaves da sessão são geradas re-geradas após a redefinição de cada dispositivo ou o comando de contador para evitar qualquer efeito a partir desse ataque. Com os dispositivos ativados por personalização (ABP) do Lorawan v1.0.*, Nada pode ser feito para evitar um ataque de repetição, exceto de alternar o dispositivo para OTAA. |
| LAF-005 | Pacotes de dados Downlink Replay | PENDÊNCIA | Alto | Um pacote de downlink duplicado foi detectado. O servidor está respondendo a um ataque de repetição ou está gerando um tráfego atípico para dispositivos | Verifique os logs dos servidores e verifique se a ação recomendada anterior é implementada |
| LAF-006 | Possível dispositivo ABP (redefinição do contador e nenhuma junção) | Lafpacketanalysis.py | Alto | Se o contador foi redefinido (voltou para 0), o Devaddr é mantido o mesmo e nenhum processo de junção anterior foi detectado, pode implicar que o dispositivo seja ativado pela personalização (ABP). A implementação dos dispositivos ABP é desencorajada porque nenhum processo de junção é feito, o que significa que as chaves da sessão são mantidas iguais para sempre. Um dispositivo que não altera suas chaves de sessão é propenso a diferentes ataques, como o EAVEASDROP ou o reprodução. | Todos os dispositivos ativados pelos dispositivos de personalização (ABP) devem ser substituídos por dispositivos ativados por ar (OTAA), se possível. A implementação dos dispositivos ABP é desencorajada. |
| LAF-007 | Recebido contador menor do que o esperado (distinto de 0) | Lafpacketanalysis.py | Médio | Se um invasor obtiver um par de chaves de sessão (por ter roubado o AppKey em dispositivos OTAA ou o Appskey/NWKSKEY em dispositivos ABP), ele poderá enviar dados falsos válidos ao servidor. Para que o servidor aceite mensagens falsificadas, é necessário que o FCNT (contador de quadros) da mensagem seja maior que o FCNT da última mensagem enviada. Em um cenário em que o dispositivo falsificado original continua enviando mensagens, o servidor começará a descartar as mensagens (válidas), pois teriam um FCNT menor. Portanto, quando mensagens com um valor FCNT menor do que o esperado pelo servidor Lorawan estão sendo recebidas, é possível inferir que uma sessão paralela foi estabelecida. | Se o dispositivo estiver acima do dispositivo ativado por ar (OTAA), altere seu AppKey porque provavelmente foi comprometido. Se for ativado pela personalização, mude seu Appskey e Nwkskey. Além disso, verifique se o servidor Lorawan está atualizado e não está aceitando mensagens duplicadas. |
| LAF-008 | Senha rachada com junção | Lafbruteforcer.py | Alto | Foi possível descriptografar uma mensagem de junção -request usando um AppKey conhecido. | Use aplicativos diferentes dos fornecedores fornecidos por fornecedores ou use mais teclas aleatórias. |
| LAF-009 | Senha rachada | Lafbruteforcer.py | Alto | O AppKey do dispositivo foi encontrado tentando com uma sequência bem conhecida ou não aleatória. Foi descriptografado usando um par de mensagens de junção (solicitação e aceitação). | Use um gerador de chave aleatório para o AppKey em vez de usar os fornecidos pelos fornecedores. Além disso, não defina o mesmo AppKey para mais de um dispositivo e não gera aplicativos usando uma lógica previsível (por exemplo, valores incrementais, gire certos bytes, etc.) |
| LAF-010 | O gateway mudou de localização | Lafpacketanalysis.py | Médio | Se o gateway não deve mudar sua localização. Pode ter sido roubado, movido ou um gateway falso pode estar tentando se passar por gateway legítima. | Verifique se o gateway não estava adulterado, tanto física quanto logicamente. |
Este diretório fornece um conjunto de invólucros para a biblioteca https://github.com/brocaar/lorawan/, que está escrito em Golang. Essas funções são implementadas pelas ferramentas.
Aqui você encontrará uma série de scripts destinados a automatizar diferentes tarefas. Certifique -se de dar a eles permissão de execução, se necessário ( chmod +x your_script para Linux/MacOS).
Configure facilmente o seu gateway e trocam seus canais para fins de fungagem. Para obter mais informações sobre como usá -las, você pode ver o ReadMe neste diretório.
Esse script é usado para instalar todos os pacotes de software necessários em um Raspberry Pi para criar um gateway de Lorawan em conjunto com um concentrador LORA conectado (IC980-SPI, RHF0M301-SPI, RAK831-SPI ou qualquer outro por configuração manual).
Como não é possível saber em quais frequências os dispositivos LORA estão operando, criamos um script que pode alternar os canais de gateways das bandas de frequência US915 e EU868 para fins de funão. Embora existam gateways profissionais e caros que suportam 32 ou 64 canais, a maioria dos gateways suporta até 8 canais. Este script pretende ser executado nesse tipo de gateways.
Pelo menos na banda de frequência dos EUA915, os 8 primeiros canais são os mais utilizados. Mas existem implementações bem conhecidas que usam outro grupo de canais, como por exemplo, as redes das coisas, que usam o segundo grupo (8-15) de canais para comunicação de uplink.
Atualmente, não apoiamos outras bandas de frequência, mas, com poucas alterações nesses scripts, você seria capaz de fazer isso por conta própria :).
Carregamos um vídeo dessa estrutura em ação (o mesmo cenário apresentado em Blackhat 2019): https://youtu.be/mm6a2rvnocs. As etapas detalhadas da demonstração estão na descrição do vídeo do YouTube.
PENDÊNCIA
Este projeto está licenciado sob licença de BSD-3-cláusula.