Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ss:laboratoare:05 [2025/02/20 16:30]
127.0.0.1 external edit
ss:laboratoare:05 [2026/03/30 19:39] (current)
ciprian.popescu0411 [Exerciții]
Line 1: Line 1:
-===== Laboratorul 05. =====+====== Laborator 5: Securizarea unui proiect embedded pe ESP32-CAM ======
  
 +În acest laborator ne vom concentra pe securizarea completă a sistemului, de la layer-ul de transport (TLS) până la codul sursă și hardware-ul propriu-zis.
  
 +===== Obiective =====
 +
 +  - Implementarea comunicației criptate (MQTT peste TLS).
 +  - Analiza securității codului folosind unelte automate (''​bandit'',​ ''​cppcheck''​).
 +  - Mecanisme de protecție a firmware-ului (Secure Boot, Flash Encryption).
 +
 +===== Partea 1: Securizarea transportului (TLS/SSL) =====
 +
 +Până acum, traficul MQTT (inclusiv imaginile) circulă **în clar** prin rețea. Oricine conectat la aceeași rețea poate intercepta datele cu un simplu Wireshark. Vom securiza comunicația folosind **TLS (Transport Layer Security)**.
 +
 +==== 1.1 Generarea certificatelor (OpenSSL) ====
 +
 +Vom crea o **Autoritate de Certificare (CA)** proprie care va semna certificatele serverului.
 +
 +<note important>​
 +Modern OpenSSL validează adresele IP prin câmpul **Subject Alternative Name (SAN)**, nu doar prin Common Name (CN). Comenzile de mai jos includ acest câmp.
 +</​note>​
 +
 +Creați un director ''​certs''​ în rădăcina proiectului:​
 +
 +<code bash>
 +mkdir certs && cd certs
 +</​code>​
 +
 +=== Pasul 1: Generarea CA (Certificate Authority) ===
 +
 +<code bash>
 +# Cheia privată a CA
 +openssl genrsa -out ca.key 2048
 +
 +# Certificatul CA (auto-semnat,​ valabil 10 ani)
 +openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt \
 +    -subj "/​CN=SS-Project-CA"​
 +</​code>​
 +
 +=== Pasul 2: Generarea certificatului pentru broker (Server) ===
 +
 +Înlocuiți ''​ADRESA_IP_BROKER''​ cu IP-ul real al mașinii pe care rulează Mosquitto (ex: ''​192.168.1.100''​):​
 +
 +<code bash>
 +# Cheia privată a serverului
 +openssl genrsa -out server.key 2048
 +
 +# Cererea de semnare (CSR) cu Subject Alternative Name
 +openssl req -new -key server.key -out server.csr \
 +    -subj "/​CN=ADRESA_IP_BROKER"​ \
 +    -addext "​subjectAltName=IP:​ADRESA_IP_BROKER"​
 +
 +# Semnarea certificatului de către CA (valabil 1 an)
 +openssl x509 -req -in server.csr \
 +    -CA ca.crt -CAkey ca.key -CAcreateserial \
 +    -out server.crt -days 365 -sha256 \
 +    -copy_extensions copyall
 +</​code>​
 +
 +=== Verificare ===
 +
 +<code bash>
 +# Verificați că certificatul serverului conține SAN-ul corect
 +openssl x509 -in server.crt -text -noout | grep -A1 "​Subject Alternative Name"
 +# Ar trebui să vedeți: IP Address:​ADRESA_IP_BROKER
 +</​code>​
 +
 +==== 1.2 Configurarea Mosquitto cu TLS ====
 +
 +Creați un fișier ''​mosquitto_secure.conf'':​
 +
 +<file bash mosquitto_secure.conf>​
 +listener 8883
 +cafile ./​certs/​ca.crt
 +certfile ./​certs/​server.crt
 +keyfile ./​certs/​server.key
 +require_certificate false
 +</​file>​
 +
 +Porniți brokerul securizat:
 +
 +<code bash>
 +sudo systemctl stop mosquitto.service
 +mosquitto -c mosquitto_secure.conf -v
 +</​code>​
 +
 +Ar trebui să vedeți în log: ''​Opening ipv4 listen socket on port 8883.''​
 +
 +==== 1.3 Actualizarea receiver-ului Python ====
 +
 +Adăugați o singură linie înainte de ''​client.connect()'':​
 +
 +<code python>
 +# Activăm TLS cu certificatul CA
 +client.tls_set(ca_certs="​certs/​ca.crt"​)
 +
 +# Schimbăm portul la 8883
 +client.connect(BROKER,​ 8883, 60)
 +</​code>​
 +
 +Testați: rulați receiver-ul și verificați că se conectează fără erori.
 +
 +==== 1.4 Actualizarea firmware-ului ESP32 ====
 +
 +Modificați ''​main.cpp''​ pentru a folosi ''​WiFiClientSecure'':​
 +
 +<file cpp main.cpp>​
 +#include <​WiFiClientSecure.h> ​ // Înlocuiește <​WiFi.h>​ pentru TLS
 +
 +// Copiați conținutul fișierului ca.crt aici (inclusiv BEGIN/END):
 +const char* ca_cert = \
 +"​-----BEGIN CERTIFICATE-----\n"​ \
 +"​MIIDaz... (conținutul certificatului vostru) ...\n" \
 +"​-----END CERTIFICATE-----\n";​
 +
 +// Înlocuiți WiFiClient cu WiFiClientSecure
 +WiFiClientSecure espClient;
 +
 +void setup() {
 +  // ... (după conectarea la WiFi)
 +  ​
 +  // Încărcăm certificatul CA
 +  espClient.setCACert(ca_cert);​
 +  ​
 +  // Portul devine 8883
 +  client.setServer(mqtt_server,​ 8883);
 +  // ...
 +}
 +</​file>​
 +
 +<​note>​
 +**Debugging**:​ Dacă ESP32 refuză conexiunea cu ''​SSL handshake failed'',​ verificați:​
 +  - CN/SAN-ul certificatului corespunde IP-ului brokerului.
 +  - Ceasul ESP32 este aproximativ corect (certificatele au dată de expirare).
 +  - Ca test temporar, puteți folosi ''​espClient.setInsecure()''​ pentru a dezactiva validarea.
 +</​note>​
 +
 +===== Partea 2: Analiza statică a codului (SAST) =====
 +
 +Folosim unelte automate pentru a găsi vulnerabilități **fără a rula** codul.
 +
 +==== 2.1 Bandit (Python) ====
 +
 +Analizează codul Python pentru probleme de securitate.
 +
 +<code bash>
 +pip install bandit
 +bandit -r receiver/
 +</​code>​
 +
 +**Ce caută Bandit?**
 +
 +  * **Hardcoded secrets**: Parole sau chei scrise direct în cod.
 +  * **Weak cryptography**:​ Algoritmi învechiți (MD5, SHA1 pentru hashing de securitate).
 +  * **Subprocess injection**:​ Apeluri ''​os.system()''​ sau ''​subprocess''​ cu input nesanitizat.
 +
 +==== 2.2 Cppcheck (C/C++) ====
 +
 +Analizează codul firmware-ului pentru bug-uri și vulnerabilități.
 +
 +<code bash>
 +sudo apt-get install cppcheck
 +cppcheck --enable=all --inconclusive --std=c++11 camera/src/
 +</​code>​
 +
 +**Ce caută Cppcheck?**
 +
 +  * **Buffer overflows**:​ Scrierea în afara limitelor unui array (critic pe dispozitive embedded!).
 +  * **Uninitialized variables**:​ Comportament nedefinit care poate cauza crash-uri aleatorii.
 +  * **Memory leaks**: Pierderi de memorie care duc la blocarea dispozitivului în timp.
 +  * **Null pointer dereference**:​ Accesarea unui pointer nul.
 +
 +===== Partea 3: Securitatea hardware (ESP32) =====
 +
 +Chiar dacă comunicația este criptată și codul este curat, un atacator cu **acces fizic** la dispozitiv poate extrage firmware-ul sau cheile TLS din memoria flash.
 +
 +==== 3.1 Flash encryption ====
 +
 +Criptează conținutul memoriei flash (cod + date) cu o cheie AES stocată în **eFuse** (memorie **write-once** din cip, imposibil de citit prin software).
 +  * Dacă un atacator copiază flash-ul fizic, va vedea doar date criptate.
 +  * Dispozitivul decriptează transparent codul la boot.
 +
 +==== 3.2 Secure Boot ====
 +
 +Verifică **semnătura digitală** a firmware-ului la fiecare pornire.
 +  * Dezvoltatorul semnează firmware-ul cu o cheie privată.
 +  * Bootloader-ul verifică semnătura — dacă nu se potrivește (firmware modificat), dispozitivul **refuză să pornească**.
 +  * Previne instalarea de firmware malițios.
 +
 +==== 3.3 Verificarea stării cu ''​espefuse.py''​ ====
 +
 +Putem inspecta starea de securitate a unui cip **fără a modifica nimic**:
 +
 +<code bash>
 +espefuse.py --port /​dev/​ttyACM0 summary
 +</​code>​
 +
 +Urmăriți secțiunea **Security fuses**:
 +  * ''​FLASH_CRYPT_CNT'':​ Contor criptare flash (0 = dezactivat).
 +  * ''​ABS_DONE_0'':​ Secure Boot (0 = dezactivat, 1 = activat).
 +
 +<note warning>
 +**PERICOL DE BRICK-UIRE PERMANENTĂ A PLĂCUȚEI DE LABORATOR!**
 +
 +Comenzile ''​espefuse.py burn_efuse'',​ ''​espefuse.py burn_key''​ și ''​espefuse.py write_protect_efuse''​ sunt **IREVERSIBILE**. eFuse-urile sunt memorii **one-time programmable** — odată scrise, nu mai pot fi modificate sau resetate. O comandă greșită va face plăcuța **complet inutilizabilă (bricked)**.
 +
 +**Reguli stricte:**
 +  - Folosiți **NUMAI** comanda ''​summary''​ (doar citire).
 +  - **NU** rulați **NICIO** altă comandă `espefuse.py` fără aprobarea asistentului.
 +  - Dacă vedeți un tutorial online care vă cere să scrieți eFuse-uri, **IGNORAȚI-L**! Acele operații sunt pentru producția de serie, nu pentru laborator.
 +  - Studenții care distrug plăcuțe prin neglijență vor fi responsabili de înlocuirea lor.
 +</​note>​
 +
 +===== Exerciții =====
 +
 +  - **Implementare TLS**: Urmăriți pașii din Partea 1 pentru a securiza comunicația. Verificați cu Wireshark că traficul pe portul 8883 este criptat (comparativ cu portul 1883 din laboratorul anterior).
 +  - **Secret management**:​ Modificați ''​main.cpp''​ și ''​receiver.py''​ astfel încât credențialele să nu mai fie hardcodate:
 +    * **Python**: Citiți din variabile de mediu (''​os.getenv("​MQTT_BROKER"​)''​).
 +    * **ESP32**: Creați un fișier ''​include/​secrets.h''​ cu credențialele și adăugați-l în ''​.gitignore''​.
 +  - **Analiza vulnerabilității**:​ Rulați ''​bandit''​ și ''​cppcheck''​ pe codul vostru. Documentați toate problemele găsite și remediați cele de nivel "​High"​ și "​Medium"​.
ss/laboratoare/05.1740061822.txt.gz · Last modified: 2025/02/26 00:15 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0