diff --git a/Log Manager/Database Schema/shellm_sessions_answers.sql b/Log Manager/Database Schema/shellm_sessions_answers.sql new file mode 100644 index 0000000..d69846b --- /dev/null +++ b/Log Manager/Database Schema/shellm_sessions_answers.sql @@ -0,0 +1,44 @@ +-- MySQL dump 10.13 Distrib 8.0.40, for Win64 (x86_64) +-- +-- Host: localhost Database: shellm_sessions +-- ------------------------------------------------------ +-- Server version 8.0.40 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `answers` +-- + +DROP TABLE IF EXISTS `answers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `answers` ( + `answer_id` int NOT NULL AUTO_INCREMENT, + `command_id` int DEFAULT NULL, + `answer` text NOT NULL, + PRIMARY KEY (`answer_id`), + KEY `command_id` (`command_id`), + CONSTRAINT `answers_ibfk_1` FOREIGN KEY (`command_id`) REFERENCES `commands` (`command_id`) +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2024-12-06 9:42:51 diff --git a/Log Manager/Database Schema/shellm_sessions_attacker_session.sql b/Log Manager/Database Schema/shellm_sessions_attacker_session.sql new file mode 100644 index 0000000..b9b6746 --- /dev/null +++ b/Log Manager/Database Schema/shellm_sessions_attacker_session.sql @@ -0,0 +1,30 @@ +-- MySQL dump 10.13 Distrib 8.0.40, for Win64 (x86_64) +-- +-- Host: localhost Database: shellm_sessions +-- ------------------------------------------------------ +-- Server version 8.0.40 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `attacker_session` +-- + +DROP TABLE IF EXISTS `attacker_session`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `attacker_session` ( + `attacker_session_id` int NOT NULL AUTO_INCREMENT, + `src_ip` varchar(45) NOT NULL, + PRIMARY KEY (`attacker_session_id`) +) ENGINE=InnoDB AUTO_INCREMENT=224 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; diff --git a/Log Manager/Database Schema/shellm_sessions_commands.sql b/Log Manager/Database Schema/shellm_sessions_commands.sql new file mode 100644 index 0000000..e1b698a --- /dev/null +++ b/Log Manager/Database Schema/shellm_sessions_commands.sql @@ -0,0 +1,44 @@ +-- MySQL dump 10.13 Distrib 8.0.40, for Win64 (x86_64) +-- +-- Host: localhost Database: shellm_sessions +-- ------------------------------------------------------ +-- Server version 8.0.40 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `commands` +-- + +DROP TABLE IF EXISTS `commands`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `commands` ( + `command_id` int NOT NULL AUTO_INCREMENT, + `shellm_session_id` int DEFAULT NULL, + `command` text NOT NULL, + PRIMARY KEY (`command_id`), + KEY `shellm_session_id` (`shellm_session_id`), + CONSTRAINT `commands_ibfk_1` FOREIGN KEY (`shellm_session_id`) REFERENCES `shellm_session` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=153 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2024-12-06 9:42:50 diff --git a/Log Manager/Database Schema/shellm_sessions_shellm_session.sql b/Log Manager/Database Schema/shellm_sessions_shellm_session.sql new file mode 100644 index 0000000..c2b4ea0 --- /dev/null +++ b/Log Manager/Database Schema/shellm_sessions_shellm_session.sql @@ -0,0 +1,49 @@ +-- MySQL dump 10.13 Distrib 8.0.40, for Win64 (x86_64) +-- +-- Host: localhost Database: shellm_sessions +-- ------------------------------------------------------ +-- Server version 8.0.40 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `shellm_session` +-- + +DROP TABLE IF EXISTS `shellm_session`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `shellm_session` ( + `id` int NOT NULL AUTO_INCREMENT, + `ssh_session_id` int DEFAULT NULL, + `model` varchar(255) NOT NULL, + `start_time` datetime NOT NULL, + `end_time` datetime NOT NULL, + `attacker_id` int DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `ssh_session_id` (`ssh_session_id`), + KEY `fk_attacker` (`attacker_id`), + CONSTRAINT `fk_attacker` FOREIGN KEY (`attacker_id`) REFERENCES `attacker_session` (`attacker_session_id`), + CONSTRAINT `shellm_session_ibfk_1` FOREIGN KEY (`ssh_session_id`) REFERENCES `ssh_session` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2024-12-06 9:42:51 diff --git a/Log Manager/Database Schema/shellm_sessions_ssh_session.sql b/Log Manager/Database Schema/shellm_sessions_ssh_session.sql new file mode 100644 index 0000000..fb6063f --- /dev/null +++ b/Log Manager/Database Schema/shellm_sessions_ssh_session.sql @@ -0,0 +1,46 @@ +-- MySQL dump 10.13 Distrib 8.0.40, for Win64 (x86_64) +-- +-- Host: localhost Database: shellm_sessions +-- ------------------------------------------------------ +-- Server version 8.0.40 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `ssh_session` +-- + +DROP TABLE IF EXISTS `ssh_session`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `ssh_session` ( + `id` int NOT NULL AUTO_INCREMENT, + `username` varchar(255) NOT NULL, + `time_date` datetime NOT NULL, + `src_ip` varchar(45) NOT NULL, + `dst_ip` varchar(45) NOT NULL, + `src_port` int DEFAULT NULL, + `dst_port` int DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=227 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2024-12-06 9:42:50 diff --git a/Log Manager/dashboard.html b/Log Manager/dashboard.html new file mode 100644 index 0000000..52f04a0 --- /dev/null +++ b/Log Manager/dashboard.html @@ -0,0 +1,104 @@ + + + + + + Log Manager Dashboard + + + +

Log Manager Dashboard

+ +
+
+ + +
+ + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Log Manager/db_credentials.env b/Log Manager/db_credentials.env new file mode 100644 index 0000000..ac1a475 --- /dev/null +++ b/Log Manager/db_credentials.env @@ -0,0 +1,3 @@ +MYSQL_USER= +MYSQL_PASSWORD= +MYSQL_HOST= diff --git a/Log Manager/log_manager.py b/Log Manager/log_manager.py new file mode 100644 index 0000000..b2c0eed --- /dev/null +++ b/Log Manager/log_manager.py @@ -0,0 +1,112 @@ +from flask import Flask, jsonify, render_template +from flask_cors import CORS # Import Flask-CORS +import ssh_module +import mysql.connector +from datetime import datetime, timedelta +from dotenv import load_dotenv +import os + +# Load environment variables from .env file +load_dotenv('db_credentials.env') + +MYSQL_USER = os.getenv('MYSQL_USER') +MYSQL_PASSWORD = os.getenv('MYSQL_PASSWORD') +MYSQL_HOST = os.getenv('MYSQL_HOST') + +def connect_to_db(): + # Connect to the MySQL server + conn = mysql.connector.connect( + host=MYSQL_HOST, + user=MYSQL_USER, + password=MYSQL_PASSWORD, + database='shellm_sessions' + ) + cursor = conn.cursor() + + return conn, cursor + +app = Flask(__name__) + +CORS(app) + +# Route to fetch SSH sessions from the database +@app.route('/ssh_sessions', methods=['GET']) +def get_ssh_sessions(): + conn, cursor = connect_to_db() + if conn is None: + return jsonify({"error": "Database connection failed"}), 500 + + try: + cursor.execute("SELECT * FROM ssh_session ORDER BY id DESC;") + sessions = cursor.fetchall() # Fetch data as a list of dictionaries + return jsonify(sessions) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + cursor.close() + conn.close() + +@app.route('/shellm_sessions', methods=['GET']) +def get_shellm_sessions(): + conn, cursor = connect_to_db() + cursor.execute("SELECT * FROM shellm_session ORDER BY id DESC;") + sessions = cursor.fetchall() + cursor.close() + conn.close() + + return jsonify(sessions) + +@app.route('/commands', methods=['GET']) +def get_commands(): + conn, cursor = connect_to_db() + cursor.execute("SELECT * FROM commands ORDER BY command_id DESC;") + commands = cursor.fetchall() + cursor.close() + conn.close() + + return jsonify(commands) + +@app.route('/answers', methods=['GET']) +def get_answers(): + conn, cursor = connect_to_db() + cursor.execute("SELECT * FROM answers ORDER BY answer_id DESC;") + answers = cursor.fetchall() + cursor.close() + conn.close() + + return jsonify(answers) + +# Route to render the dashboard +@app.route('/', methods=['GET']) +def dashboard(): + return render_template('dashboard.html') + +@app.route('/commands_answers/', methods=['GET']) +def get_commands_answers(shellm_session_id): + conn, cursor = connect_to_db() + + # Fetch commands and their associated answers + cursor.execute(""" + SELECT c.command_id, c.command, a.answer_id, COALESCE(a.answer, 'No answer') AS answer + FROM commands c + LEFT JOIN answers a ON c.command_id = a.command_id + WHERE c.shellm_session_id = %s + """, (shellm_session_id,)) + + results = cursor.fetchall() + conn.close() + + # Return as a JSON response + # Return as a JSON response + return jsonify([ + { + "command_id": row[0], + "command": row[1], + "answer_id": row[2], + "answer": row[3] + } + for row in results + ]) + +if __name__ == "__main__": + app.run(debug=True) \ No newline at end of file diff --git a/Log Manager/script.js b/Log Manager/script.js new file mode 100644 index 0000000..cb74775 --- /dev/null +++ b/Log Manager/script.js @@ -0,0 +1,388 @@ +// Function to fetch SSH session data from the Flask server +function fetchSSH_Sessions() { + fetch('http://127.0.0.1:5000/ssh_sessions') + .then(response => response.json()) + .then(data => { + displaySSHSessions(data); + }) + .catch(error => { + console.error('Error fetching SSH sessions:', error); + }); +} + +// Function to fetch shelLM sessions data from the Flask server +function fetchShelLM_Sessions() { + fetch('http://127.0.0.1:5000/shellm_sessions') + .then(response => response.json()) + .then(data => { + displayshelLMSessions(data); + }) + .catch(error => { + console.error('Error fetching shelLM sessions:', error); + }); +} + +// Function to fetch Commands data from the Flask server +function fetchCommands() { + fetch('http://127.0.0.1:5000/commands') + .then(response => response.json()) + .then(data => { + displayCommands(data); + }) + .catch(error => { + console.error('Error fetching Commands:', error); + }); +} + +// Function to fetch Answers data from the Flask server +function fetchAnswers() { + fetch('http://127.0.0.1:5000/answers') + .then(response => response.json()) + .then(data => { + displayAnswers(data); + }) + .catch(error => { + console.error('Error fetching Answers:', error); + }); +} + +// Function to display SSH sessions in the table +function displaySSHSessions(sessions) { + console.log("Sessions data received:", sessions); + + const table = document.getElementById("ssh-sessions-table"); // Reference to the table + const tableBody = document.getElementById("ssh-sessions-table-body"); + + if (!table || !tableBody) { + console.error("Table or table body with ID 'ssh-sessions-table' or 'ssh-sessions-table-body' not found."); + return; + } + + // Make sure the table is visible + table.style.display = "table"; // Unhide the table + + // Clear previous entries + tableBody.innerHTML = ""; + + // Check if 'sessions' is an array and contains valid data + if (Array.isArray(sessions) && sessions.length > 0) { + sessions.forEach((session, index) => { + console.log(`Processing session ${index}:`, session); + + if (!Array.isArray(session) || session.length < 7) { + console.error("Invalid session data:", session); + return; + } + + const row = document.createElement("tr"); + + const idCell = document.createElement("td"); + idCell.textContent = session[0]; + + const usernameCell = document.createElement("td"); + usernameCell.textContent = session[1]; + + const timeDateCell = document.createElement("td"); + timeDateCell.textContent = session[2]; + + const srcIPCell = document.createElement("td"); + srcIPCell.textContent = session[3]; + + const dstIPCell = document.createElement("td"); + dstIPCell.textContent = session[4]; + + const dstPortCell = document.createElement("td"); + dstPortCell.textContent = session[6]; + + row.appendChild(idCell); + row.appendChild(usernameCell); + row.appendChild(timeDateCell); + row.appendChild(srcIPCell); + row.appendChild(dstIPCell); + row.appendChild(dstPortCell); + + tableBody.appendChild(row); + }); + + console.log("Table populated successfully."); + } else { + console.error("Invalid data structure received:", sessions); + } +} + + +// Function to display SSH sessions in the table +function displayshelLMSessions(sessions) { + console.log("Sessions data received:", sessions); + + const table = document.getElementById("shellm-sessions-table"); // Reference to the table + const tableBody = document.getElementById("shellm-sessions-table-body"); + + if (!table || !tableBody) { + console.error("Table or table body with ID 'shellm-sessions-table' or 'shellm-sessions-table-body' not found."); + return; + } + + // Make sure the table is visible + table.style.display = "table"; // Unhide the table + + // Clear previous entries + tableBody.innerHTML = ""; + + // Check if 'sessions' is an array and contains valid data + if (Array.isArray(sessions) && sessions.length > 0) { + sessions.forEach((session, index) => { + console.log(`Processing session ${index}:`, session); + + if (!Array.isArray(session) || session.length < 6) { + console.error("Invalid session data:", session); + return; + } + + const row = document.createElement("tr"); + + const idCell = document.createElement("td"); + idCell.textContent = session[0]; + idCell.style.cursor = "pointer"; + idCell.addEventListener("click", () => fetchAndDisplayCommandsAnswers(session[0])); + + const ssh_session_idCell = document.createElement("td"); + ssh_session_idCell.textContent = session[1]; + + const modelCell = document.createElement("td"); + modelCell.textContent = session[2]; + + const start_timeCell = document.createElement("td"); + start_timeCell.textContent = session[3]; + + const end_timeCell = document.createElement("td"); + end_timeCell.textContent = session[4]; + + const attacker_idCell = document.createElement("td"); + attacker_idCell.textContent = session[5]; + + row.appendChild(idCell); + row.appendChild(ssh_session_idCell); + row.appendChild(modelCell); + row.appendChild(start_timeCell); + row.appendChild(end_timeCell); + row.appendChild(attacker_idCell); + + tableBody.appendChild(row); + }); + + console.log("Table populated successfully."); + } else { + console.error("Invalid data structure received:", sessions); + } +} + +// Function to display SSH sessions in the table +function displayCommands(sessions) { + console.log("Commands data received:", sessions); + + const table = document.getElementById("commands-table"); // Reference to the table + const tableBody = document.getElementById("commands-table-body"); + + if (!table || !tableBody) { + console.error("Table or table body with ID 'commands-table' or 'commands-table-body' not found."); + return; + } + + // Make sure the table is visible + table.style.display = "table"; // Unhide the table + + // Clear previous entries + tableBody.innerHTML = ""; + + // Check if 'sessions' is an array and contains valid data + if (Array.isArray(sessions) && sessions.length > 0) { + sessions.forEach((session, index) => { + console.log(`Processing command ${index}:`, session); + + if (!Array.isArray(session) || session.length < 3) { + console.error("Invalid commands data:", session); + return; + } + + const row = document.createElement("tr"); + + const idCell = document.createElement("td"); + idCell.textContent = session[0]; + + const shellm_session_idCell = document.createElement("td"); + shellm_session_idCell.textContent = session[1]; + + const commandCell = document.createElement("td"); + commandCell.textContent = session[2]; + + row.appendChild(idCell); + row.appendChild(shellm_session_idCell); + row.appendChild(commandCell); + + tableBody.appendChild(row); + }); + + console.log("Table populated successfully."); + } else { + console.error("Invalid data structure received:", sessions); + } +} + +// Function to display SSH sessions in the table +function displayAnswers(sessions) { + console.log("Answers data received:", sessions); + + const table = document.getElementById("answers-table"); // Reference to the table + const tableBody = document.getElementById("answers-table-body"); + + if (!table || !tableBody) { + console.error("Table or table body with ID 'answers-table' or 'answers-table-body' not found."); + return; + } + + // Make sure the table is visible + table.style.display = "table"; // Unhide the table + + // Clear previous entries + tableBody.innerHTML = ""; + + // Check if 'sessions' is an array and contains valid data + if (Array.isArray(sessions) && sessions.length > 0) { + sessions.forEach((session, index) => { + console.log(`Processing answer ${index}:`, session); + + if (!Array.isArray(session) || session.length < 3) { + console.error("Invalid answer data:", session); + return; + } + + const row = document.createElement("tr"); + + const idCell = document.createElement("td"); + idCell.textContent = session[0]; + + const command_idCell = document.createElement("td"); + command_idCell.textContent = session[1]; + + const answerCell = document.createElement("td"); + answerCell.textContent = session[2]; + + row.appendChild(idCell); + row.appendChild(command_idCell); + row.appendChild(answerCell); + + tableBody.appendChild(row); + }); + + console.log("Table populated successfully."); + } else { + console.error("Invalid data structure received:", sessions); + } +} + +// Function to fetch and display commands and answers for a shellm session +function fetchAndDisplayCommandsAnswers(shellmSessionID) { + console.log("Fetching commands and answers for ShellM Session ID:", shellmSessionID); + + fetch(`http://127.0.0.1:5000/commands_answers/${shellmSessionID}`) + .then((response) => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) + .then((data) => { + const tableBody = document.getElementById("commands-answers-table-body"); + const commandsAnswersTable = document.getElementById("commands-answers-table"); + + if (!tableBody || !commandsAnswersTable) { + console.error("Commands and Answers table elements not found in the DOM."); + return; + } + + // Clear previous entries + tableBody.innerHTML = ""; + + // Show the table + commandsAnswersTable.style.display = "table"; + + // Populate the table with the received data + if (Array.isArray(data) && data.length > 0) { + data.forEach((entry) => { + const row = document.createElement("tr"); + + // Create and populate cells + const commandIDCell = document.createElement("td"); + commandIDCell.textContent = entry.command_id || "N/A"; + + const commandCell = document.createElement("td"); + commandCell.textContent = entry.command || "N/A"; + + const answerIDCell = document.createElement("td"); + answerIDCell.textContent = entry.answer_id || "N/A"; + + const answerCell = document.createElement("td"); + answerCell.textContent = entry.answer || "N/A"; + + // Append cells to the row + row.appendChild(commandIDCell); + row.appendChild(commandCell); + row.appendChild(answerIDCell); + row.appendChild(answerCell); + + // Append the row to the table body + tableBody.appendChild(row); + }); + } else { + // If no data is found, show a "No data available" message + const row = document.createElement("tr"); + const noDataCell = document.createElement("td"); + noDataCell.textContent = "No commands or answers found for this session."; + noDataCell.colSpan = 4; + row.appendChild(noDataCell); + tableBody.appendChild(row); + } + }) + .catch((error) => console.error("Error fetching commands and answers:", error)); +} + +// Function to hide all tables +function hideAllTables() { + const tables = document.querySelectorAll('table'); + tables.forEach(table => table.style.display = 'none'); +} + +// Add event listeners to the buttons +document.getElementById('sshSessionsBtn').addEventListener('click', () => { + hideAllTables(); + fetchSSH_Sessions(); +}); +document.getElementById('shelLM_SessionsBtn').addEventListener('click', () => { + hideAllTables(); + fetchShelLM_Sessions(); +}); +document.getElementById('commandsBtn').addEventListener('click', () => { + hideAllTables(); + fetchCommands(); +}); +document.getElementById('answersBtn').addEventListener('click', () => { + hideAllTables(); + fetchAnswers(); +}); + +// Function to handle ID click +function handleIDClick(shellmSessionID) { + console.log("ShellM Session ID clicked:", shellmSessionID); + + const commandsAnswersSection = document.getElementById("commands-answers-section"); + commandsAnswersSection.style.display = "block"; // Show the new button + + const commandsAnswersBtn = document.getElementById("commandsAnswersBtn"); + commandsAnswersBtn.onclick = () => fetchAndDisplayCommandsAnswers(shellmSessionID); // Attach handler +} + +// Ensure the page is ready for actions +document.addEventListener("DOMContentLoaded", () => { + console.log("Log Manager Dashboard ready."); +}); diff --git a/Log Manager/ssh_module.py b/Log Manager/ssh_module.py new file mode 100644 index 0000000..6fa1bff --- /dev/null +++ b/Log Manager/ssh_module.py @@ -0,0 +1,419 @@ +import paramiko +import mysql.connector +from datetime import datetime, timedelta +from dotenv import load_dotenv +import os + + +# Load environment variables from .env file +load_dotenv('db_credentials.env') + +MYSQL_USER = os.getenv('MYSQL_USER') +MYSQL_PASSWORD = os.getenv('MYSQL_PASSWORD') +MYSQL_HOST = os.getenv('MYSQL_HOST') + + +def parse_last_output(last_output): + sessions = [] + + # Process the output line by line + for line in last_output.splitlines(): + # Skip empty lines or irrelevant lines + if not line.strip() or line.startswith("wtmp") or "reboot" in line: + continue + + parts = line.split() # Split the line into words + + # Extract details based on fixed column positions + username = parts[0] + terminal = parts[1] + src_ip = parts[2] if parts[2] != ":0" else "127.0.0.1" # Default to localhost for local logins + time_date_start = " ".join(parts[3:8]) # Combine the time and date parts + + # Convert time strings to MySQL-compatible format + time_date_start = datetime.strptime(time_date_start, "%a %b %d %H:%M:%S %Y").strftime("%Y-%m-%d %H:%M:%S") + + # Destination IP (your server IP or localhost for testing) + dst_ip = "olympus.felk.cvut.cz" + dst_port = 1337 + + # Append parsed data as a tuple + sessions.append((username, time_date_start, src_ip, dst_ip, dst_port)) + + return sessions + + +def connect_to_db(): + # Connect to the MySQL server + conn = mysql.connector.connect( + host=MYSQL_HOST, + user=MYSQL_USER, + password=MYSQL_PASSWORD, + database='shellm_sessions' + ) + cursor = conn.cursor() + + return conn, cursor + + +# Function to insert data into MySQL +def insert_into_ssh_session(data): + conn, cursor = connect_to_db() + + # Insert data into ssh_session table + for session in data: + cursor.execute(""" + INSERT INTO ssh_session (username, time_date, src_ip, dst_ip, dst_port) + VALUES (%s, %s, %s, %s, %s) + """, session) + + # Commit and close + conn.commit() + cursor.close() + conn.close() + + +# Function to insert data into MySQL +def insert_into_attacker_session(data): + conn, cursor = connect_to_db() + + # Insert data into ssh_session table + for session in data: + src_ip = session[2] + cursor.execute(""" + INSERT INTO attacker_session (src_ip) + VALUES (%s) + """, (src_ip,)) + + # Commit and close + conn.commit() + cursor.close() + conn.close() + + +# Function to count how many new connections were to ssh since last database entry +def count_newest(data): + conn, cursor = connect_to_db() + + cursor.execute(""" + SELECT time_date FROM ssh_session ORDER BY id DESC LIMIT 1; + """) + + latest_entry = cursor.fetchone() + + if latest_entry: + time_date = latest_entry[0] + + # Check if it's a datetime object or a string + if isinstance(time_date, datetime): + # If it's a datetime object, format it as a string + time_date_str = time_date.strftime(f"%Y-%m-%d %H:%M:%S") + else: + # If it's already a string, use it directly + time_date_str = str(time_date) + + counter = 0 + + # Go through ssh logs and stop when old entries are reached + for session in data: + if session[1] <= time_date_str: # time_date_str - the specific date is only for testing + break + else: + counter += 1 + + # Commit and close + conn.commit() + cursor.close() + conn.close() + + return counter + + +def create_filenames(data): + filenames = [] + + for session in data: + # Extract the time_date value from the session tuple + time_date = session[1] # Assuming time_date is the second element in the tuple + + # Convert the time_date to a string if it's not already + if isinstance(time_date, datetime): + time_date = time_date + timedelta(seconds=1) + time_date_str = time_date.strftime(f"%Y-%m-%d_%H-%M-%S") + else: + time_date_str = str(time_date).replace(" ", "_").replace(":", "-") + + # Create the filename using the formatted time_date + filename = f"historySSH_{time_date_str}.txt" + filenames.append(filename) + + return filenames + + +def get_latest_sessions_ids(counter): + ids = [] + + conn, cursor = connect_to_db() + cursor.execute(""" + SELECT id FROM ssh_session ORDER BY id DESC LIMIT %s; + """,(counter,)) + ids = [row[0] for row in cursor.fetchall()] + + return ids + + +def get_latest_attackers_ids(counter): + ids = [] + + conn, cursor = connect_to_db() + cursor.execute(""" + SELECT attacker_session_id FROM attacker_session ORDER BY attacker_session_id DESC LIMIT %s; + """,(counter,)) + ids = [row[0] for row in cursor.fetchall()] + + return ids + + +def parse_historylog(filename, ssh): + stdin, stdout, stderr = ssh.exec_command(f"cat /path/to/the/specific/historylog/{filename}") + conversation = stdout.read().decode('utf-8') + conversation_error = stderr.read().decode('utf-8') + + commands = [] + answers = [] + timestamps = [] + start = "" + + lines = conversation.splitlines() + + previous_line = None + output = None + + for line in lines: + + if "For the last login date use" in line: + line_parts = line.split() + start = line_parts[-2] + " " + line_parts[-1] + + # Check if the line contains a command + if line.strip().endswith('>'): # Command line ends with '>' + + # First make sure if there is a multiline output to put it to answers + if output is not None: + answers.append(output) + output = None + + split_line = line.split() + + command = split_line[1:-2] + command = ' '.join(command) + + if previous_line is not None and ":~" in previous_line: + output = split_line[0] + answers.append(output) + output = None + + # print(line) + # print(command) + + # For the exit command just put "" + if command == "exit": + answers.append("") + + # Extract timestamp from the command line + try: + timestamp = split_line[-2] + split_line[-1] + timestamps.append(timestamp) + except (IndexError, ValueError): + pass # Ignore lines without valid timestamps + + commands.append(command) + + previous_line = line + + else: + # Collect lines of output for the current command + if previous_line is not None: + if ":~" in previous_line: + output = line.strip() + previous_line = line + else: + output = output + "\n" + line.strip() + previous_line = line + + # Determine start and end times + timestamps = [timestamps[0], timestamps[-1]] + start_time = start if start else timestamps[0] if timestamps else None + end_time = timestamps[1] if timestamps else None + + # print(timestamps) + # print(commands) + # print(answers) + + return commands, answers, start_time, end_time + + +def insert_into_commands_and_answers(commands, shellm_session_id, answers): + conn, cursor = connect_to_db() + + try: + # Ensure we have a matching number of commands and answers + if len(commands) != len(answers): + raise ValueError("The number of commands and answers must be equal.") + + answer_counter = 0 + + # Insert each command and its corresponding answer + for command in commands: + # Insert command into 'commands' table + cursor.execute(""" + INSERT INTO commands (shellm_session_id, command) + VALUES (%s, %s) + """, (shellm_session_id, command)) + + # Fetch the last inserted 'command_id' + cursor.execute(""" + SELECT LAST_INSERT_ID(); + """) + command_id = cursor.fetchone()[0] # Extract the value from the tuple + + # Insert answer into 'answers' table + cursor.execute(""" + INSERT INTO answers (command_id, answer) + VALUES (%s, %s) + """, (command_id, answers[answer_counter])) + + answer_counter += 1 + + # Commit the transaction + conn.commit() + + except Exception as e: + print(f"An error occurred: {e}") + conn.rollback() # Rollback in case of error + + finally: + # Clean up resources + cursor.close() + conn.close() + + +def insert_into_shellm_session(start_time, end_time, latest_session_ids, latest_attacker_ids): + conn, cursor = connect_to_db() + + ssh_session_id = latest_session_ids[0] + latest_attacker_id = latest_attacker_ids[0] + + cursor.execute(""" + INSERT INTO shellm_session (ssh_session_id, model, start_time, end_time, attacker_id) + VALUES (%s, %s, %s, %s, %s) + """, (ssh_session_id, "FT GPT-3.5-16k", start_time, end_time, latest_attacker_id)) + + conn.commit() + cursor.close() + conn.close() + + +def get_latest_shellm_session(): + + conn, cursor = connect_to_db() + + cursor.execute(""" + SELECT id FROM shellm_session ORDER BY id DESC LIMIT 1; + """) + + shellm_session_id = cursor.fetchone() + + # Commit and close + conn.commit() + cursor.close() + conn.close() + + return shellm_session_id + + +def format_datetime_for_db(raw_time): + # Step 1: Remove angle brackets + cleaned_time = raw_time.strip('<>') + + # Step 2: Insert a space between the date and time + formatted_time = cleaned_time[:10] + ' ' + cleaned_time[10:] + + # Step 3: Convert to datetime object (validates the format) + datetime_obj = datetime.strptime(formatted_time, f"%Y-%m-%d %H:%M:%S.%f") + + # Step 4: Format to MySQL-compatible DATETIME string + return datetime_obj.strftime(f"%Y-%m-%d %H:%M:%S") + + +def get_logs_from_server(): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + # Load your private key to log in to remote server with logs + private_key = paramiko.RSAKey.from_private_key_file('C:\\pathtoprivatekey\\id_rsa') + + # Connect to the SSH server using key-based authentication + ssh.connect(hostname="hostname", port="", username="user", pkey=private_key) + + # Execute commands as before + stdin, stdout, stderr = ssh.exec_command("docker exec containerid last -F") + error_output = stderr.read().decode('utf-8') + docker_history = stdout.read().decode('utf-8') + + ssh_data = parse_last_output(docker_history) + counter = count_newest(ssh_data) + ssh_data = ssh_data[:counter][::-1] + + stdin, stdout, stderr = ssh.exec_command(f"ls /path/to/history/logs") + shellm_histories = stdout.read().decode('utf-8') + error_getting_histories = stderr.read().decode('utf-8') + + # Get just the last created histories. Ignore earlier. This is to know exact file names of history logs. + shellm_histories = shellm_histories.split() + shellm_histories = shellm_histories[-counter:][::1] + # print(shellm_histories) + + if counter > 0: + if docker_history: + insert_into_ssh_session(ssh_data) + insert_into_attacker_session(ssh_data) + else: + print(error_output) + + # filenames = create_filenames(ssh_data) + # print(filenames) + + # Get ids of the latest created session. They are FKs in shellm_session table. Invert them to get them in right order. + latest_sessions_ids = get_latest_sessions_ids(counter) + latest_sessions_ids = latest_sessions_ids[:][::-1] + latest_attacker_ids = get_latest_attackers_ids(counter) + latest_attacker_ids = latest_attacker_ids[:][::-1] + # print(latest_sessions_ids) + + for filename in shellm_histories: + commands, answers, start_time, end_time = parse_historylog(filename, ssh) + + start_time = format_datetime_for_db(start_time) + end_time = format_datetime_for_db(end_time) + + insert_into_shellm_session(start_time, end_time, latest_sessions_ids, latest_attacker_ids) + + shellm_session_id = get_latest_shellm_session() + # print(shellm_session_id) + + insert_into_commands_and_answers(commands, shellm_session_id[0], answers) + + # Pop the processed ssh_session + latest_sessions_ids = latest_sessions_ids[1:] + latest_attacker_ids = latest_attacker_ids[1:] + + + # log_file_content = stdout.read().decode() + + ssh.close() + + return docker_history#, log_file_content + +if __name__ == "__main__": + get_logs_from_server() \ No newline at end of file diff --git a/Log Manager/style.css b/Log Manager/style.css new file mode 100644 index 0000000..0ce352e --- /dev/null +++ b/Log Manager/style.css @@ -0,0 +1,93 @@ +body { + font-family: Arial, sans-serif; + margin: 0; + padding: 0; + background-color: #f9f9f9; + color: #333; +} + +h1 { + text-align: center; + padding: 20px; + background-color: #4CAF50; + color: white; + margin: 0; +} + +.container { + max-width: 1200px; + margin: 20px auto; + padding: 20px; + background: white; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); +} + +.button-container { + display: flex; + justify-content: center; + margin-bottom: 20px; +} + +.button-container button { + background-color: #4CAF50; + color: white; + border: none; + padding: 10px 20px; + margin: 0 10px; + border-radius: 5px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.button-container button:hover { + background-color: #45a049; +} + +table { + border-collapse: collapse; + width: 100%; + margin-top: 20px; +} + +th, td { + border: 1px solid #ddd; + padding: 12px; + text-align: left; +} + +th { + background-color: #4CAF50; + color: white; +} + +tr:nth-child(even) { + background-color: #f2f2f2; +} + +tr:hover { + background-color: #ddd; +} + +#commands-answers-table { + display: none; +} + +.table-header { + margin-top: 30px; + text-align: center; + font-size: 18px; + color: #555; +} + +footer { + text-align: center; + margin-top: 40px; + padding: 10px 0; + background-color: #4CAF50; + color: white; + position: relative; + bottom: 0; + width: 100%; +}