174 lines
7.4 KiB
JavaScript
174 lines
7.4 KiB
JavaScript
|
// Lets use some libs to help us out.
|
||
|
const fs = require('fs')
|
||
|
Tail = require('tail').Tail;
|
||
|
|
||
|
sshTail = new Tail("/var/log/auth.log");
|
||
|
wpTail = new Tail("/var/log/apache2/access.log");
|
||
|
const cmd = require('cmd-promise')
|
||
|
|
||
|
// Setting up our main storage logic - for now this program does not use a database system.
|
||
|
let serverStatusCount = 0;
|
||
|
let attackData = []
|
||
|
let blockedIPs = []
|
||
|
let ipToBlock
|
||
|
|
||
|
console.log("Welcome to the security notification system secuNotify by Discord-Linux!");
|
||
|
console.log("We currently will notify you about login events, such as failed logins and successful logins.");
|
||
|
|
||
|
// Setting up our notification function - This allows us to direct message our user.
|
||
|
function notify(message) {
|
||
|
const { spawn } = require('child_process');
|
||
|
const notif = spawn('notif', [message]);
|
||
|
|
||
|
notif.stdout.on('data', (data) => {
|
||
|
console.log(`stdout: ${data}`);
|
||
|
});
|
||
|
|
||
|
notif.stderr.on('data', (data) => {
|
||
|
console.error(`stderr: ${data}`);
|
||
|
});
|
||
|
|
||
|
notif.on('close', (code) => {
|
||
|
console.log(`Code: ${code} - Continuing to monitor`);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function listenAuthLog(logLocation) {
|
||
|
sshTail.on("line", function (info) {
|
||
|
let infoString = info.toString();
|
||
|
|
||
|
if (infoString.includes("Failed password for root")) {
|
||
|
console.log(info);
|
||
|
notify("secuNotify Service Alert: \n" + info);
|
||
|
}
|
||
|
|
||
|
if (infoString.includes("Accepted password for")) {
|
||
|
console.log(info);
|
||
|
notify("secuNotify Service Alert: \n" + info + "This does mean that someone (Maybe you) has logged in successfully!");
|
||
|
}
|
||
|
if (infoString.includes("Invalid user")) {
|
||
|
console.log(info);
|
||
|
notify("secuNotify Service Alert: \n" + info + "This means that someone (Maybe you) has tried to login with an invalid username!");
|
||
|
}
|
||
|
})
|
||
|
|
||
|
;
|
||
|
}
|
||
|
|
||
|
function listenWPLog(logLocation) {
|
||
|
// Check to see if we are a wordpress user, if so, activate the wordpress notification service
|
||
|
const wpLog = '/var/www/html/wp-config.php'
|
||
|
try {
|
||
|
if (fs.existsSync(wpLog)) {
|
||
|
console.log("We are a wordpress user, activating wordpress notification service");
|
||
|
|
||
|
// Tail Logs section, if we have a lot, it will have a listeniner below.
|
||
|
wpTail.on("line", function (info) {
|
||
|
|
||
|
// Convert Data to String
|
||
|
let requestInfo = info.toString()
|
||
|
// FIND IP Address from this request
|
||
|
var ipRegEx = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/; // RegEx IPAddress Format
|
||
|
var ipRegExMatched = requestInfo.match(ipRegEx); // Set up our match
|
||
|
let remoteIP = ipRegExMatched[0] // Set our var
|
||
|
|
||
|
// // Grab the whitelist
|
||
|
// let whitelistData = process.env.WHITELIST
|
||
|
// let whitelist = whitelistData.split(",")
|
||
|
|
||
|
// // If an IP is found to be in the whitelist, return as to do nothing.
|
||
|
// for (const [key, value] of Object.entries(whitelist)) {
|
||
|
// if (value === remoteIP) return
|
||
|
// }
|
||
|
|
||
|
// Filtering out any server-status requests - These are annoying.
|
||
|
if (requestInfo.includes("server-status")) {
|
||
|
// Add to the server status count so we may keep track of these requests.
|
||
|
serverStatusCount++
|
||
|
// Lets return the data as no not proceed with any further code, as it is not needed.
|
||
|
// We return to stdout here to update the cli without adding a new line line a clock
|
||
|
return process.stdout.write("Server Status Count: " + serverStatusCount + "\r");
|
||
|
}
|
||
|
|
||
|
// If request contans wp-login lets process its request
|
||
|
if (requestInfo.includes("wp-login.php")) {
|
||
|
// Lets start the process of logging attack attempts to determine request intent.
|
||
|
// Over the threshhold here will automatically CSF D the IP Address.
|
||
|
// In this simple version, we will just log each IP Address as they come in within an array
|
||
|
// We will then roll and count this array after each detection to determine the IPs intent.
|
||
|
console.log("---------\nWP LOGIN REQUEST DETECTED!\n---------")
|
||
|
console.log(info + "\n----------");
|
||
|
attackData.push(remoteIP)
|
||
|
|
||
|
// Lets count the attack data per IP Address to ensure its logged properly.
|
||
|
var counts = {};
|
||
|
|
||
|
// For each IP Address recorded into the main attackData array, count them and see outmany bad requests they have made.
|
||
|
attackData.forEach(function (x) {
|
||
|
// Add a point for each entry
|
||
|
counts[x] = (counts[x] || 0) + 1;
|
||
|
//
|
||
|
for ([key, value] of Object.entries(counts)) {
|
||
|
// If the count has hit the blockON Count we start the blocking process
|
||
|
|
||
|
if (counts[x] == 5) {
|
||
|
// Preserve the key for later blocklist addition
|
||
|
ipToBlock = key
|
||
|
|
||
|
// Check the already blocked IPs - If the remoteIP is in the list do nothing
|
||
|
if (blockedIPs.includes(key)) {
|
||
|
return
|
||
|
|
||
|
} else {
|
||
|
// The remoteIP is not listed, lets add it.
|
||
|
blockedIPs.push(ipToBlock)
|
||
|
// Let the log know we are blocking the IP
|
||
|
console.log("Starting to block bad IP")
|
||
|
// Run the block, wait for the promise - Requests are still going on
|
||
|
cmd(`/var/tools/firewallctl 123.123.123.123 ` + key + " WP-Login Brute Force Blocked Via secuNotify").then(out => {
|
||
|
notify("secuNotify Service Alert: \n " + key + " has been blocked for 5 bad wordpress login attempts!");
|
||
|
|
||
|
// The block has finished - remoteIP no longer has access
|
||
|
}).catch(err => {
|
||
|
// IF we see an error, give its output
|
||
|
console.log('CSF Error: ', err)
|
||
|
}).then(out2 => {
|
||
|
// Set IPBLOCK to null for a reset and start scanning for new attacks
|
||
|
ipToBlock = null;
|
||
|
console.log("Attack Stopped, Looking for new attacks....")
|
||
|
|
||
|
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
});
|
||
|
|
||
|
// Live view of the counts
|
||
|
console.log(counts)
|
||
|
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
} catch (err) {
|
||
|
console.log(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
listenAuthLog("/var/log/auth.log")
|
||
|
|
||
|
const fs = require('fs')
|
||
|
|
||
|
const path = '/var/log/apache2/access.log'
|
||
|
|
||
|
try {
|
||
|
if (fs.existsSync(path)) {
|
||
|
listenWPLog("/var/log/apache2/access.log")
|
||
|
}
|
||
|
} catch(err) {
|
||
|
console.log("I could not find any WP instaltion within the /var/www/html directory\nNOT loading the WP Log listener")
|
||
|
}
|
||
|
|