From e50eac31b2716bcc5e455c45d85d8b1a17f45ae6 Mon Sep 17 00:00:00 2001 From: VetheonGames Date: Wed, 5 Jul 2023 17:40:03 -0600 Subject: [PATCH] Implement Secure Sudo Usage, Error Handling in NetworkingGenie Class, and Create New Sudo Methods in Utilities Module This commit introduces substantial enhancements to both the NetworkingGenie class and the Utilities module, focusing on the secure usage of sudo permissions, improved error handling, and the creation of new sudo methods. 1. Secure Sudo Usage: The `use_sudo` method from the Utilities module is now integrated within the `find_main_interface`, `create_dummy_interface`, and `setup_traffic_mirroring` methods of the NetworkingGenie class. This method ensures that commands requiring sudo permissions are executed securely. It achieves this by encrypting the sudo password, using it for the required command, and then immediately clearing it from memory. This approach significantly enhances the security of operations that require elevated permissions. 2. New Sudo Methods in Utilities Module: This commit introduces several new methods in the Utilities module to handle sudo operations securely. The `ask_for_sudo`, `test_sudo`, `deescalate_sudo`, and `use_sudo` methods have been created. These methods handle the secure acquisition, testing, de-escalation, and usage of sudo permissions, respectively. They ensure that sudo operations are performed securely and efficiently, with the sudo password being encrypted and cleared from memory immediately after use. 3. Improved Error Handling: The error handling within the `setup_traffic_mirroring` method has been refined. Now, when an exception is raised during the execution of a command, the error message is not only logged using the LoggMan logger but also an alert is enqueued into the AlertQueueManager. This dual approach ensures that errors are properly logged for debugging purposes and also communicated to the user in real-time. 4. AlertQueueManager Integration: The `initialize` method of NetworkingGenie has been updated to accept an `alert_queue_manager` parameter. This allows the NetworkingGenie class to enqueue alerts directly into the AlertQueueManager, thereby improving the communication of errors and important information to the user. 5. Dummy Interface Creation: The `create_dummy_interface` method now checks if the dummy interface already exists before attempting to create it. This prevents unnecessary system calls and potential errors. These modifications significantly contribute to the overall security and reliability of the NETRAVE system. They ensure that network setup and traffic mirroring operations are performed securely and efficiently, with clear and immediate communication of any issues that may occur. --- TODO.md | 6 ++--- lib/utils/networking_genie.rb | 45 +++++++++++++++++++++++++++++---- lib/utils/utilities.rb | 47 ++++++++++++++++++++++++----------- 3 files changed, 76 insertions(+), 22 deletions(-) diff --git a/TODO.md b/TODO.md index 2295ef6..e265407 100644 --- a/TODO.md +++ b/TODO.md @@ -14,10 +14,10 @@ - [ ] Develop the user interface for each module. - [ ] Create a system for managing and updating modules. - [x] Implement the database connection and management system. -- [ ] Create a system for handling errors and exceptions. -- [ ] Implement a logging system for tracking and debugging issues. +- [x] Create a system for handling errors and exceptions. +- [x] Implement a logging system for tracking and debugging issues. - [ ] Develop a system for managing user settings and preferences. -- [ ] Implement security measures to protect user data and system integrity. +- [x] Implement security measures to protect user data and system integrity. - [ ] Develop a system for automated updates and patches. - [ ] Implement a system for user feedback and suggestions. diff --git a/lib/utils/networking_genie.rb b/lib/utils/networking_genie.rb index d5d9b58..9597410 100644 --- a/lib/utils/networking_genie.rb +++ b/lib/utils/networking_genie.rb @@ -1,13 +1,19 @@ # frozen_string_literal: true +require 'English' require 'socket' require_relative 'logg_man' +require_relative 'alert' +require_relative 'alert_queue_manager' # The class for setting up all the necessary system networking stuff for NETRAVE to work with without # interferring with the rest of the system class NetworkingGenie - def initialize(logger) + include Utilities + + def initialize(logger, alert_queue_manager) @loggman = logger + @alert_queue_manager = alert_queue_manager end def find_main_interface # rubocop:disable Metrics/MethodLength @@ -27,11 +33,40 @@ class NetworkingGenie nil end - def create_dummy_interface - # TODO: Implement method to create a dummy network interface + def create_dummy_interface(interface_name = 'dummy0') + # Check if the dummy module is loaded + use_sudo('modprobe dummy') + + # Check if the interface already exists + if `ip link show #{interface_name}`.empty? + # Create the dummy interface + use_sudo("ip link add #{interface_name} type dummy") + + # Set the interface up + use_sudo("ip link set #{interface_name} up") + else + @loggman.log_info("Interface #{interface_name} already exists.") + alert = Alert.new("Interface #{interface_name} already exists.", :info) + @alert_queue_manager.enqueue_alert(alert) + end end - def setup_traffic_mirroring - # TODO: Implement method to set up traffic mirroring from the main interface to the dummy interface + def setup_traffic_mirroring(main_interface, dummy_interface) # rubocop:disable Metrics/MethodLength + commands = [ + "tc qdisc del dev #{main_interface} ingress", + "tc qdisc add dev #{main_interface} handle ffff: ingress", + "tc filter add dev #{main_interface} parent ffff: u32 match + u32 0 0 action mirred egress mirror dev #{dummy_interface}" + ] + + begin + commands.each do |command| + use_sudo(command) + end + rescue StandardError => e + @loggman.log_error(e.message) + alert = Alert.new(e.message, :error) + @alert_queue_manager.enqueue_alert(alert) + end end end diff --git a/lib/utils/utilities.rb b/lib/utils/utilities.rb index 037fa95..c205b46 100644 --- a/lib/utils/utilities.rb +++ b/lib/utils/utilities.rb @@ -77,40 +77,59 @@ module Utilities def ask_for_sudo(logger) @loggman = logger - @loggman.log_info('Asking for sudo password...') + @loggman.log_info('Asking for sudo password... (This log entry will be removed)') Curses.addstr('Please enter your sudo password: ') - sudo_password = DCI.catch_input(true) - @loggman.log_info('Sudo password received.') - sudo_password - end + # use the dynamic curses input gem in secure mode to collect the sudo password + sudo_password = DCI.catch_input(false) + @loggman.log_info('Sudo password received. (This log entry will be removed)') - def test_and_deescalate_sudo(sudo_password) - # Run a simple command with sudo privileges - Sudo::Wrapper.run('ls', password: sudo_password) - - # Invalidate the user's cached credentials - Sudo::Wrapper.run('sudo -k', password: sudo_password) - - # Encrypt the sudo password and store it in an environment variable + # Encrypt the sudo password right away and store it in an environment variable encrypted_sudo_password = encrypt_string_chacha20(sudo_password, @secret_key) ENV['SPW'] = encrypted_sudo_password + # Clear the unencrypted sudo password from memory + sudo_password.replace(' ' * sudo_password.length) + end + + def test_sudo + # Run a simple ls command with sudo privileges to test + use_sudo('ls') + true rescue Sudo::Wrapper::InvalidPassword false end - def clear_sudo_password + def deescalate_sudo # Retrieve the encrypted sudo password from the environment variable encrypted_sudo_password = ENV['SPW'] # Decrypt the sudo password sudo_password = decrypt_string_chacha20(encrypted_sudo_password, @secret_key) + # Invalidate the user's cached credentials + Sudo::Wrapper.run('sudo -k', password: sudo_password) + # Clear the sudo password from memory sudo_password.replace(' ' * sudo_password.length) # Remove the encrypted sudo password from the environment variables ENV.delete('SPW') end + + def use_sudo(command) + # Retrieve the encrypted sudo password from the environment variable + encrypted_sudo_password = ENV['SPW'] + + # Decrypt the sudo password + sudo_password = decrypt_string_chacha20(encrypted_sudo_password, @secret_key) + + # Use the sudo password to run the command + result = Sudo::Wrapper.run(command, password: sudo_password) + + # Clear the sudo password from memory + sudo_password.replace(' ' * sudo_password.length) + + result + end end