Развертывания IoT просто продолжают расти, и одна часть этого значительного роста состоит из миллионов датчиков LPWAN (сеть с низкой мощью), развернутые в сотнях городов (умные города) по всему миру, также в отраслях и домах. Одной из наиболее используемых технологий LPWAN является LORA, для которой Лораван является сетевым стандартом (MAC -слой). Lorawan - это безопасный протокол со встроенным шифрованием, но проблемы и недостатки реализации влияют на безопасность большинства текущих развертываний.
Этот проект намеревается предоставить серию инструментов для создания, разбора, отправки, анализа и взлома набора пакетов Lorawan, чтобы проверить или пройти безопасность инфраструктуры Lorawan.
Ниже структура этого репозитория:
|-- 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
Мы предоставляем различные варианты, чтобы ваша структура аудита Lorawan работала:
tools/ DIR, чтобы избежать проблем с отображением портов Docker.localhost . См. Инструкции ниже, чтобы настроить Docker.Эти инструкции дадут вам копию проекта и его зависимости в вашей местной машине. Команды ниже предназначены для среды на основе Debian:
Клонировать этот репозиторий: git clone --recurse-submodules https://github.com/IOActive/laf.git
Установите Python3:
sudo apt-get updatesudo apt-get install python3.6Загрузите и установите зависимости от Python:
sudo pip3 install paho-mqtt && sudo pip3 install sqlalchemy && sudo pip3 install psycopg2-binary &&sudo pip3 install python-dateutilУстановить Pythonpath и окружающую среду
cd laf && export PYTHONPATH=$(pwd) && export ENVIRONMENT='DEV'Установите и настройте Golang:
cd ~/Downloadssudo tar -C /usr/local -xvzf YOUR_GOLANG_FILEexport PATH=$PATH:/usr/local/go/binexport GOPATH="$HOME/go"Компилировать библиотеку:
cd laf/lorawanwrapper/utilsgo build -o lorawanWrapper.so -buildmode=c-shared jsonUnmarshaler.go lorawanWrapper.go micGenerator.go sessionKeysGenerator.go hashGenerator.goВ зависимости от того, какой БД вы хотели бы использовать:
а Potresql: следуйте инструкциям «Установить LAF с помощью Docker» до 3 -го шага.
беременный SQLite:
cd laf/auditing/db__init__.py с вашим предпочтительным текстовым редактором и прокомментируйте строки, которые будут использоваться с Postgres (DB Connection Connection и Environment Variate).И это все!
Этот подход избегает работы с установкой зависимостей и запускает дБ PostgreSQL, где инструменты сохраняют пакеты и данные. Контейнеры:
Шаги:
git clone https://github.com/IOActive/laf.gitcd laf/docker-compose up --builddocker exec -ti laf_tools_1 /bin/bashВы можете проверить данные в БД с помощью pgadmin:
Во -первых, доступ к Pgadmin:
Затем вам нужно добавить сервер:
Вот описание каталогов и инструментов / функции внутри них.
Основная цель инструментов, представленных в этом каталоге, состоит в том, чтобы облегчить выполнение теста на проникновение в инфраструктуру Лоравана.
Этот инструмент предназначен для отправки пакетов восходящей линии связи (на сетевой сервер или шейный мост, в зависимости от инфраструктуры) или пакетов нисходящей линии связи (к пакетному кнопку). Необязательно, пакеты могут быть размытыми, и можно рассчитать действительный микрофон.
Необязательные аргументы:
-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
Требуемые аргументы:
--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}'"
Пример:
Чтобы отправлять один пакет каждые 2 секунды в (Localhost, 10001) из порта 10000, случайным образом пузырь, и Fcounter: 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="}]}'"
Этот прокси UDP в основном предназначен для размещения между серийными шлюзами (packet_forwarders) и сетевым сервером или мостом шлюза в зависимости от оцениваемой инфраструктуры. Он также предлагает основание для нечетких данных в желаемом направлении (восходящая линейка или нисходящая линия)
Необязательные аргументы:
-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)
Требуемые аргументы:
--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.
Пример:
Отправить пакеты, полученные в порту 1234 в (Localhost, 1235) и Vicecersa. Пакеты, полученные в порту, будут размытыми (Devnonce будет изменен в Randonly) и перенаправлена на (Localhost, 1235).
python3 UdpProxy.py --port 1234 --dst-ip 127.0.0.1 --dst-port 1235 --fuzz-in 9
Этот прокси TCP в основном предназначен для размещения между сетевым сервером и брокерами MQTT. Он также предлагает основу для Fuzz Data.
Необязательные аргументы:
-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)
Требуемые аргументы:
--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.
Пример:
Отправить и получать данные от (Localhost, 1884) и (Localhost, 1883)
python3 TcpProxy.py --lcl-port 1884 --dst-ip 127.0.0.1 --dst-port 1883
Этот каталог содержит серию сценариев для разбора, ремесла, брутового и т. Д. Лораван пакеты.
Этот скрипт получает JoinAccept или JoinRequest в Base64 и пытается расшифровать свой Appkey с помощью набора возможных ключей, которые могут быть предоставлены в файле или могут быть сгенерированы на лету.
Необязательные аргументы:
-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
Требуемые аргументы:
-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=
Пример:
Взломайте JoinRequest с набором ключей от my-keys.txt, а также генерируйте APROX. 200000 еще динамически.
python3 BruteForcer.py -a IHvAP4MXo5Qo6tdV+Yfk08o= -r AMQAAAAAhQAAAgAAAAAAAADcYldcgbc= -k ./my-keys.txt
Этот сценарий получает пакет Phypayload в Base64 и ключ, который может быть NWKSkey of AppKey в зависимости от типа пакета и генерирует новый микрофон.
Необязательные аргументы:
-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"
Требуемые аргументы:
-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
Пример:
Подпишите заданный Phypayload с помощью Appkey 00112233445566778899AABBCCDDEEFF.
python3 MicGenerator.py -d AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU= -k 00112233445566778899AABBCCDDEEFF
Этот сценарий получает пакет Lorawan JSON и транслирует его в Base64. Он выполняет обратную как PacketParser.py, поэтому вывод этого сценария можно использовать здесь и наоборот.
Необязательные аргументы:
-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.
Требуемые аргументы:
-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"}'
Пример:
Получите загрузку joinrequest phypayload в Base64 с данными в JSON со значениями, передаваемыми в него.
python3 PacketCrafter.py -j '{"mhdr":{"mType":"JoinRequest","major":"LoRaWANR1"},"macPayload":{"joinEUI":"55d239ac716f234d","devEUI":"b827eb891cf50003","devNonce":51639},"mic":"7005c4a5"}'
Этот скрипт анализирует и печатает одни данные Lorawan Phypayload в Base64. Он выполняет обратный как packetcrafter.py, поэтому вывод этого сценария можно использовать здесь и наоборот.
Необязательные аргументы:
-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
Требуемые аргументы:
-d DATA, --data DATA Base64 data to be parsed. eg. -d
AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU=
Пример:
Получите joinRequest в формате JSON из примера выше.
python3 PacketParser.py -d AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU=
Этот сценарий получает JoinAccept и JoinRequest в Base64 и Appkey для создания клавиш сеанса. Пример использования:
Необязательные аргументы:
-h, --help show this help message and exit
Требуемые аргументы:
-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
Пример:
Получите приложение и NWKSkey со следующими данными соединения.
python3 SessionKeysGenerator.py -r AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU= -a IB1scNmwJRA32RfMbvwe3oI= -k f5a3b185dfe452c8edca3499abcd0341
Это вспомогательные функции, используемые UdpSender.py и UdpProxy.py . В Fuzzer.py вы можете увидеть реализованные режимы пушины.
Общая цель этого каталога состоит в том, чтобы собрать пакеты Lorawan и проанализировать различные аспекты трафика, а также попробовать набор ключей, чтобы попытаться BruteForce Appkey.
Этот каталог содержит набор сценариев, которые получают пакеты Lorawan из разных источников (то есть Gateway Packet_forwarder, Things Network и т. Д.) И сохраняют их в файлах со стандартным форматом. Эти файлы должны быть извлечены позже с помощью Script /auditing/analyzers/LafProcessData.py lafprocessdata.py для выполнения различных подразделений.
Этот сценарий подключается к брокеру MQQT, получает все темы и сохраняет сообщения в файл в указанном поле. Имя файла состоит из даты, когда этот сценарий был запущен.
Необязательные аргументы:
-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 "#.
Требуемые аргументы:
--ip IP MQTT broker ip, eg. --ip 192.168.3.101.
--port PORT MQTT broker port, eg. --port 623.
Пример:
Подключитесь к MQTT брокера с IP 200.200.200.200 в порту по умолчанию (1883).
python3 GenericMqttCollector.py --ip 200.200.200.200 --port 1883
Этот скрип подключается к брокеру loraserver.io MQQT и сохраняет сообщения в БД. Вы должны указать уникальный CollectoreID, и вы можете указать темы, на которые хотите подготовиться.
Необязательные аргументы:
-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 "#.
Требуемые аргументы:
--ip IP MQTT broker ip, eg. --ip 192.168.3.101.
Этот сценарий получает пакеты UDP от прокси UDP в формате Gateway Packet_forwarder и сохраняет их.
Необязательные аргументы:
-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
Требуемые аргументы:
-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.
Пример:
Записывают данные между шлюзом, отправляющим в локальный порт 1700, и сетью XServer Sulding In (Localhost, 1701). Сохраните данные в каталоге ./ .
python3 PacketForwarderCollector.py --name semtech_collector --port 1700
Этот скрипт считывает A из файла или файлов или stdin и выполняет различные подразделения. В зависимости от выбранной опции вы можете выполнить анализ трафика Lorawan, попытаться разобраться в Appkey или проанализировать все полученные пакеты. Эти варианты могут быть объединены.
Необязательные аргументы:
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.
Пример:
Пакеты процессов в БД, начиная с ID 1000 Packet, выполните анализ трафика, и старайтесь взломать Appkeys, приведенные в my-keys.txt, но не генерируйте динамно больше ключей.
python3 LafProcessData.py -a -b -k my-keys.txt --no-gen --from-id 1000
Эти сценарии предоставляют функциональность, представленные LafProcessData.py. Ниже предупреждения, которые реализованы LafPacketAnalysis.py и LafBruteForcer.py :
| ИДЕНТИФИКАТОР | Заголовок | Анализатор | Уровень риска | Описание | Рекомендуемое действие |
|---|---|---|---|---|---|
| LAF-001 | Devnonce повторил | Lafpacketanalysis.py | Низкий | Devnonces для каждого устройства должны быть достаточно случайными, чтобы не столкнуться. Если такая же Devnonce повторялась во многих сообщениях, можно сделать вывод, что устройство находится под атакой воспроизведения. Это атакующий, который захватил JoinRequest и пытается отправить его снова в шлюз. | Проверьте, как генерируются DevNonces: функция, которая их генерирует, должна быть реализована с использованием случайной библиотеки. Более того, вы должны убедиться, что сервер проверяет исторические разработки (они должны сохраняться в БД), чтобы не принимать старый допустимый JoinRequest, ранее отправленный устройством, и, таким образом, генерировать новый сеанс. |
| LAF-002 | DeVeuis, разделяя один и тот же деваддр | Lafpacketanalysis.py | Информация | Два разных устройства могли быть назначены одинаковыми Devaddr. Это не угроза безопасности. | Если устройство превышает активированный воздух (OTAA): проверьте логику, используемую для назначения DevAddrs, и убедитесь, что сервер не назначает один и тот же Devaddr на разные устройства. Если устройство активируется персонализацией (ABP): проверьте Devaddr, настроенный в прошивке устройства, является уникальным в сети Lorawan. |
| LAF-003 | Присоединяйтесь к Replay | Тодо | Середина | Был обнаружен дублированный пакет запроса на соединение, что может означать, что сервер Lorawan находится под атакой воспроизведения. Это атакующий, который, возможно, захватил предыдущий пакет запроса на соединение и отправляет его снова на сервер Lorawan, чтобы попытаться сгенерировать новый сеанс. | Проверьте, как генерируются DevNonces: функция, которая их генерирует, должна быть реализована с использованием случайной библиотеки. Более того, вы должны убедиться, что сервер проверяет исторические разработки (они должны сохраняться в БД), чтобы не принимать старый допустимый JoinRequest, ранее отправленный устройством, и, таким образом, генерировать новый сеанс. |
| LAF-004 | Пакеты данных восходящей линии связи | Тодо | Середина | Был обнаружен дублированный пакет восходящей линии связи, что может означать, что сервер Lorawan находится под атакой воспроизведения. Это атакующий, который, возможно, захватил пакет восходящей линии связи (отправлено с устройства) и отправляет его снова на сервер Lorawan. | В устройствах с активированным воздухом (OTAA): убедитесь, что клавиши сеансов повторно генерируются после сброса каждого устройства или переполнения счетчика, чтобы избежать какого-либо эффекта от этой атаки. При активированном устройствах персонализации (ABP) от Lorawan V1.0.*, Ничего нельзя сделать, чтобы предотвратить атаку повторения, за исключением переключения устройства на OTAA. |
| LAF-005 | Повторение пакетов данных нисходящей линии связи | Тодо | Высокий | Был обнаружен дублированный пакет нисходящей линии связи. Сервер отвечает на атаку повторения или генерирует нетипичный трафик на устройства | Проверьте журналы серверов и проверьте, что предыдущее рекомендуемое действие осуществлено |
| LAF-006 | Возможное устройство ABP (сброс счетчика и без присоединения) | Lafpacketanalysis.py | Высокий | Если счетчик был сброшен (вернулся к 0), деваддр остается таким же, и не было обнаружено предыдущего процесса соединения, может означать, что устройство активируется персонализацией (ABP). Реализация устройств ABP не рекомендуется, потому что процесс соединения не выполняется, что означает, что клавиши сеансов остаются одинаковыми навсегда. Устройство, которое не изменяет свои клавиши сеансов, подвержено различным атакам, таким как Eaveasdrop или Replay. | Все активированные устройствами персонализации (ABP) должны быть заменены для устройств, активированных AIR (OTAA), если это возможно. Реализация устройств ABP обескуражена. |
| LAF-007 | Получил меньший счетчик, чем ожидалось (в отличие от 0) | Lafpacketanalysis.py | Середина | Если злоумышленник получает пару клавиш сеансов (для того, чтобы украсть Appkey в устройствах OTAA или Appskey/Nwkskey на устройствах ABP), он/она сможет отправить поддельные достоверные данные на сервер. Чтобы сервер принял поддельные сообщения, необходимо, чтобы FCNT (счетчик кадров) сообщения был выше, чем FCNT последнего отправленного сообщения. В сценарии, в котором исходное поддельное устройство продолжает отправлять сообщения, сервер начнет отказываться от (допустимых) сообщений, поскольку у них будет меньший FCNT. Следовательно, когда получаются сообщения с меньшим значением FCNT, чем ожидалось на сервере Lorawan, можно сделать вывод, что был установлен параллельный сеанс. | Если устройство находится над устройством активированного воздуха (OTAA), измените его Appkey, потому что оно было скомпрометировано. Если он активируется персонализацией, измените его приложение и NWKSkey. Более того, убедитесь, что сервер Lorawan обновляется и не принимает дублированные сообщения. |
| LAF-008 | Пароль взломал joinRequest | Lafbruteforcer.py | Высокий | Было возможно расшифровать сообщение JoinRequest, используя известный AppKey. | Используйте разные приложения, чем те, которые предоставляются поставщиками или используйте более случайные ключи. |
| LAF-009 | Пароль взломал | Lafbruteforcer.py | Высокий | Приложение устройства было найдено, пытаясь с хорошо известной или неровной строкой. Он был расшифрован с использованием пары сообщений соединения (запрос и принять). | Используйте генератор случайных ключей для Appkey вместо использования поставщиков. Более того, не устанавливайте одно и то же Appkey на более чем одно устройство и не генерируйте приложения, используя предсказуемую логику (например, инкрементные значения, перевернуть определенные байты и т. Д.) |
| LAF-010 | Ворота изменила местоположение | Lafpacketanalysis.py | Середина | Если шлюз не должен менять свое местоположение. Возможно, он был украден, перемещен, или поддельные ворота могут пытаться выдать себя за законные шлюзы. | Убедитесь, что шлюз не был подделан, как физически, так и логически. |
Этот каталог предоставляет набор обертка для библиотеки https://github.com/brocaar/lorawan/, которая написана в Голанге. Эти функции реализованы инструментами.
Здесь вы найдете серию сценариев, предназначенных для автоматизации различных задач. Обязательно дайте им разрешение на выполнение, если это необходимо ( chmod +x your_script для Linux/MacOS).
Легко установите свой шлюз и переключите его каналы для понюхания. Для получения дополнительной информации о том, как их использовать, вы можете увидеть Readme в этом каталоге.
Этот сценарий используется для установки всех необходимых программных пакетов на Raspberry Pi для создания шлюза Lorawan в сочетании с подключенным концентратором Lora (IC980-SPI, RHF0M301-SPI, RAK831-SPI или любой другой по ручной настройке).
Поскольку невозможно узнать, на каких частотах работают устройства LORA, мы создали сценарий, который может переключать каналы шлюзов с полос частот US915 и EU868 для обнюхивания. Хотя есть профессиональные и дорогие шлюзы, которые поддерживают 32 или 64 канала, большинство шлюзов поддерживают до 8 каналов. Этот сценарий предназначен для запуска в такого рода шлюзах.
По крайней мере, в полосе частот US915 первые 8 каналов являются наиболее используемыми. Но есть хорошо известные реализации, которые используют другую группу канала, например, сети вещей, в которых используется вторая группа (8-15) каналов для общения восходящей линии связи.
В настоящее время мы не поддерживаем другие частотные полосы, но с небольшими изменениями в этих сценариях вы сможете сделать это самостоятельно :).
Мы загрузили видео с этой структурой в действии (тот же сценарий, представленный на Blackhat 2019): https://youtu.be/mm6a2rvnocs. Подробные шаги демонстрации находятся в описании видео на YouTube.
Тодо
Этот проект лицензирован по лицензии BSD-3-CLAUSE.