Intrusion Detection System.#
A simple and basic intrusion detection system is a more advanced one known as trip wire, which monitors log files for suspicious activities. In this example, I have created a simple host-based intrusion detection system (HIDS) that monitors a sample log file. It raises an alert if it detects multiple failed login attempts from a specific IP address within a given time frame.
This system has been implemented in nine different programming languages to demonstrate the variations in the amount of code required to achieve such a simple task or program. It also serves as a good learning curve for experimentation.
- Python
- Go
- C
- C++
- C#
- Rust
- Pearl
- Ruby
- JavaScript
Python#
A simple and basic intrusion detection system using - Python
- First, create a sample log file
(sample_log.txt)with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
- A Python script for the intrusion detection system
intrusion_detection.py
import time
def read_log_file(log_file):
with open(log_file, 'r') as file:
return file.readlines()
def detect_intrusion(log_entries, max_attempts=3, time_window=60):
ip_attempts = {}
for entry in log_entries:
parts = entry.split()
if len(parts) >= 5 and parts[-2] == 'failed' and parts[-1] == 'attempt':
timestamp, _, ip_address, _ = parts[:4]
timestamp = time.mktime(time.strptime(timestamp, '%Y-%m-%d %H:%M:%S'))
if ip_address in ip_attempts:
if timestamp - ip_attempts[ip_address][-1] <= time_window:
ip_attempts[ip_address].append(timestamp)
if len(ip_attempts[ip_address]) >= max_attempts:
return True, ip_address
else:
ip_attempts[ip_address] = [timestamp]
else:
ip_attempts[ip_address] = [timestamp]
return False, None
if __name__ == "__main__":
log_file = "sample_log.txt"
log_entries = read_log_file(log_file)
intrusion_detected, suspicious_ip = detect_intrusion(log_entries)
if intrusion_detected:
print(f"Intrusion detected from {suspicious_ip}.")
else:
print("No intrusion detected.")
sample_log.txt file to check if there are three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.
Go#
A simple and basic intrusion detection system using - Go
- First, create a sample log file
sample_log.txtwith entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
- Go script for the intrusion detection system
intrusion_detection.go
package main
import (
"bufio"
"fmt"
"os"
"strings"
"time"
)
func readLogFile(logFile string) ([]string, error) {
file, err := os.Open(logFile)
if err != nil {
return nil, err
}
defer file.Close()
var logEntries []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
logEntries = append(logEntries, scanner.Text())
}
return logEntries, scanner.Err()
}
func detectIntrusion(logEntries []string, maxAttempts int, timeWindow time.Duration) (bool, string) {
ipAttempts := make(map[string][]time.Time)
for _, entry := range logEntries {
parts := strings.Fields(entry)
if len(parts) >= 5 && parts[3] == "failed" && parts[4] == "login" && parts[5] == "attempt" {
timestampStr := parts[0] + " " + parts[1]
timestamp, err := time.Parse("2006-01-02 15:04:05", timestampStr)
if err != nil {
continue
}
ipAddress := parts[2]
if attempts, ok := ipAttempts[ipAddress]; ok {
if time.Since(attempts[len(attempts)-1]) <= timeWindow {
ipAttempts[ipAddress] = append(ipAttempts[ipAddress], timestamp)
if len(ipAttempts[ipAddress]) >= maxAttempts {
return true, ipAddress
}
} else {
ipAttempts[ipAddress] = []time.Time{timestamp}
}
} else {
ipAttempts[ipAddress] = []time.Time{timestamp}
}
}
}
return false, ""
}
func main() {
logFile := "sample_log.txt"
logEntries, err := readLogFile(logFile)
if err != nil {
fmt.Println("Error reading log file:", err)
return
}
intrusionDetected, suspiciousIP := detectIntrusion(logEntries, 3, 60*time.Second)
if intrusionDetected {
fmt.Printf("Intrusion detected from %s.\n", suspiciousIP)
} else {
fmt.Println("No intrusion detected.")
}
}
intrusion_detection.go and then execute the following command in the terminal:
Run the script, and it will analyze the sample_log.txt file to check if there are three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.
C#
A simple and basic intrusion detection system using - C
- Create a sample log file
sample_log.txtwith entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
intrusion_detection.c
#include <stdio.h>
#include <string.h>
#include <time.h>
#define MAX_LOG_ENTRIES 1000
typedef struct {
char timestamp[20];
char ip_address[16];
char action[20];
} LogEntry;
int readLogFile(const char *logFile, LogEntry logEntries[MAX_LOG_ENTRIES]) {
FILE *file = fopen(logFile, "r");
if (file == NULL) {
printf("Error opening log file.\n");
return -1;
}
int numEntries = 0;
while (numEntries < MAX_LOG_ENTRIES && fscanf(file, "%19s %15s %19s", logEntries[numEntries].timestamp,
logEntries[numEntries].ip_address,
logEntries[numEntries].action) == 3) {
numEntries++;
}
fclose(file);
return numEntries;
}
int detectIntrusion(LogEntry logEntries[MAX_LOG_ENTRIES], int numEntries, int maxAttempts, int timeWindow) {
struct tm timestamp1, timestamp2;
for (int i = 0; i < numEntries; i++) {
if (strcmp(logEntries[i].action, "failed") == 0 &&
strcmp(logEntries[i].ip_address, "login") == 0 &&
strcmp(logEntries[i].action, "attempt") == 0) {
strptime(logEntries[i].timestamp, "%Y-%m-%d %H:%M:%S", ×tamp1);
time_t t1 = mktime(×tamp1);
int attempts = 1;
for (int j = i + 1; j < numEntries; j++) {
if (strcmp(logEntries[j].ip_address, logEntries[i].ip_address) == 0) {
strptime(logEntries[j].timestamp, "%Y-%m-%d %H:%M:%S", ×tamp2);
time_t t2 = mktime(×tamp2);
if (t2 - t1 <= timeWindow) {
attempts++;
if (attempts >= maxAttempts) {
return 1; // Intrusion detected
}
} else {
break;
}
}
}
}
}
return 0; // No intrusion detected
}
int main() {
const char *logFile = "sample_log.txt";
LogEntry logEntries[MAX_LOG_ENTRIES];
int numEntries = readLogFile(logFile, logEntries);
if (numEntries == -1) {
return 1;
}
int intrusionDetected = detectIntrusion(logEntries, numEntries, 3, 60);
if (intrusionDetected) {
printf("Intrusion detected.\n");
} else {
printf("No intrusion detected.\n");
}
return 0;
}
- To compile and run the C program, make sure you have a C compiler installed (e.g., GCC). Save the program in a file named
intrusion_detection.c,and then execute the following command in the terminal:
The C program will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert stating "Intrusion detected."
C++#
A simple and basic intrusion detection system using - C++
- Create a sample log file
sample_log.txtwith entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
- Now, let's create the C++ program for the intrusion detection system (main.cpp)
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <ctime>
#include <chrono>
struct LogEntry {
std::string timestamp;
std::string ip_address;
std::string action;
};
std::vector<LogEntry> readLogFile(const std::string& logFile) {
std::ifstream file(logFile);
std::vector<LogEntry> logEntries;
std::string line;
while (std::getline(file, line)) {
std::istringstream iss(line);
LogEntry entry;
iss >> entry.timestamp >> entry.ip_address >> entry.action;
logEntries.push_back(entry);
}
return logEntries;
}
bool detectIntrusion(const std::vector<LogEntry>& logEntries, int maxAttempts, int timeWindow) {
std::map<std::string, std::vector<time_t>> ipAttempts;
for (const auto& entry : logEntries) {
if (entry.action == "failed" && entry.ip_address == "login" && entry.action == "attempt") {
struct tm timeinfo;
strptime(entry.timestamp.c_str(), "%Y-%m-%d %H:%M:%S", &timeinfo);
time_t timestamp = mktime(&timeinfo);
if (ipAttempts.find(entry.ip_address) != ipAttempts.end()) {
auto& attempts = ipAttempts[entry.ip_address];
if (difftime(timestamp, attempts.back()) <= timeWindow) {
attempts.push_back(timestamp);
if (attempts.size() >= maxAttempts) {
return true; // Intrusion detected
}
} else {
attempts = { timestamp };
}
} else {
ipAttempts[entry.ip_address] = { timestamp };
}
}
}
return false; // No intrusion detected
}
int main() {
const std::string logFile = "sample_log.txt";
std::vector<LogEntry> logEntries = readLogFile(logFile);
bool intrusionDetected = detectIntrusion(logEntries, 3, 60);
if (intrusionDetected) {
std::cout << "Intrusion detected." << std::endl;
} else {
std::cout << "No intrusion detected." << std::endl;
}
return 0;
}
- To compile and run the C++ program, save the C++ code in a file named main.cpp, and then execute the following commands in the terminal:
The C++ program will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert stating "Intrusion detected."
C##
A simple and basic intrusion detection system using - C#
- First, create a sample log file
(sample_log.txt)with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
- Now, let's create the C# program for the intrusion detection system (Program.cs):
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
namespace IntrusionDetection
{
class Program
{
static List<string> ReadLogFile(string logFile)
{
return new List<string>(File.ReadAllLines(logFile));
}
static (bool, string) DetectIntrusion(List<string> logEntries, int maxAttempts, int timeWindow)
{
var ipAttempts = new Dictionary<string, List<DateTime>>();
foreach (var entry in logEntries)
{
var parts = entry.Split(' ');
if (parts.Length >= 6 && parts[3] == "failed" && parts[4] == "login" && parts[5] == "attempt")
{
var timestampStr = parts[0] + " " + parts[1];
var timestamp = DateTime.ParseExact(timestampStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
var ipAddress = parts[2];
if (ipAttempts.TryGetValue(ipAddress, out var attempts))
{
if (DateTime.Now.Subtract(attempts[attempts.Count - 1]).TotalSeconds <= timeWindow)
{
attempts.Add(timestamp);
if (attempts.Count >= maxAttempts)
{
return (true, ipAddress); // Intrusion detected
}
}
else
{
ipAttempts[ipAddress] = new List<DateTime> { timestamp };
}
}
else
{
ipAttempts[ipAddress] = new List<DateTime> { timestamp };
}
}
}
return (false, ""); // No intrusion detected
}
static void Main(string[] args)
{
var logFile = "sample_log.txt";
var logEntries = ReadLogFile(logFile);
var (intrusionDetected, suspiciousIp) = DetectIntrusion(logEntries, 3, 60);
if (intrusionDetected)
{
Console.WriteLine($"Intrusion detected from {suspiciousIp}.");
}
else
{
Console.WriteLine("No intrusion detected.");
}
}
}
}
- To run the C# program, you'll need to have the .NET SDK installed. Save the C# code in a file named Program.cs, and then execute the following command in the terminal:
The C# program will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.
Rust#
A simple and basic intrusion detection system using - Rust
- Create a sample log file
sample_log.txtwith entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
- Now, let's create the Rust program for the intrusion detection system (
main.rs):
use std::fs::File;
use std::io::{self, BufRead};
use std::time::{SystemTime, Duration};
use chrono::{NaiveDateTime, Timelike};
fn read_log_file(log_file: &str) -> io::Result<Vec<String>> {
let file = File::open(log_file)?;
let reader = io::BufReader::new(file);
reader.lines().collect()
}
fn detect_intrusion(log_entries: Vec<String>, max_attempts: usize, time_window: Duration) -> (bool, String) {
let mut ip_attempts: std::collections::HashMap<String, Vec<SystemTime>> = std::collections::HashMap::new();
for entry in log_entries {
let parts: Vec<&str> = entry.split_whitespace().collect();
if parts.len() >= 6 && parts[3] == "failed" && parts[4] == "login" && parts[5] == "attempt" {
let timestamp_str = parts[0].to_owned() + " " + parts[1];
let timestamp = NaiveDateTime::parse_from_str(×tamp_str, "%Y-%m-%d %H:%M:%S").unwrap();
let timestamp = SystemTime::from(timestamp);
let ip_address = parts[2].to_owned();
if let Some(attempts) = ip_attempts.get_mut(&ip_address) {
if let Some(last_attempt) = attempts.last() {
if timestamp.duration_since(*last_attempt).unwrap() <= time_window {
attempts.push(timestamp);
if attempts.len() >= max_attempts {
return (true, ip_address); // Intrusion detected
}
} else {
*attempts = vec![timestamp];
}
}
} else {
ip_attempts.insert(ip_address, vec![timestamp]);
}
}
}
(false, String::new()) // No intrusion detected
}
fn main() {
let log_file = "sample_log.txt";
let log_entries = read_log_file(log_file).expect("Error reading log file.");
let (intrusion_detected, suspicious_ip) = detect_intrusion(log_entries, 3, Duration::from_secs(60));
if intrusion_detected {
println!("Intrusion detected from {}.", suspicious_ip);
} else {
println!("No intrusion detected.");
}
}
- To run the Rust program, you'll need to have the Rust programming language installed. Save the Rust code in a file named main.rs, and then execute the following command in the terminal:
The Rust program will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.
Perl#
A simple and basic intrusion detection system using - Perl
- Create a sample log file
sample_log.txtwith entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
- Create the Perl script for the intrusion detection system
intrusion_detection.pl
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
use Time::Seconds;
sub read_log_file {
my ($log_file) = @_;
open(my $fh, '<', $log_file) or die "Error opening log file: $!";
my @log_entries = <$fh>;
close($fh);
return @log_entries;
}
sub detect_intrusion {
my ($log_entries_ref, $max_attempts, $time_window) = @_;
my %ip_attempts;
foreach my $entry (@$log_entries_ref) {
my @parts = split(' ', $entry);
next unless @parts >= 6 && $parts[3] eq 'failed' && $parts[4] eq 'login' && $parts[5] eq 'attempt';
my $timestamp_str = $parts[0] . ' ' . $parts[1];
my $timestamp = Time::Piece->strptime($timestamp_str, '%Y-%m-%d %H:%M:%S');
my $ip_address = $parts[2];
if (exists $ip_attempts{$ip_address}) {
if ($timestamp - $ip_attempts{$ip_address}[-1] <= $time_window) {
push @{$ip_attempts{$ip_address}}, $timestamp;
if (@{$ip_attempts{$ip_address}} >= $max_attempts) {
return 1, $ip_address; # Intrusion detected
}
} else {
$ip_attempts{$ip_address} = [$timestamp];
}
} else {
$ip_attempts{$ip_address} = [$timestamp];
}
}
return 0, ''; # No intrusion detected
}
sub main {
my $log_file = 'sample_log.txt';
my @log_entries = read_log_file($log_file);
my ($intrusion_detected, $suspicious_ip) = detect_intrusion(\@log_entries, 3, 60);
if ($intrusion_detected) {
print "Intrusion detected from $suspicious_ip.\n";
} else {
print "No intrusion detected.\n";
}
}
main();
- To run the Perl script, make sure you have Perl installed on your system. Save the script in a file named
intrusion_detection.pl,and then execute the following command in the terminal:
The Perl script will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.
Ruby#
A simple and basic intrusion detection system using - Ruby
- First, create a sample log file
(sample_log.txt)with entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
- Create the Ruby script for the intrusion detection system
intrusion_detection.rb
require 'time'
def read_log_file(log_file)
File.readlines(log_file)
end
def detect_intrusion(log_entries, max_attempts, time_window)
ip_attempts = {}
log_entries.each do |entry|
parts = entry.split
next unless parts.length >= 6 && parts[3] == 'failed' && parts[4] == 'login' && parts[5] == 'attempt'
timestamp_str = parts[0] + ' ' + parts[1]
timestamp = Time.parse(timestamp_str)
ip_address = parts[2]
if ip_attempts.key?(ip_address)
if timestamp - ip_attempts[ip_address].last <= time_window
ip_attempts[ip_address] << timestamp
if ip_attempts[ip_address].length >= max_attempts
return true, ip_address # Intrusion detected
end
else
ip_attempts[ip_address] = [timestamp]
end
else
ip_attempts[ip_address] = [timestamp]
end
end
return false, '' # No intrusion detected
end
def main
log_file = 'sample_log.txt'
log_entries = read_log_file(log_file)
intrusion_detected, suspicious_ip = detect_intrusion(log_entries, 3, 60)
if intrusion_detected
puts "Intrusion detected from #{suspicious_ip}."
else
puts "No intrusion detected."
end
end
main
- To run the Ruby script, make sure you have Ruby installed on your system. Save the script in a file named
intrusion_detection.rb,and then execute the following command in the terminal:
The Ruby script will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.
JavaScript#
A simple and basic intrusion detection system using - JavaScript
- Create a sample log file
sample_log.txtwith entries like the following:
2023-07-19 12:34:56 192.168.0.101 failed login attempt
2023-07-19 12:35:02 192.168.0.101 failed login attempt
2023-07-19 12:36:45 192.168.0.102 failed login attempt
2023-07-19 12:36:50 192.168.0.101 failed login attempt
2023-07-19 12:37:10 192.168.0.101 failed login attempt
- Create the JavaScript code for the intrusion detection system:
const fs = require('fs');
const moment = require('moment');
function readLogFile(logFile) {
return fs.readFileSync(logFile, 'utf8').split('\n');
}
function detectIntrusion(logEntries, maxAttempts, timeWindow) {
const ipAttempts = {};
logEntries.forEach(entry => {
const parts = entry.split(' ');
if (parts.length >= 6 && parts[3] === 'failed' && parts[4] === 'login' && parts[5] === 'attempt') {
const timestampStr = parts[0] + ' ' + parts[1];
const timestamp = moment(timestampStr, 'YYYY-MM-DD HH:mm:ss');
const ipAddress = parts[2];
if (ipAttempts[ipAddress]) {
if (moment().diff(ipAttempts[ipAddress][ipAttempts[ipAddress].length - 1], 'seconds') <= timeWindow) {
ipAttempts[ipAddress].push(timestamp);
if (ipAttempts[ipAddress].length >= maxAttempts) {
return { intrusionDetected: true, suspiciousIp: ipAddress };
}
} else {
ipAttempts[ipAddress] = [timestamp];
}
} else {
ipAttempts[ipAddress] = [timestamp];
}
}
});
return { intrusionDetected: false, suspiciousIp: '' };
}
function main() {
const logFile = 'sample_log.txt';
const logEntries = readLogFile(logFile);
const { intrusionDetected, suspiciousIp } = detectIntrusion(logEntries, 3, 60);
if (intrusionDetected) {
console.log(`Intrusion detected from ${suspiciousIp}.`);
} else {
console.log('No intrusion detected.');
}
}
main();
- Before running the JavaScript code, you'll need to install the
'moment'library, which is used for handling dates and times. You can install it vianpm:
- Then, save the JavaScript code in a file named
intrusion_detection.js,and execute the following command in the terminal:
The JavaScript code will read the sample_log.txt file and check for three or more failed login attempts from the same IP address within a 60-second window. If such an intrusion is detected, it will display an alert with the suspicious IP address.
Note
Remember that this is a basic example, and a real-world intrusion detection system requires more sophisticated techniques and continuous monitoring of various system logs, network traffic, and user behaviors. Additionally, a production-grade system would have to consider factors like scalability, real-time monitoring, threat intelligence feeds, and more robust anomaly detection methods.
Developed and Documentation By: Raymond C. TURNER
Last Updated: Monday 28th August 2023 @ 01:03 BST