/*
* Практическая работа 3 — Модель угроз встроенной системы
* Система: Система контроля доступа (Электронный замок)
* Компоненты: Arduino Uno + Servo + LCD1602 (I2C) + LED + Buzzer
*
* Анализ STRIDE:
* S - Spoofing : Подделка карты доступа
* T - Tampering : Несанкционированное изменение списка карт
* R - Repudiation : Отрицание факта доступа (журнал аудита)
* I - Info Disclosure: Утечка UID карты
* D - DoS : Блокировка системы повторными запросами
* E - Elevation : Получение прав администратора
*
* Симуляция: Зелёная кнопка = правильная карта, Красная = неправильная
*/
#include <Servo.h>
#include <LiquidCrystal_I2C.h>
// ── Пины ────────────────────────────────────
#define BTN_VALID 2 // Зелёная кнопка — правильная карта
#define BTN_INVALID 3 // Красная кнопка — попытка взлома
#define LED_GREEN 6 // Доступ разрешён
#define LED_RED 7 // Доступ запрещён / тревога
#define BUZZER_PIN 8 // Звуковой сигнал
#define SERVO_PIN 9 // Сервопривод замка
// ── Параметры безопасности ───────────────────
#define MAX_ATTEMPTS 3 // Макс. попыток до блокировки (DoS защита)
#define BLOCK_TIME 30000 // Время блокировки: 30 секунд
#define DOOR_OPEN_TIME 5000 // Дверь открыта: 5 секунд
#define SERVO_OPEN 90 // Угол открытия замка
#define SERVO_CLOSE 0 // Угол закрытия замка
// ── Авторизованные карты (Tampering защита) ──
// В реальной системе хранится в защищённой памяти
const String VALID_CARDS[] = {"CARD_A1B2", "CARD_C3D4", "CARD_E5F6"};
const int CARD_COUNT = 3;
// ── Объекты ──────────────────────────────────
Servo doorServo;
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ── Переменные состояния ─────────────────────
int failedAttempts = 0;
bool isBlocked = false;
bool doorOpen = false;
unsigned long blockStartTime = 0;
unsigned long doorOpenTime = 0;
int totalAccess = 0; // Журнал аудита (Repudiation защита)
int totalDenied = 0;
void setup() {
Serial.begin(9600);
pinMode(BTN_VALID, INPUT_PULLUP);
pinMode(BTN_INVALID, INPUT_PULLUP);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
doorServo.attach(SERVO_PIN);
doorServo.write(SERVO_CLOSE);
lcd.init();
lcd.backlight();
// Приветственный экран
lcd.setCursor(0, 0);
lcd.print(" Система доступа");
lcd.setCursor(0, 1);
lcd.print(" Инициализация ");
delay(2000);
showReady();
Serial.println("╔══════════════════════════════════╗");
Serial.println("║ СИСТЕМА КОНТРОЛЯ ДОСТУПА ║");
Serial.println("║ STRIDE защита активирована ║");
Serial.println("╚══════════════════════════════════╝");
Serial.println("[СИСТЕМА] Готова к работе");
}
void loop() {
unsigned long now = millis();
// ── Проверка блокировки (DoS защита) ────────
if (isBlocked) {
unsigned long elapsed = now - blockStartTime;
if (elapsed >= BLOCK_TIME) {
// Разблокировка
isBlocked = false;
failedAttempts = 0;
showReady();
Serial.println("[СИСТЕМА] Блокировка снята. Система готова.");
} else {
// Показать оставшееся время блокировки
int remaining = (BLOCK_TIME - elapsed) / 1000;
lcd.setCursor(0, 0);
lcd.print("[!] ЗАБЛОКИРОВАН");
lcd.setCursor(0, 1);
lcd.print("Ожидайте: ");
lcd.print(remaining);
lcd.print(" сек ");
delay(500);
return;
}
}
// ── Автоматическое закрытие двери ───────────
if (doorOpen && (now - doorOpenTime >= DOOR_OPEN_TIME)) {
closeDoor();
}
// ── Кнопка правильной карты (Spoofing симуляция) ──
if (digitalRead(BTN_VALID) == LOW) {
delay(50); // Дебаунс
if (digitalRead(BTN_VALID) == LOW) {
handleValidCard("CARD_A1B2");
while (digitalRead(BTN_VALID) == LOW); // Ждём отпускания
}
}
// ── Кнопка неправильной карты (атака Spoofing) ──
if (digitalRead(BTN_INVALID) == LOW) {
delay(50); // Дебаунс
if (digitalRead(BTN_INVALID) == LOW) {
handleInvalidCard("CARD_FAKE99");
while (digitalRead(BTN_INVALID) == LOW);
}
}
}
// ── Обработка правильной карты ───────────────
void handleValidCard(String cardUID) {
totalAccess++;
// Журнал аудита — защита от Repudiation
Serial.print("[ДОСТУП РАЗРЕШЁН] UID=");
Serial.print(cardUID);
Serial.print(" | Всего входов: ");
Serial.println(totalAccess);
failedAttempts = 0;
openDoor();
}
// ── Обработка неправильной карты ─────────────
void handleInvalidCard(String cardUID) {
failedAttempts++;
totalDenied++;
// Info Disclosure защита — не показываем детали карты в логе
Serial.print("[ОТКАЗ] Неизвестная карта | Попытка: ");
Serial.print(failedAttempts);
Serial.print("/");
Serial.print(MAX_ATTEMPTS);
Serial.print(" | Всего отказов: ");
Serial.println(totalDenied);
// Сигнал тревоги
digitalWrite(LED_RED, HIGH);
tone(BUZZER_PIN, 500, 300);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("[!] ОТКАЗ ДОСТУПА");
lcd.setCursor(0, 1);
lcd.print("Попытка: ");
lcd.print(failedAttempts);
lcd.print("/");
lcd.print(MAX_ATTEMPTS);
delay(1500);
digitalWrite(LED_RED, LOW);
// ── DoS / Brute-Force защита ─────────────────
if (failedAttempts >= MAX_ATTEMPTS) {
activateBlock();
} else {
showReady();
}
}
// ── Открыть дверь ────────────────────────────
void openDoor() {
doorOpen = true;
doorOpenTime = millis();
doorServo.write(SERVO_OPEN);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_RED, LOW);
tone(BUZZER_PIN, 1000, 200);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("[OK] ДОСТУП ОТК.");
lcd.setCursor(0, 1);
lcd.print("Добро пожаловать");
Serial.println("[ЗАМОК] Дверь открыта");
}
// ── Закрыть дверь ────────────────────────────
void closeDoor() {
doorOpen = false;
doorServo.write(SERVO_CLOSE);
digitalWrite(LED_GREEN, LOW);
Serial.println("[ЗАМОК] Дверь закрыта");
showReady();
}
// ── Активировать блокировку ──────────────────
void activateBlock() {
isBlocked = true;
blockStartTime = millis();
digitalWrite(LED_RED, HIGH);
tone(BUZZER_PIN, 300, 1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("[!] ЗАБЛОКИРОВАН");
lcd.setCursor(0, 1);
lcd.print("Тревога! DoS? ");
Serial.println("╔══════════════════════════════════╗");
Serial.println("║ [КРИТИЧНО] СИСТЕМА ЗАБЛОКИРОВАНА ║");
Serial.println("║ Обнаружена атака Brute-Force! ║");
Serial.println("╚══════════════════════════════════╝");
delay(1000);
digitalWrite(LED_RED, LOW);
}
// ── Показать экран ожидания ──────────────────
void showReady() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Система готова");
lcd.setCursor(0, 1);
lcd.print(" Прислоните карту");
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_RED, LOW);
}