การปรับใช้ IoT เพิ่มขึ้นเรื่อย ๆ และส่วนหนึ่งของการเติบโตที่สำคัญนั้นประกอบด้วยเซ็นเซอร์ LPWAN (เครือข่ายพื้นที่กว้างพลังงานต่ำ) หลายล้านเซ็นเซอร์ที่นำไปใช้กับหลายร้อยเมือง (เมืองอัจฉริยะ) ทั่วโลกรวมถึงอุตสาหกรรมและบ้าน หนึ่งในเทคโนโลยี LPWAN ที่ใช้มากที่สุดคือ LORA ซึ่ง Lorawan เป็นมาตรฐานเครือข่าย (เลเยอร์ MAC) Lorawan เป็นโปรโตคอลที่ปลอดภัยที่มีการเข้ารหัสในตัว แต่ปัญหาการใช้งานและจุดอ่อนส่งผลกระทบต่อความปลอดภัยของการปรับใช้ในปัจจุบันส่วนใหญ่
โครงการนี้มุ่งมั่นที่จะจัดหาชุดเครื่องมือในการประดิษฐ์แยกวิเคราะห์ส่งวิเคราะห์และถอดชุดแพ็คเก็ต Lorawan เพื่อตรวจสอบหรือ pentest ความปลอดภัยของโครงสร้างพื้นฐาน 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 เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับการแมปพอร์ต Dockerlocalhost ดูคำแนะนำด้านล่างเพื่อตั้งค่า Dockerคำแนะนำเหล่านี้จะได้รับสำเนาของโครงการและการพึ่งพาในเครื่องท้องถิ่นของคุณ คำสั่งด้านล่างนี้มีไว้สำหรับสภาพแวดล้อมที่ใช้ Debian:
โคลนที่เก็บนี้: git clone --recurse-submodules https://github.com/IOActive/laf.git
ติดตั้ง Python3:
sudo apt-get updatesudo apt-get install python3.6ดาวน์โหลดและติดตั้ง Python Dependencies:
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"Compile Go Library:
cd laf/lorawanwrapper/utilsgo build -o lorawanWrapper.so -buildmode=c-shared jsonUnmarshaler.go lorawanWrapper.go micGenerator.go sessionKeysGenerator.go hashGenerator.goขึ้นอยู่กับว่าคุณต้องการใช้ฐานข้อมูลใด:
. POSTRESQL: ทำตามคำแนะนำ 'ติดตั้ง LAF โดยใช้ Docker' จนถึงขั้นตอนที่ 3
ข. sqlite:
cd laf/auditing/db__init__.py ด้วยตัวแก้ไขข้อความที่คุณต้องการและแสดงความคิดเห็นบรรทัดที่จะใช้กับ postgres (ตัวแปรการเชื่อมต่อ db และสภาพแวดล้อม) การลดความไม่ลงรอยกันของบรรทัดที่จะใช้กับ sqliteแล้วก็แค่ไหน!
วิธีการนี้หลีกเลี่ยงการจัดการกับการติดตั้งการพึ่งพาและเริ่มต้น PostgreSQL DB ซึ่งเครื่องมือบันทึกแพ็กเก็ตและข้อมูล ภาชนะบรรจุ:
ขั้นตอน:
git clone https://github.com/IOActive/laf.gitcd laf/docker-compose up --builddocker exec -ti laf_tools_1 /bin/bashคุณสามารถตรวจสอบข้อมูลใน db โดยใช้ PGADMIN:
ก่อนอื่นให้เข้าถึง pgadmin:
จากนั้นคุณต้องเพิ่มเซิร์ฟเวอร์:
นี่คือคำอธิบายของไดเรกทอรีและเครื่องมือ / ฟังก์ชั่นภายใน
วัตถุประสงค์หลักของเครื่องมือที่ให้ไว้ในไดเรกทอรีนี้คือการลดการทดสอบการเจาะเข้าไปในโครงสร้างพื้นฐานของ Lorawan
เครื่องมือนี้มีจุดประสงค์เพื่อส่งแพ็กเก็ตอัปลิงค์ (ไปยังเซิร์ฟเวอร์เครือข่ายหรือ GatewayBridge ขึ้นอยู่กับโครงสร้างพื้นฐาน) หรือแพ็คเก็ต downlink (ไปยังแพ็กเก็ต-ล่วงหน้า) สามารถเลือกแพ็คเก็ตได้และสามารถคำนวณไมโครโฟนที่ถูกต้องได้
อาร์กิวเมนต์เสริม:
-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) จากพอร์ต 10,000 ฟัซซิงแบบสุ่มไมโครโฟนและ 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) และเซิร์ฟเวอร์เครือข่ายหรือเกตเวย์บริดจ์ขึ้นอยู่กับโครงสร้าง infraestructure ที่กำลังประเมิน นอกจากนี้ยังมีความเป็นไปได้ในการใช้ข้อมูลฟัซซี่ในทิศทางที่ต้องการ (อัปลิงค์หรือดาวน์ลิงค์)
อาร์กิวเมนต์เสริม:
-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
อาร์กิวเมนต์เสริม:
-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
ไดเรกทอรีนี้มีชุดสคริปต์เพื่อแยกวิเคราะห์, งานฝีมือ, Bruteforcer ฯลฯ Lorawan แพ็คเก็ต
สคริปต์นี้ได้รับการเข้าร่วมหรือเข้าร่วมใน 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=
ตัวอย่าง:
ถอดรหัสการเข้าร่วมด้วยชุดคีย์จาก my-keys.txt และสร้าง aprox 200000 ยิ่งขึ้น
python3 BruteForcer.py -a IHvAP4MXo5Qo6tdV+Yfk08o= -r AMQAAAAAhQAAAgAAAAAAAADcYldcgbc= -k ./my-keys.txt
สคริปต์นี้ได้รับแพ็คเก็ต phypayload ใน Base64 และคีย์ซึ่งสามารถเป็น nwkskey ของ 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 001122334455566778899aabbccddeeff
python3 MicGenerator.py -d AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU= -k 00112233445566778899AABBCCDDEEFF
สคริปต์นี้ได้รับแพ็คเก็ต Lorawan JSON และ tranforms เป็น 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"}'
ตัวอย่าง:
รับ phypayload joinRequest ใน base64 โดยให้ใน JSON โดยมีค่าที่ส่งผ่านไป
python3 PacketCrafter.py -j '{"mhdr":{"mType":"JoinRequest","major":"LoRaWANR1"},"macPayload":{"joinEUI":"55d239ac716f234d","devEUI":"b827eb891cf50003","devNonce":51639},"mic":"7005c4a5"}'
สคริปต์นี้แยกวิเคราะห์และพิมพ์ข้อมูล phypayload Lorawan เดียวใน 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=
สคริปต์นี้ได้รับการเข้าร่วมและการเข้าร่วมใน 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
ตัวอย่าง:
รับ AppSkey และ NWKSKEY พร้อมข้อมูลการเข้าร่วมต่อไปนี้
python3 SessionKeysGenerator.py -r AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU= -a IB1scNmwJRA32RfMbvwe3oI= -k f5a3b185dfe452c8edca3499abcd0341
เหล่านี้เป็นฟังก์ชั่นเสริมที่ใช้โดย UdpSender.py และ UdpProxy.py ใน Fuzzer.py คุณสามารถเห็นโหมดฟัซซิ่งที่ใช้งานได้
วัตถุประสงค์ทั่วไปของไดเรกทอรีนี้คือการรวบรวมแพ็คเก็ต Lorawan และวิเคราะห์แง่มุมต่าง ๆ ของการรับส่งข้อมูลรวมถึงลองใช้ชุดกุญแจเพื่อลองใช้ breuteforce appkey
ไดเรกทอรีนี้มีชุดสคริปต์ที่ได้รับแพ็คเก็ต Lorawan จากแหล่งต่าง ๆ (เช่น Gateway Packet_Forwarder, Things Network ฯลฯ ) และบันทึกไว้ในไฟล์ด้วยรูปแบบมาตรฐาน ไฟล์นี้ควรถูกดึงในภายหลังโดยสคริปต์/การตรวจสอบ /auditing/analyzers/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 และบันทึกข้อความลงใน DB คุณต้องระบุ collectorID ที่ไม่ซ้ำกันและคุณสามารถระบุหัวข้อที่คุณต้องการให้ถูกต้อง
อาร์กิวเมนต์เสริม:
-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 ฟังใน (LocalHost, 1701) บันทึกข้อมูลใน ./ ไดเรกทอรี
python3 PacketForwarderCollector.py --name semtech_collector --port 1700
สคริปต์นี้อ่านจากไฟล์หรือไฟล์หรือ stdin และดำเนินการเครื่องมือย่อยที่แตกต่างกัน ขึ้นอยู่กับตัวเลือกที่เลือกคุณสามารถดำเนินการวิเคราะห์ปริมาณการใช้งานของ Lorawan พยายามที่จะ bruteforce 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 ดำเนินการวิเคราะห์การจราจรและพยายามที่จะถอดรหัส 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 เดียวกันถูกทำซ้ำในหลายข้อความก็สามารถอนุมานได้ว่าอุปกรณ์อยู่ภายใต้การโจมตีซ้ำ นี่คือผู้โจมตีที่จับคู่เข้าร่วมและพยายามส่งไปที่เกตเวย์อีกครั้ง | ตรวจสอบว่า devnonces ถูกสร้างขึ้นอย่างไร: ฟังก์ชั่นที่สร้างขึ้นควรใช้งานโดยใช้ไลบรารีแบบสุ่ม ยิ่งไปกว่านั้นคุณต้องตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ตรวจสอบ devnonces ในอดีต (ควรมีการคงอยู่ใน db) เพื่อไม่ให้ยอมรับการเข้าร่วมที่ถูกต้องเก่าที่ส่งมาก่อนหน้านี้โดยอุปกรณ์และสร้างเซสชันใหม่ |
| LAF-002 | Deveuis แบ่งปัน devaddr เดียวกัน | lafpacketanalysis.py | ข้อมูล | อุปกรณ์สองตัวที่แตกต่างกันอาจได้รับมอบหมาย devaddr เดียวกัน นี่ไม่ใช่ภัยคุกคามด้านความปลอดภัย | หากอุปกรณ์อยู่เหนือ Air Activated (OTAA): ตรวจสอบตรรกะที่ใช้ในการกำหนด devaddrs และตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ไม่ได้กำหนด devaddr เดียวกันให้กับอุปกรณ์ที่แตกต่างกัน หากอุปกรณ์เปิดใช้งานโดย Personalization (ABP): ตรวจสอบ devaddr ที่กำหนดค่าในเฟิร์มแวร์ของอุปกรณ์นั้นไม่ซ้ำกันในเครือข่าย Lorawan |
| LAF-003 | เข้าร่วมเล่นซ้ำ | สิ่งที่ต้องทำ | ปานกลาง | ตรวจพบแพ็คเก็ตคำขอเข้าร่วมซ้ำซึ่งอาจบ่งบอกว่าเซิร์ฟเวอร์ Lorawan อยู่ภายใต้การโจมตีซ้ำ นี่คือผู้โจมตีที่อาจจับแพ็คเก็ตคำขอเข้าร่วมก่อนหน้านี้และกำลังส่งไปยังเซิร์ฟเวอร์ Lorawan อีกครั้งเพื่อพยายามสร้างเซสชันใหม่ | ตรวจสอบว่า devnonces ถูกสร้างขึ้นอย่างไร: ฟังก์ชั่นที่สร้างขึ้นควรใช้งานโดยใช้ไลบรารีแบบสุ่ม ยิ่งไปกว่านั้นคุณต้องตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ตรวจสอบ devnonces ในอดีต (ควรมีการคงอยู่ใน db) เพื่อไม่ให้ยอมรับการเข้าร่วมที่ถูกต้องเก่าที่ส่งมาก่อนหน้านี้โดยอุปกรณ์และสร้างเซสชันใหม่ |
| LAF-004 | อัปลิงค์แพ็คเก็ตข้อมูลซ้ำ | สิ่งที่ต้องทำ | ปานกลาง | ตรวจพบแพ็คเก็ตอัปลิงค์ที่ซ้ำกันซึ่งอาจบ่งบอกว่าเซิร์ฟเวอร์ Lorawan อยู่ภายใต้การโจมตีซ้ำ นี่คือผู้โจมตีที่อาจจับแพ็คเก็ตอัปลิงค์ (ส่งจากอุปกรณ์) และกำลังส่งอีกครั้งไปยังเซิร์ฟเวอร์ Lorawan | ในอุปกรณ์ Over Air Activated (OTAA): ตรวจสอบให้แน่ใจว่าคีย์เซสชันจะถูกสร้างขึ้นใหม่หลังจากอุปกรณ์ทั้งหมดรีเซ็ตหรือตัวนับล้นเพื่อหลีกเลี่ยงผลกระทบใด ๆ จากการโจมตีนี้ ด้วยอุปกรณ์ที่เปิดใช้งานโดยอุปกรณ์ส่วนตัว (ABP) จาก Lorawan v1.0.*ไม่มีอะไรสามารถทำได้เพื่อป้องกันการโจมตีซ้ำยกเว้นจากการเปลี่ยนอุปกรณ์เป็น OTAA |
| LAF-005 | แพ็คเก็ตข้อมูล downlink เล่นซ้ำ | สิ่งที่ต้องทำ | สูง | ตรวจพบแพ็คเก็ต downlink ที่ซ้ำกัน เซิร์ฟเวอร์กำลังตอบสนองต่อการโจมตีซ้ำหรือกำลังสร้างทราฟฟิกที่ผิดปกติไปยังอุปกรณ์ | ตรวจสอบบันทึกของเซิร์ฟเวอร์และตรวจสอบว่ามีการดำเนินการที่แนะนำก่อนหน้านี้ |
| LAF-006 | อุปกรณ์ ABP ที่เป็นไปได้ (รีเซ็ตตัวนับและไม่มีการเข้าร่วม) | lafpacketanalysis.py | สูง | หากตัวนับถูกรีเซ็ต (กลับมาเป็น 0) devaddr จะถูกเก็บไว้เหมือนกันและไม่พบกระบวนการเข้าร่วมก่อนหน้านี้อาจบ่งบอกว่าอุปกรณ์นั้นเปิดใช้งานโดยการปรับเปลี่ยนแบบส่วนตัว (ABP) การใช้งานอุปกรณ์ ABP นั้นไม่ได้รับการสนับสนุนเนื่องจากไม่มีกระบวนการเข้าร่วมซึ่งหมายความว่าคีย์เซสชันจะถูกเก็บไว้เหมือนเดิมตลอดไป อุปกรณ์ที่ไม่เปลี่ยนคีย์เซสชันมีแนวโน้มที่จะโจมตีที่แตกต่างกันเช่น Eaveasdrop หรือ Replay | อุปกรณ์ทั้งหมดที่เปิดใช้งานโดยอุปกรณ์ส่วนบุคคล (ABP) ควรถูกแทนที่สำหรับอุปกรณ์ที่เปิดใช้งานอากาศ (OTAA) หากเป็นไปได้ การใช้งานอุปกรณ์ ABP นั้นไม่ได้รับการสนับสนุน |
| LAF-007 | ได้รับเคาน์เตอร์ที่เล็กกว่าที่คาดไว้ (แตกต่างจาก 0) | lafpacketanalysis.py | ปานกลาง | หากผู้โจมตีได้รับคีย์เซสชันคู่หนึ่ง (สำหรับการขโมย Appkey ในอุปกรณ์ OTAA หรือ AppSkey/NWKSKEY ในอุปกรณ์ ABP) เขา/เธอจะสามารถส่งข้อมูลปลอมที่ถูกต้องไปยังเซิร์ฟเวอร์ได้ เพื่อให้เซิร์ฟเวอร์ยอมรับข้อความปลอมแปลงเป็นสิ่งจำเป็นสำหรับ FCNT (ตัวนับเฟรม) ของข้อความที่สูงกว่า FCNT ของข้อความล่าสุดที่ส่ง ในสถานการณ์ที่อุปกรณ์ปลอมตัวเดิมส่งข้อความเซิร์ฟเวอร์จะเริ่มทิ้งข้อความ (ถูกต้อง) เนื่องจากพวกเขาจะมี FCNT ที่เล็กกว่า ดังนั้นเมื่อได้รับข้อความที่มีค่า FCNT ที่เล็กกว่าที่คาดไว้โดยเซิร์ฟเวอร์ Lorawan จะได้รับมันเป็นไปได้ที่จะอนุมานว่ามีการสร้างเซสชันแบบขนาน | หากอุปกรณ์อยู่เหนืออุปกรณ์เปิดใช้งานอากาศ (OTAA) ให้เปลี่ยน appkey ของมันเพราะอาจถูกบุกรุก หากเปิดใช้งานโดยการตั้งค่าส่วนบุคคลให้เปลี่ยน AppSkey และ NWKSKEY ยิ่งกว่านั้นตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ Lorawan ได้รับการปรับปรุงและไม่รับข้อความที่ซ้ำกัน |
| LAF-008 | รหัสผ่านแตกด้วย joinrequest | lafbruteforcer.py | สูง | มันเป็นไปได้ที่จะถอดรหัสข้อความเข้าร่วมโดยใช้ appkey ที่รู้จัก | ใช้ appkeys ที่แตกต่างจากที่จัดทำโดยผู้ขายหรือใช้ปุ่มสุ่มเพิ่มเติม |
| LAF-009 | รหัสผ่านแตก | lafbruteforcer.py | สูง | appkey ของอุปกรณ์พบว่าพยายามด้วยสตริงที่รู้จักกันดีหรือไม่สุ่ม มันถูกถอดรหัสโดยใช้ข้อความเข้าร่วมคู่หนึ่ง (คำขอและยอมรับ) | ใช้เครื่องกำเนิดคีย์แบบสุ่มสำหรับ appkey แทนการใช้สิ่งที่ผู้ขายจัดหาให้ ยิ่งไปกว่านั้นอย่าตั้งค่า appkey เดียวกันเป็นมากกว่าหนึ่งอุปกรณ์และไม่สร้าง appkeys โดยใช้ตรรกะที่คาดการณ์ได้ (เช่นค่าที่เพิ่มขึ้น, พลิกไบต์บางอย่าง ฯลฯ ) |
| LAF-010 | เกตเวย์เปลี่ยนตำแหน่ง | lafpacketanalysis.py | ปานกลาง | หากเกตเวย์ไม่ควรเปลี่ยนตำแหน่ง มันอาจถูกขโมยย้ายหรือเกตเวย์ปลอมอาจพยายามเลียนแบบเกตเวย์ที่ถูกกฎหมาย | ตรวจสอบให้แน่ใจว่าเกตเวย์ไม่ได้ถูกดัดแปลงทั้งทางร่างกายหรือแบบมีเหตุผล |
ไดเรกทอรีนี้มีชุดเครื่องห่อสำหรับห้องสมุด https://github.com/brocaar/lorawan/ ซึ่งเขียนไว้ใน Golang ฟังก์ชั่นเหล่านี้ถูกนำไปใช้โดยเครื่องมือ
ที่นี่คุณจะพบชุดสคริปต์ที่มีจุดประสงค์เพื่อทำงานที่แตกต่างกันโดยอัตโนมัติ ตรวจสอบให้แน่ใจว่าให้สิทธิ์การดำเนินการหากจำเป็น ( chmod +x your_script สำหรับ Linux/MacOS)
ตั้งค่าเกตเวย์ของคุณได้อย่างง่ายดายและสลับช่องเพื่อจุดประสงค์ในการดมกลิ่น สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการใช้งานคุณสามารถดู readMe ในไดเรกทอรีนี้
สคริปต์นี้ใช้ในการติดตั้งแพ็คเกจซอฟต์แวร์ที่จำเป็นทั้งหมดบน Raspberry Pi สำหรับการสร้างเกตเวย์ Lorawan ร่วมกับ Lora Concentrator ที่เชื่อมต่อ (IC980-SPI, RHF0M301-SPI, RAK831-SPI หรืออื่น ๆ โดยการตั้งค่าด้วยตนเอง)
เนื่องจากเป็นไปไม่ได้ที่จะรู้ว่าอุปกรณ์ LORA ใช้งานความถี่ใดเราจึงได้สร้างสคริปต์ที่สามารถเปลี่ยนช่องทางเกตเวย์จาก US915 และ EU868 Bands ความถี่ เพื่อจุดประสงค์ในการดมกลิ่น แม้ว่าจะมีเกตเวย์มืออาชีพและมีราคาแพงที่รองรับ 32 หรือ 64 ช่อง แต่เกตเวย์ส่วนใหญ่รองรับได้ถึง 8 ช่อง สคริปต์นี้มีจุดประสงค์เพื่อทำงานในเกตเวย์ประเภทนี้
อย่างน้อยในวงดนตรีความถี่ US915 ช่อง 8 ช่องแรกนั้นใช้มากที่สุด แต่มีการใช้งานที่รู้จักกันดีซึ่งใช้กลุ่มช่องอื่นเช่นเครือข่ายสิ่งต่าง ๆ ซึ่งใช้กลุ่มที่สอง (8-15) ช่องสำหรับการสื่อสารอัปลิงค์
ขณะนี้เราไม่สนับสนุนแถบความถี่อื่น ๆ แต่ด้วยการเปลี่ยนแปลงสคริปต์เหล่านี้เล็กน้อยคุณจะสามารถทำสิ่งนี้ได้ด้วยตัวเอง :)
เราอัปโหลดวิดีโอของเฟรมเวิร์กนี้ในการดำเนินการ (สถานการณ์เดียวกันที่นำเสนอที่ Blackhat 2019): https://youtu.be/mm6a2rvnocs ขั้นตอนโดยละเอียดของการสาธิตอยู่ในคำอธิบายวิดีโอ YouTube
สิ่งที่ต้องทำ
โครงการนี้ได้รับใบอนุญาตภายใต้ใบอนุญาต BSD-3-Clause