Как обнаружить сканирование портов по логу сетевого трафика?
Я студент, разрабатываю на C++ сетевой сниффер для мониторинга трафика и обнаружения подозрительной активности. Для анализа сканирования портов я реализовал следующий алгоритм:
#pragma once
#include "IAnalyzer.hpp"
#include "PacketInfo.h"
#include <string>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <vector>
struct ScanResult {
std::string srcIp;
std::string dstIp;
int uniqueDstPorts;
bool suspicious;
};
class PortScanningAnalyzer : public IAnalyzer
{
public:
nlohmann::json analyze(const std::vector<PacketInfo>& packets) override;
private:
std::vector<ScanResult> detectPortScanning(const std::vector<PacketInfo>& packets, int threshold);
};
nlohmann::json PortScanningAnalyzer::analyze(const std::vector<PacketInfo>& packets) {
nlohmann::json result;
result["rule"] = "portScan";
const int threshold = 100;
std::vector<ScanResult> scanResults = detectPortScanning(packets, threshold);
nlohmann::json counts = nlohmann::json::object();
std::set<std::string> suspiciousIps;
for (const auto& r : scanResults) {
counts[r.srcIp] = counts.contains(r.srcIp) ? counts[r.srcIp].get<int>() + r.uniqueDstPorts : r.uniqueDstPorts;
if (r.suspicious) {
suspiciousIps.insert(r.srcIp);
}
}
result["dst_ports_count"] = counts;
result["suspicious_ips"] = suspiciousIps;
result["threshold"] = threshold;
return result;
}
std::vector<ScanResult> PortScanningAnalyzer::detectPortScanning(const std::vector<PacketInfo>& packets, int threshold) {
std::unordered_map<std::string, std::unordered_map<std::string, std::set<int>>> portsMap;
for (const auto& p : packets) {
if (p.protocol == "TCP" || p.protocol == "UDP") {
portsMap[p.srcIp][p.dstIp].insert(p.dstPort);
}
}
std::vector<ScanResult> results;
for (const auto& [srcIp, dstMap] : portsMap) {
for (const auto& [dstIp, portSet] : dstMap) {
ScanResult r;
r.srcIp = srcIp;
r.dstIp = dstIp;
r.uniqueDstPorts = static_cast<int>(portSet.size());
r.suspicious = r.uniqueDstPorts > threshold;
results.push_back(r);
}
}
return results;
}
Проблема: при тестировании алгоритма не все попытки сканирования портов обнаруживаются. Например, при сканировании с мобильного устройства уникальные порты не превышали 4-10, а при сканировании с другой машины счетчик остановился на ~100 портах вместо реальных 1000 запросов.
Вопросы:
- Какие есть замечания по текущему алгоритму обнаружения сканирования портов?
- Какие еще признаки указывают на сканирование портов, кроме количества уникальных портов назначения? (например, широковещательные пакеты)
P.S. Я не специалист по кибербезопасности, поэтому прошу объяснять доступно, без излишнего сленга.
Основная проблема вашего алгоритма заключается в его чрезмерной простоте - он учитывает только количество уникальных портов назначения, что недостаточно для обнаружения различных типов сканирования портов. Давайте разберем это подробнее.
Содержание
- Проблемы текущего алгоритма
- Дополнительные признаки сканирования портов
- Улучшенный подход к обнаружению
- Практические рекомендации по реализации
- Заключение
Проблемы текущего алгоритма
Ваш текущий алгоритм имеет несколько существенных недостатков:
1. Игнорирование различных типов сканирования
- Вы обрабатываете все TCP/UDP пакеты одинаково, хотя существуют разные виды сканирования с разной степенью заметности
- Например, SYN-сканирование отправляет только SYN пакеты и не устанавливает полное соединение, что делает его менее заметным
- FIN-, XMAS- и NULL-сканирование используют необычные комбинации флагов, которые могут обходить базовые системы обнаружения
2. Отсутствие временного анализа
- Ваш алгоритм не учитывает, когда происходят запросы - быстро или медленно
- Медленные сканирования (slow scans) могут длиться неделями, как упоминается в исследованиях
- При тестировании с мобильного устройства количество портов было небольшим (4-10), но они могли быть запрошены в течение длительного времени
3. Недостаточный учет характеристик трафика
- Как показывают исследования, сканеры портов вызывают множество небольших потоков данных, в то время как нормальный трафик имеет больший размер и большую изменчивость
- Ваш алгоритм не анализирует размер пакетов или последовательность запросов
4. Простой пороговый подход
- Использование единого порога (100 портов) слишком грубое
- Нормальный трафик к разным хостам может legitimately запрашивать множество портов
- Отсутствует адаптация к нормальному поведению сети
Дополнительные признаки сканирования портов
Помимо количества уникальных портов, на сканирование указывают следующие признаки:
1. Временные паттерны
- Ритмичность запросов: Постоянные интервалы между пакетами к разным портам
- Высокая частота: Много запросов в краткий промежуток времени
- Ненормальные временные окна: Активность в нерабочее время или необычные временные паттерны
2. Комбинации флагов TCP
- FIN-сканирование: Пакеты с установленным только FIN флагом
- XMAS-сканирование: Пакеты с установленными флагами FIN, PSH и URG
- NULL-сканирование: Пакеты без установленных флагов
3. Поведение соединений
- Незавершенные соединения: Много SYN-пакетов без ответов или без установления полного соединения
- Таймауты: Много запросов, заканчивающихся таймаутом
- Повторные попытки: Много повторных запросов к одним и тем же портам
4. Статистические аномалии
- Последовательный vs случайный доступ: Сканирование часто идет последовательно (1,2,3…), а не случайно
- Шаблоны доступа: Неправильное распределение запросов по портам (например, только порты выше 1024)
- Отклонение от нормы: Поведение, отличающееся от типичного для данного источника
5. Протокольные особенности
- ICMP-сканирование: Много ping-запросов (ICMP echo requests) для обнаружения хостов
- ARP-сканирование: В локальных сетях - много ARP-запросов
- DNS-запросы: Необычные DNS-запросы для обнаружения сервисов
Улучшенный подход к обнаружению
Исследования показывают, что эффективное обнаружение сканирования портов должно использовать несколько методов одновременно:
Методы на основе анализа потоков данных
- Анализ размера потоков: Порт-сканеры создают много небольших потоков, в то время как нормальный трафик имеет большие и более изменчивые размеры потоков [источник]
- Последовательное тестирование гипотез: Позволяет обнаруживать сканирование даже при небольшом количестве портов, если паттерны последовательны
Временное окно анализа
- Скользящие окна: Анализ трафика в окнах определенного размера (например, 60 секунд)
- Адаптивные пороги: Пороги, зависящие от нормального поведения сети
Комбинированные индикаторы
- Весовая система: Разные признаки дают разные баллы (количество портов, скорость, шаблоны)
- Машина состояний: Отслеживание состояния соединений и паттернов поведения
Практические рекомендации по реализации
1. Добавьте анализ TCP флагов
struct PacketFlags {
bool syn;
bool ack;
bool fin;
bool rst;
bool psh;
bool urg;
};
// В вашей структуре PacketInfo
PacketInfo {
// ... существующие поля
PacketFlags flags;
int packetSize;
timestamp_t timestamp;
};
2. Реализуйте временной анализ
struct TimeWindow {
std::vector<PacketInfo> packets;
timestamp_t startTime;
timestamp_t endTime;
double getPacketRate() const {
double duration = endTime - startTime;
return packets.size() / duration;
}
double getAveragePacketSize() const {
double totalSize = 0;
for (const auto& p : packets) {
totalSize += p.packetSize;
}
return totalSize / packets.size();
}
};
3. Добавьте детектор шаблонов портов
class PortPatternDetector {
public:
enum class PatternType {
SEQUENTIAL,
RANDOM,
COMMON_PORTS,
HIGH_RANGE
};
PatternType detectPattern(const std::set<int>& ports) {
// Анализ последовательности портов
// Поиск паттернов в диапазонах
// Обнаружение популярных портов
}
};
4. Реализуйте систему балльной оценки
class PortScanScorer {
public:
double calculateSuspicionScore(const std::vector<PacketInfo>& packets) {
double score = 0.0;
// Базовые признаки
score += countUniquePorts(packets) * 0.3;
score += getPacketRate(packets) * 0.2;
score += getFlagAnomalies(packets) * 0.4;
score += getTimePatternScore(packets) * 0.1;
return score;
}
private:
// Вспомогательные методы расчета признаков
};
5. Улучшите основной алгоритм
std::vector<ScanResult> PortScanningAnalyzer::detectPortScanning(
const std::vector<PacketInfo>& packets, int threshold) {
// Группировка по временным окнам
std::vector<TimeWindow> timeWindows = groupIntoTimeWindows(packets, 60); // 60 секунд
std::vector<ScanResult> results;
for (const auto& window : timeWindows) {
for (const auto& srcIp : getUniqueSources(window)) {
auto srcPackets = filterBySource(window, srcIp);
// Расчет различных признаков
int uniquePorts = countUniquePorts(srcPackets);
double packetRate = calculatePacketRate(srcPackets);
double avgPacketSize = calculateAveragePacketSize(srcPackets);
PatternType pattern = detectPortPattern(srcPackets);
// Комбинированная оценка
double suspicionScore = calculateSuspicionScore({
uniquePorts, packetRate, avgPacketSize, pattern
});
if (suspicionScore > SUSPICION_THRESHOLD) {
results.push_back(createScanResult(srcIp, suspicionScore));
}
}
}
return results;
}
Заключение
Ваш текущий алгоритм является хорошей отправной точкой, но для эффективного обнаружения сканирования портов необходимо учитывать несколько факторов:
- Множественные индикаторы: Используйте комбинацию количества портов, временных паттернов, характеристик пакетов и поведенческих шаблонов
- Адаптивные пороги: Вместо фиксированного порога используйте динамические пороги, основанные на нормальном поведении сети
- Временной анализ: Добавьте анализ трафика во временных окнах для обнаружения медленных сканирований
- Разнообразие типов сканирования: Учитывайте различные методы сканирования (SYN, FIN, XMAS и т.д.)
Начните с добавления анализа TCP флагов и временных паттернов, затем постепенно усложняйте алгоритм, добавляя дополнительные признаки. Такой подход позволит обнаруживать как быстрые, так и медленные сканирования, а также различные их типы.
Источники
- Detection of slow port scans in flow-based network traffic - PMC
- PD-CPS: A practical scheme for detecting covert port scans in high-speed networks - ScienceDirect
- What is a Port Scan + How to Detect It - Vectra
- Detecting and Understanding Online Port Scans - ExtraHop
- The Ultimate Port Scanning Guide - SecOps Solution