diff --git a/app/Config/OpenAudit.php b/app/Config/OpenAudit.php index d900fc032..f063105a6 100755 --- a/app/Config/OpenAudit.php +++ b/app/Config/OpenAudit.php @@ -14,7 +14,7 @@ class OpenAudit extends BaseConfig public string $displayVersion = '5.1.0'; public int $appVersion = 20240104; - public array $enterprise_collections = array('applications' => 'cud', 'baselines' => 'crud', 'baselines_policies' => 'crud', 'baselines_results' => 'crud', 'clouds' => 'crud', 'collectors' => 'crud', 'dashboards' => 'cud', 'discovery_scan_options' => 'cud', 'files' => 'crud', 'integrations' => 'crud', 'racks' => 'crud', 'roles' => 'cu'); + public array $enterprise_collections = array('applications' => 'cud', 'baselines' => 'crud', 'baselines_policies' => 'crud', 'baselines_results' => 'crud', 'clouds' => 'crud', 'collectors' => 'crud', 'dashboards' => 'cud', 'discovery_scan_options' => 'cud', 'files' => 'crud', 'executables' => 'crud', 'integrations' => 'crud', 'racks' => 'crud', 'roles' => 'cu'); public array $professional_collections = array('applications' => 'r', 'clusters' => 'crud', 'dashboards' => 'r', 'discovery_scan_options' => 'r', 'maps' => 'crud', 'rules' => 'crud', 'tasks' => 'crud', 'widgets' => 'crud'); public float $microtime = 0; public int $collector_connect_timeout = 10; @@ -32,6 +32,7 @@ class OpenAudit extends BaseConfig public string $server_os = ''; public string $server_platform = ''; public bool $advanced_queries = true; + public bool $executables = false; public function __set($key, $value) { diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 0439793ee..fa2a1f888 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -15,7 +15,7 @@ */ $collections = array('agents','applications','attributes','baselines','baselines_policies','baselines_results','clouds','clusters','collectors', 'components', -'configuration','connections','credentials','dashboards','devices','discoveries','discovery_log','discovery_scan_options','errors','fields','files', +'configuration','connections','credentials','dashboards','devices','discoveries','discovery_log','discovery_scan_options','errors','executables','fields','files', 'groups','integrations','ldap_servers','licenses','locations','maps','networks','nmis','orgs','queries','queue','racks','rack_devices','reports','roles', 'rules','scripts','summaries','support','tasks','users','widgets'); diff --git a/app/Controllers/Input.php b/app/Controllers/Input.php index c72358969..85e70eb4e 100644 --- a/app/Controllers/Input.php +++ b/app/Controllers/Input.php @@ -54,7 +54,7 @@ public function devices() include "include_process_device.php"; $discoveryLogModel = new \App\Models\DiscoveryLogModel(); $log = new \stdClass(); - $log->discovery_id = null; + $log->discovery_id = (!empty($device->system->discovery_id)) ? intval($device->system->discovery_id) : null; $log->device_id = $device->system->id; $log->timestamp = null; $log->severity = 7; diff --git a/app/Controllers/Scripts.php b/app/Controllers/Scripts.php index 4a74c15fe..c05933ec1 100644 --- a/app/Controllers/Scripts.php +++ b/app/Controllers/Scripts.php @@ -32,13 +32,15 @@ class Scripts extends BaseController { public function download($id) { - $id = intval($id); if (empty($this->scriptsModel)) { $this->scriptsModel = model('App\Models\ScriptsModel'); } if (!is_numeric($id)) { $id = $this->scriptsModel->getByOs($id); } + if (is_numeric($id)) { + $id = intval($id); + } if (empty($id)) { return; } diff --git a/app/Controllers/include_process_device.php b/app/Controllers/include_process_device.php index 7318202a8..3ccdb5059 100644 --- a/app/Controllers/include_process_device.php +++ b/app/Controllers/include_process_device.php @@ -16,7 +16,7 @@ helper('utility'); $log = new \stdClass(); -$log->discovery_id = null; +$log->discovery_id = (!empty($device->system->discovery_id)) ? intval($device->system->discovery_id) : null; $log->device_id = null; $log->timestamp = null; $log->severity = 7; diff --git a/app/Helpers/components_helper.php b/app/Helpers/components_helper.php index a3ae20540..4cf0ae68f 100644 --- a/app/Helpers/components_helper.php +++ b/app/Helpers/components_helper.php @@ -19,6 +19,9 @@ function match_columns($table) if ($table === 'dns') { $match_columns = array('ip', 'name', 'fqdn'); } + if ($table === 'executable') { + $match_columns = array('full_name', 'hash', 'inode', 'last_changed'); + } if ($table === 'file') { $match_columns = array('full_name', 'hash', 'inode', 'last_changed'); } diff --git a/app/Helpers/discoveries_helper.php b/app/Helpers/discoveries_helper.php index 7f2460b50..935b7f0d3 100644 --- a/app/Helpers/discoveries_helper.php +++ b/app/Helpers/discoveries_helper.php @@ -66,7 +66,7 @@ function all_ip_list($discovery = null) function responding_ip_list($discovery = null) { if (is_null($discovery)) { - return false; + return array(); } $discoveryLogModel = new \App\Models\DiscoveryLogModel(); @@ -88,8 +88,20 @@ function responding_ip_list($discovery = null) if ($discovery->scan_options->ping === 'y') { if (!empty($discovery->scan_options->exclude_ip)) { $command = 'nmap -n -oG - -sP --exclude ' . $discovery->scan_options->exclude_ip . ' ' . $discovery->subnet; + // NOTE - Below should be faster than 'normal' Nmap + // $command = 'nmap -n -oG - -sP -T5 --min-parallelism 100 --max-parallelism 256 --exclude ' . $discovery->scan_options->exclude_ip . ' ' . $discovery->subnet; } else { $command = 'nmap -n -oG - -sP ' . $discovery->subnet; + // NOTE - Below should be faster than 'normal' Nmap + // $command = 'nmap -n -oG - -sP -T5 --min-parallelism 100 --max-parallelism 256 ' . $discovery->subnet; + // + // NOTE - below is for Linux only and only in specific circumstances + // - Fping doesn't have an exclude option + // - Fping doesn't accept the same host formatting as Nmap, except for 1.2.3.4/5 + // if (filter_var($discovery->subnet, FILTER_VALIDATE_IP)) { + // $discovery->subnet = $discovery->subnet . '/32'; + // } + // $command = 'fping -A -a -q -g -r 2 ' . $discovery->subnet . ' 2>&1'; } if (php_uname('s') === 'Darwin') { $command = '/usr/local/bin/' . $command; @@ -103,13 +115,19 @@ function responding_ip_list($discovery = null) $ip_addresses[] = $temp[1]; } } + // Caters to a single responding IP on each line, for fping or Nmap with piping to cut, et al + // foreach ($output as $line) { + // if (filter_var($line, FILTER_VALIDATE_IP)) { + // $ip_addresses[] = $line; + // } + // } } else { if (php_uname('s') === 'Windows NT' and empty($output)) { log_message('error', 'No response from Nmap. Is the Apache Service running as a normal user?'); } $log->command_output = json_encode($output); $discoveryLogModel->create($log); - return false; + return array(); } } else { if (!empty($discovery->scan_options->exclude_ip)) { @@ -131,7 +149,7 @@ function responding_ip_list($discovery = null) } } else { $discoveryLogModel->create($log); - return false; + return array(); } } $log->command_output = 'Responding IPs: ' . @count($ip_addresses); @@ -1807,7 +1825,7 @@ function ip_audit($ip_scan = null) $log->message = 'Matching device from audit result'; $discoveryLogModel->create($log); $audit_device = deviceMatch($audit->system, intval($discovery->id), $discovery->match_options); - #$audit->system->discovery_id = $discovery->id; + $audit->system->discovery_id = $discovery->id; if (!empty($audit->system->id)) { $log->device_id = $audit->system->id; } @@ -1973,6 +1991,7 @@ function ip_audit($ip_scan = null) unset($device_json->system->original_last_seen); unset($device_json->system->id); unset($device_json->system->first_seen); + $device_json->system->discovery_id = $discovery->id; $device_json = json_encode($device_json); $url = $server->host . $server->community . '/index.php/input/devices'; @@ -1995,6 +2014,7 @@ function ip_audit($ip_scan = null) // error $log->severity = 4; $log->message = 'Could not send result to ' . $url . ' - please check with your server administrator.'; + $log->device_id = $device->id; $discoveryLogModel->create($log); $log->severity = 7; log_message('error', 'Could not send result to ' . $url); @@ -2002,6 +2022,7 @@ function ip_audit($ip_scan = null) // success $log->severity = 7; $log->message = 'Result sent to ' . $server->host . '.'; + $log->device_id = $device->id; $discoveryLogModel->create($log); log_message('debug', 'Result sent to ' . $server->host . '.'); } @@ -2021,6 +2042,7 @@ function ip_audit($ip_scan = null) $log->command_status = 'device complete'; $log->command_time_to_execute = microtime(true) - $start; $log->message = 'IP Audit finish on device ' . ip_address_from_db($device->ip); + $log->device_id = $device->id; $log->ip = ip_address_from_db($device->ip); $discoveryLogModel->create($log); diff --git a/app/Helpers/response_helper.php b/app/Helpers/response_helper.php index e67c76ab7..02b23894a 100644 --- a/app/Helpers/response_helper.php +++ b/app/Helpers/response_helper.php @@ -1498,7 +1498,7 @@ function response_valid_actions() */ function response_valid_collections() { - return array('agents','applications','attributes','baselines','baselines_policies','baselines_results','chart','clouds','clusters','collectors','components','configuration','connections','credentials','dashboards','database','devices','discoveries','discovery_log','discovery_scan_options','errors','fields','files','groups','help','integrations','integrations_log','integrations_rules','ldap_servers','licenses','locations','logs','maps','networks','nmis','orgs','queries','queue','racks','rack_devices','reports','roles','rules','scripts','search','sessions','summaries','support','tasks','users','widgets'); + return array('agents','applications','attributes','baselines','baselines_policies','baselines_results','chart','clouds','clusters','collectors','components','configuration','connections','credentials','dashboards','database','devices','discoveries','discovery_log','discovery_scan_options','errors','executables','fields','files','groups','help','integrations','integrations_log','integrations_rules','ldap_servers','licenses','locations','logs','maps','networks','nmis','orgs','queries','queue','racks','rack_devices','reports','roles','rules','scripts','search','sessions','summaries','support','tasks','users','widgets'); } } @@ -1532,7 +1532,7 @@ function response_valid_formats() */ function response_valid_includes() { - return array('application', 'attachment', 'audit_log', 'bios', 'certificate', 'change_log', 'cluster', 'credential', 'discovery_log', 'disk', 'dns', 'edit_log', 'field', 'file', 'image', 'ip', 'location', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'purchase', 'rack_devices', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'); + return array('application', 'attachment', 'audit_log', 'bios', 'certificate', 'change_log', 'cluster', 'credential', 'discovery_log', 'disk', 'dns', 'edit_log', 'executable', 'field', 'file', 'image', 'ip', 'location', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'purchase', 'rack_devices', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'); } } @@ -1588,7 +1588,7 @@ function response_valid_permissions($collection) */ function response_valid_sub_resources() { - return array('application', 'attachment', 'audit_log', 'bios', 'certificate', 'change_log', 'cluster', 'credential', 'discovery', 'discovery_log', 'disk', 'dns', 'edit_log', 'field', 'image', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'partition_graph', 'policy', 'print_queue', 'processor', 'radio', 'route', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows', 'report', 'query', 'group'); + return array('application', 'attachment', 'audit_log', 'bios', 'certificate', 'change_log', 'cluster', 'credential', 'discovery', 'discovery_log', 'disk', 'dns', 'edit_log', 'executable', 'field', 'image', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'partition_graph', 'policy', 'print_queue', 'processor', 'radio', 'route', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows', 'report', 'query', 'group'); } } diff --git a/app/Helpers/snmp_6876_2_helper.php b/app/Helpers/snmp_6876_2_helper.php index e608d252f..7fbdf2532 100644 --- a/app/Helpers/snmp_6876_2_helper.php +++ b/app/Helpers/snmp_6876_2_helper.php @@ -41,6 +41,7 @@ $guest->cpu = my_snmp_get($ip, $credentials, "1.3.6.1.4.1.6876.2.1.1.9.".$guest->vm_ident); $guest->status = my_snmp_get($ip, $credentials, "1.3.6.1.4.1.6876.2.1.1.6.".$guest->vm_ident); $guest->config_file = my_snmp_get($ip, $credentials, "1.3.6.1.4.1.6876.2.1.1.3.".$guest->vm_ident); + $guest->os = my_snmp_get($ip, $credentials, "1.3.6.1.4.1.6876.2.1.1.4.".$guest->vm_ident); $guest->vm_group = ''; $guest->type = 'esx'; $guests[] = $guest; diff --git a/app/Helpers/snmp_helper.php b/app/Helpers/snmp_helper.php index 0ca0e6833..0108e7b87 100644 --- a/app/Helpers/snmp_helper.php +++ b/app/Helpers/snmp_helper.php @@ -1634,8 +1634,7 @@ function snmp_audit(string $ip = '', object $credentials = null, int $discovery_ $log->command_time_to_execute = (microtime(true) - $item_start); $log->message = 'Route count retrieval for '.$ip; $log->command = 'snmpwalk 1.3.6.1.2.1.4.24.3.0'; - $temp = (!empty($route_count)) ? count($route_count) : 0; - $log->command_output = "Count is $temp"; + $log->command_output = "Count is $route_count"; $log->command_status = 'notice'; if (!empty($route_count) && $route_count < $config_value) { $retrieve_routes = 1; diff --git a/app/Helpers/ssh_helper.php b/app/Helpers/ssh_helper.php index fe7d269cd..b435c3881 100644 --- a/app/Helpers/ssh_helper.php +++ b/app/Helpers/ssh_helper.php @@ -605,7 +605,9 @@ function ssh_audit($parameters) } } else if ($credential->type === 'ssh') { log_message('debug', 'Testing credentials named: ' . $credential->name . ' on ' . $ip); - if ($ssh->login($credential->credentials->username, $credential->credentials->password)) { + // NOTE - Use @ below because some devices cause "Error reading from socket" and halt this process + // TODO - change to try / catch + if (@$ssh->login($credential->credentials->username, $credential->credentials->password)) { $log->message = "Valid credentials named {$credential->name} used to log in to {$ip}."; $log->command_status = 'success'; $discoveryLogModel->create($log); diff --git a/app/Helpers/utility_helper.php b/app/Helpers/utility_helper.php index 436fbcd23..fc38493d4 100644 --- a/app/Helpers/utility_helper.php +++ b/app/Helpers/utility_helper.php @@ -643,6 +643,17 @@ function collections_list() $collections->discovery_scan_options->actions->professional = 'r'; $collections->discovery_scan_options->actions->community = 'r'; + + $collections->executables = new \StdClass(); + $collections->executables->icon = 'fa fa-file-code-o'; + $collections->executables->name = 'Executables'; + $collections->executables->edition = 'Enterprise'; + $collections->executables->orgs = 'b'; + $collections->executables->actions = new \stdClass(); + $collections->executables->actions->enterprise = 'crud'; + $collections->executables->actions->professional = ''; + $collections->executables->actions->community = ''; + $collections->fields = new \StdClass(); $collections->fields->icon = 'fa fa-comments-o'; $collections->fields->name = 'Fields'; diff --git a/app/Models/ComponentsModel.php b/app/Models/ComponentsModel.php index 1ae642417..4d28d6a52 100644 --- a/app/Models/ComponentsModel.php +++ b/app/Models/ComponentsModel.php @@ -47,7 +47,7 @@ public function collection(object $resp): array } if ($table === '') { // No components.type requested, return all the below - $tables = array('bios', 'certificate', 'disk', 'dns', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'); + $tables = array('bios', 'certificate', 'disk', 'dns', 'executable', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'); } $orgs = array(); $count = count($resp->meta->filter); @@ -67,7 +67,7 @@ public function collection(object $resp): array } } if (empty($tables)) { - if (!in_array($table, ['audit_log', 'bios', 'certificate', 'change_log', 'discovery_log', 'disk', 'dns', 'edit_log', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'])) { + if (!in_array($table, ['audit_log', 'bios', 'certificate', 'change_log', 'discovery_log', 'disk', 'dns', 'edit_log', 'executable', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'])) { # Invalid table log_message('error', 'Invalid table provided to ComponentsModel::collection, ' . $table); $_SESSION['error'] = 'Invalid table provided to ComponentsModel::collection, ' . htmlentities($table); @@ -1109,6 +1109,26 @@ public function upsert(string $table = '', object $device = null, array $data = } } } + if (empty($virtual_machine->icon) and !empty($virtual_machine->os)) { + if (stripos($virtual_machine->os, 'red hat') !== false) { + $virtual_machine->icon = 'redhat'; + } + if (stripos($virtual_machine->os, 'debian') !== false) { + $virtual_machine->icon = 'debian'; + } + if (stripos($virtual_machine->os, 'centos') !== false) { + $virtual_machine->icon = 'centos'; + } + if (stripos($virtual_machine->os, 'ubuntu') !== false) { + $virtual_machine->icon = 'ubuntu'; + } + if (stripos($virtual_machine->os, 'windows') !== false) { + $virtual_machine->icon = 'windows'; + } + if (empty($virtual_machine->icon) and stripos($virtual_machine->os, 'linux') !== false) { + $virtual_machine->icon = 'linux'; + } + } } } @@ -1277,7 +1297,7 @@ public function upsert(string $table = '', object $device = null, array $data = } $alert_details = substr($alert_details, 0, -2); $alert_details = "Item added to {$table} - {$alert_details}"; - $sql = 'INSERT INTO change_log (device_id, db_table, db_row, db_action, details, `timestamp`) VALUES (?, ?, ?, ?, ?, ?)'; + $sql = 'INSERT INTO change_log (device_id, db_table, db_row, db_action, details, `timestamp`, `notes`) VALUES (?, ?, ?, ?, ?, ?, "")'; $query = $this->db->query($sql, [intval($device->id), "{$table}", intval($id), 'create', "{$alert_details}", "{$device->last_seen}"]); // add a count to our chart table $sql = "INSERT INTO chart (`when`, `what`, `org_id`, `count`) VALUES (DATE(NOW()), '{$table}_create', " . intval($device->org_id) . ', 1) ON DUPLICATE KEY UPDATE `count` = `count` + 1'; @@ -1384,7 +1404,7 @@ public function upsert(string $table = '', object $device = null, array $data = } $alert_details = substr($alert_details, 0, -2); $alert_details = "Item removed from {$table} - {$alert_details}"; - $sql = 'INSERT INTO change_log (device_id, db_table, db_row, db_action, details, `timestamp`) VALUES (?, ?, ?, ?, ?, ?)'; + $sql = 'INSERT INTO change_log (device_id, db_table, db_row, db_action, details, `timestamp`, `notes`) VALUES (?, ?, ?, ?, ?, ?, "")'; $query = $this->db->query($sql, [intval($device->id), "{$table}", intval($db_item->id), 'delete', "{$alert_details}", "{$device->last_seen}"]); // add a count to our chart table $sql = "INSERT INTO chart (`when`, `what`, `org_id`, `count`) VALUES (DATE(NOW()), '{$table}_delete', " . intval($device->org_id) . ', 1) ON DUPLICATE KEY UPDATE `count` = `count` + 1'; diff --git a/app/Models/DevicesModel.php b/app/Models/DevicesModel.php index 61d89a752..610903c5c 100644 --- a/app/Models/DevicesModel.php +++ b/app/Models/DevicesModel.php @@ -213,7 +213,7 @@ public function create($data = null): ?int // Set the device icon reset_icons($id); - $sql = "INSERT INTO change_log VALUES (null, ?, 'devices', ?, 'create', 'Item added to devices', null, '2000-01-01 00:00:00', '', '', '', null, '', NOW())"; + $sql = "INSERT INTO change_log VALUES (null, ?, 'devices', ?, 'create', 'Item added to devices', '', '2000-01-01 00:00:00', '', '', '', null, '', NOW())"; $this->db->query($sql, [$id, $id]); $weight = weight($data->last_seen_by); @@ -356,7 +356,7 @@ public function includedCollection(): array $orgs = array_unique(array_merge($instance->user->orgs, $instance->orgsModel->getUserDescendants($instance->user->orgs, $instance->orgs))); $included = array(); - // No file, radio, san, scsi, usb + // No executable, file, radio, san, scsi, usb $current = array('audit_log', 'bios', 'change_log', 'disk', 'dns', 'edit_log', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'route', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'); foreach ($current as $table) { @@ -387,7 +387,7 @@ public function includedRead(int $id = 0): array } $include = array(); - $current = array('bios', 'certificate', 'disk', 'dns', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'); + $current = array('bios', 'certificate', 'disk', 'dns', 'executable', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows'); foreach ($current as $table) { if (empty($resp_include) or in_array($table, $resp_include)) { $sql = "SELECT * FROM `$table` WHERE device_id = ? and current = 'y'"; diff --git a/app/Models/DiscoveriesModel.php b/app/Models/DiscoveriesModel.php index 3df5591fa..ab62f02d8 100644 --- a/app/Models/DiscoveriesModel.php +++ b/app/Models/DiscoveriesModel.php @@ -550,7 +550,11 @@ public function includedRead(int $id = 0): array $sql = "SELECT * FROM discovery_log WHERE discovery_id = ? ORDER BY id"; $query = $this->db->query($sql, [$id]); - $included['discovery_log'] = $query->getResult(); + $discovery_log = $query->getResult(); + foreach ($discovery_log as $log) { + $log->ip_padded = ip_address_to_db($log->ip); + } + $included['discovery_log'] = $discovery_log; $discovery_scan_optionsModel = new \App\Models\DiscoveryScanOptionsModel(); $included['discovery_scan_options'] = $discovery_scan_optionsModel->listUser(); diff --git a/app/Models/DiscoveryLogModel.php b/app/Models/DiscoveryLogModel.php index 27bbac954..be1e34828 100644 --- a/app/Models/DiscoveryLogModel.php +++ b/app/Models/DiscoveryLogModel.php @@ -158,7 +158,6 @@ public function create($data = null): ?int $this->builder->insert($newdata); $id = intval($this->db->insertID()); - // TODO - enable // If we are a collector, forward the log if (!empty($instance->config->servers) and !empty($instance->config->servers->type) and $instance->config->servers->type === 'collector') { $log = $newdata; diff --git a/app/Models/ExecutablesModel.php b/app/Models/ExecutablesModel.php new file mode 100644 index 000000000..cb62b4e2e --- /dev/null +++ b/app/Models/ExecutablesModel.php @@ -0,0 +1,252 @@ +db = db_connect(); + $this->builder = $this->db->table('executables'); + # Use the below to execute BaseModel::__construct + # parent::__construct(); + } + + /** + * Read the collection from the database + * + * @param $resp object An object containing the properties, filter, sort and limit as passed by the user + * + * @return array An array of formatted entries + */ + public function collection(object $resp): array + { + $properties = $resp->meta->properties; + $properties[] = "orgs.name as `orgs.name`"; + $properties[] = "orgs.id as `orgs.id`"; + $this->builder->select($properties, false); + $this->builder->join('orgs', $resp->meta->collection . '.org_id = orgs.id', 'left'); + foreach ($resp->meta->filter as $filter) { + if (in_array($filter->operator, ['!=', '>=', '<=', '=', '>', '<'])) { + $this->builder->{$filter->function}($filter->name . ' ' . $filter->operator, $filter->value); + } else { + $this->builder->{$filter->function}($filter->name, $filter->value); + } + } + $this->builder->orderBy($resp->meta->sort); + $this->builder->limit($resp->meta->limit, $resp->meta->offset); + $query = $this->builder->get(); + if ($this->sqlError($this->db->error())) { + return array(); + } + return format_data($query->getResult(), $resp->meta->collection); + } + + /** + * Create an individual item in the database + * + * @param object $data The data attributes + * + * @return int|false The Integer ID of the newly created item, or false + */ + public function create($data = null): ?int + { + if (empty($data)) { + return null; + } + $data->path = str_replace("'", '', $data->path); + $data->path = str_replace('"', '', $data->path); + $data->path = str_replace(';', '', $data->path); + $data->path = str_replace("\n", '', $data->path); + $data = $this->createFieldData('executables', $data); + if (empty($data)) { + return null; + } + $this->builder->insert($data); + if ($error = $this->sqlError($this->db->error())) { + \Config\Services::session()->setFlashdata('error', json_encode($error)); + return null; + } + return (intval($this->db->insertID())); + } + + /** + * Delete an individual item from the database, by ID + * + * @param int $id The ID of the requested item + * + * @return bool true || false depending on success + */ + public function delete($id = null, bool $purge = false): bool + { + $this->builder->delete(['id' => intval($id)]); + if ($this->sqlError($this->db->error())) { + return false; + } + if ($this->db->affectedRows() !== 1) { + return false; + } + return true; + } + + /** + * Return an array containing arrays of related items to be stored in resp->included + * + * @param int $id The ID of the requested item + * @return array An array of anything needed for screen output + */ + public function includedRead(int $id = 0): array + { + return array(); + } + + /** + * Return an array containing arrays of related items to be stored in resp->included + * + * @param int $id The ID of the requested item + * @return array An array of anything needed for screen output + */ + public function includedCreateForm(int $id = 0): array + { + return array(); + } + + + /** + * Read the entire collection from the database that the user is allowed to read + * + * @return array An array of formatted entries + */ + public function listUser($where = array(), $orgs = array()): array + { + if (empty($orgs)) { + $instance = & get_instance(); + $orgs = array_unique(array_merge($instance->user->orgs, $instance->orgsModel->getUserDescendants($instance->user->orgs, $instance->orgs))); + $orgs = array_unique(array_merge($orgs, $instance->orgsModel->getUserAscendants($instance->user->orgs, $instance->orgs))); + $orgs[] = 1; + $orgs = array_unique($orgs); + } + + $properties = array(); + $properties[] = 'executables.*'; + $properties[] = 'orgs.name as `orgs.name`'; + $this->builder->select($properties, false); + $this->builder->join('orgs', 'executables.org_id = orgs.id', 'left'); + $this->builder->whereIn('orgs.id', $orgs); + $this->builder->where($where); + $query = $this->builder->get(); + if ($this->sqlError($this->db->error())) { + return array(); + } + return format_data($query->getResult(), 'executables'); + } + + /** + * Read the entire collection from the database + * + * @return array An array of all entries + */ + public function listAll(): array + { + $query = $this->builder->get(); + if ($this->sqlError($this->db->error())) { + return array(); + } + return $query->getResult(); + } + + /** + * Read an individual item from the database, by ID + * + * @param int $id The ID of the requested item + * + * @return array The array containing the requested item + */ + public function read(int $id = 0): array + { + $query = $this->builder->getWhere(['id' => intval($id)]); + if ($this->sqlError($this->db->error())) { + return array(); + } + return format_data($query->getResult(), 'executables'); + } + + /** + * Reset a table + * + * @return bool Did it work or not? + */ + public function reset(string $table = ''): bool + { + if ($this->tableReset('executables')) { + return true; + } + return false; + } + + /** + * Update an individual item in the database + * + * @param object $data The data attributes + * + * @return bool true || false depending on success + */ + public function update($id = null, $data = null): bool + { + $data = $this->updateFieldData('executables', $data); + $this->builder->where('id', intval($id)); + $this->builder->update($data); + if ($this->sqlError($this->db->error())) { + return false; + } + return true; + } + + /** + * The dictionary item + * + * @return object The stdClass object containing the dictionary + */ + public function dictionary(): object + { + $instance = & get_instance(); + + $collection = 'executables'; + $dictionary = new stdClass(); + $dictionary->table = $collection; + $dictionary->columns = new stdClass(); + + $dictionary->attributes = new stdClass(); + $dictionary->attributes->collection = array('id', 'name', 'description', 'path', 'exclude', 'orgs.name'); + $dictionary->attributes->create = array('name','org_id','path','exclude'); + $dictionary->attributes->fields = $this->db->getFieldNames($collection); + $dictionary->attributes->fieldsMeta = $this->db->getFieldData($collection); + $dictionary->attributes->update = $this->updateFields($collection); + + $dictionary->sentence = 'Open-AudIT Enterprise includes Executables, which detects executable files not know by the package manager. This feature is for Linux targets only.'; + + $dictionary->about = '

Open-AudIT can retrieve details about a file, ask the native package manager if they are known to it and monitor these files for changes as per other attributes in the Open-AudIT database.

Supported clients are Linux only.

' . $instance->dictionary->link . '

'; + + $dictionary->notes = '

Supported clients are Linux only.

'; + + + $dictionary->product = 'enterprise'; + $dictionary->columns->id = $instance->dictionary->id; + $dictionary->columns->name = $instance->dictionary->name; + $dictionary->columns->org_id = $instance->dictionary->org_id; + $dictionary->columns->description = $instance->dictionary->description; + $dictionary->columns->path = 'The path to the file or directory.'; + $dictionary->columns->os_family = 'Unused as at 5.2.0.'; + $dictionary->columns->exclude = 'Should this file (or pattern) be used to exclude files from being reported.'; + $dictionary->columns->edited_by = $instance->dictionary->edited_by; + $dictionary->columns->edited_date = $instance->dictionary->edited_date; + return $dictionary; + } +} diff --git a/app/Models/ScriptsModel.php b/app/Models/ScriptsModel.php index 86faaf2a6..3e3cbf4cd 100644 --- a/app/Models/ScriptsModel.php +++ b/app/Models/ScriptsModel.php @@ -358,7 +358,12 @@ public function download(int $id = 0): ?string if (!empty($instance->config->default_network_address)) { $options->url = $instance->config->default_network_address . 'index.php/input/devices'; } else { - unset($options->url); + $baseURL = base_url(); + if (!empty($baseURL)) { + $options->url = $baseURL . 'index.php/input/devices'; + } else { + unset($options->url); + } } } $find = 'Configuration from web UI here'; @@ -405,6 +410,30 @@ public function download(int $id = 0): ?string } } + if (!empty($instance->config->executables) and $instance->config->executables and $instance->config->product === 'enterprise') { + if ($data->based_on === 'audit_linux.sh') { + $sql = "SELECT * FROM executables"; + $result = $this->db->query($sql)->getResult(); + $exclusions = array(); + if (!empty($result)) { + foreach ($result as $item) { + $path = str_replace('\\', '\\\\', $item->path); + if ($item->exclude === 'n') { + $replace = $find . "\nexecutables[" . ($item->id + 1) . ']="' . $path . '"'; + $file = str_replace($find, $replace, $file); + } + if ($item->exclude === 'y') { + $exclusions[] = $path; + } + } + } + if (!empty($exclusions)) { + $replace = $find . "\nexclusions=\"" . implode('|', $exclusions) . "\""; + $file = str_replace($find, $replace, $file); + } + } + } + // Force all line endings to be Unix style // Windows audit scripts with Unix line endings work // Unix audit scripts with Windows line endings do not work (bash for one, chokes) diff --git a/app/Models/TasksModel.php b/app/Models/TasksModel.php index c1b82268d..478778b59 100644 --- a/app/Models/TasksModel.php +++ b/app/Models/TasksModel.php @@ -90,6 +90,15 @@ public function create($data = null): ?int if (empty($data)) { return null; } + $data->minute = implode(',', $data->minute); + $data->hour = implode(',', $data->hour); + $data->month = implode(',', $data->month); + $data->day_of_month = implode(',', $data->day_of_month); + $data->day_of_week = implode(',', $data->day_of_week); + if (empty($data->uuid)) { + $instance = & get_instance(); + $data->uuid = $instance->config->uuid; + } $data = $this->createFieldData('tasks', $data); if (empty($data)) { return null; diff --git a/app/Models/db_upgrades/db_5.2.0.php b/app/Models/db_upgrades/db_5.2.0.php index 9ad67403a..0325e7b11 100644 --- a/app/Models/db_upgrades/db_5.2.0.php +++ b/app/Models/db_upgrades/db_5.2.0.php @@ -1,6 +1,32 @@ query($sql); +$output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; +log_message('info', (string)$db->getLastQuery()); + +if ($db->fieldExists('user_id', 'change_log')) { + $sql = "ALTER TABLE `change_log` DROP `user_id`"; + $db->query($sql); + $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; + log_message('info', (string)$db->getLastQuery()); +} + +if (!$db->fieldExists('ack_by', 'change_log')) { + $sql = "ALTER TABLE `change_log` ADD `ack_by` varchar(200) NOT NULL DEFAULT '' AFTER `details`"; + $db->query($sql); + $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; + log_message('info', (string)$db->getLastQuery()); +} + +if (!$db->fieldExists('notes', 'change_log') and $db->fieldExists('note', 'change_log')) { + $sql = "ALTER TABLE `change_log` CHANGE `note` `notes` TEXT NOT NULL"; + $db->query($sql); + $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; + log_message('info', (string)$db->getLastQuery()); +} + $sql = "DELETE FROM `configuration` WHERE `name` IN ('product', 'oae_product')"; $db->query($sql); $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; @@ -16,6 +42,93 @@ $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; log_message('info', (string)$db->getLastQuery()); +$sql = "ALTER TABLE `discovery_log` CHANGE `timestamp` `timestamp` datetime DEFAULT current_timestamp()"; +$db->query($sql); +$output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; +log_message('info', (string)$db->getLastQuery()); + +$sql = "ALTER TABLE `enterprise` CHANGE `response` `response` mediumtext NOT NULL DEFAULT ''"; +$db->query($sql); +$output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; +log_message('info', (string)$db->getLastQuery()); + +if (!$db->tableExists('executables')) { + $sql = "CREATE TABLE `executables` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(200) NOT NULL DEFAULT '', + `org_id` int(10) unsigned NOT NULL DEFAULT '1', + `path` text NOT NULL, + `description` text NOT NULL, + `os_family` varchar(50) NOT NULL DEFAULT '', + `exclude` enum('y', 'n') NOT NULL DEFAULT 'n', + `edited_by` varchar(200) NOT NULL DEFAULT '', + `edited_date` datetime NOT NULL DEFAULT '2000-01-01 00:00:00', + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;"; + $db->query($sql); + $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; + log_message('info', (string)$db->getLastQuery()); +} + +if (!$db->tableExists('executable')) { + $sql = " CREATE TABLE `executable` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `device_id` int(10) unsigned DEFAULT NULL, + `current` enum('y','n') NOT NULL DEFAULT 'y', + `first_seen` datetime NOT NULL DEFAULT '2000-01-01 00:00:00', + `last_seen` datetime NOT NULL DEFAULT '2000-01-01 00:00:00', + `executable_id` int(10) unsigned DEFAULT NULL, + `name` varchar(200) NOT NULL DEFAULT '', + `full_name` text NOT NULL, + `description` varchar(1000) NOT NULL, + `package` varchar(1000) NOT NULL, + `size` int(10) unsigned NOT NULL DEFAULT '0', + `directory` text NOT NULL, + `hash` varchar(250) NOT NULL DEFAULT '', + `last_changed` varchar(100) NOT NULL DEFAULT '', + `meta_last_changed` varchar(100) NOT NULL DEFAULT '', + `permission` varchar(250) NOT NULL DEFAULT '', + `owner` varchar(100) NOT NULL DEFAULT '', + `group` varchar(100) NOT NULL DEFAULT '', + `type` varchar(100) NOT NULL DEFAULT '', + `version` varchar(100) NOT NULL DEFAULT '', + `inode` bigint(20) unsigned NOT NULL DEFAULT '0', + `ack_by` varchar(200) NOT NULL DEFAULT '', + `ack_date` datetime NOT NULL DEFAULT '2000-01-01 00:00:00', + `notes` text NOT NULL, + PRIMARY KEY (`id`), + KEY `system_id` (`device_id`), + KEY `name` (`name`), + CONSTRAINT `executable_system_id` FOREIGN KEY (`device_id`) REFERENCES `devices` (`id`) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci"; + $db->query($sql); + $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; + log_message('info', (string)$db->getLastQuery()); +} + +$sql = "ALTER TABLE `partition` CHANGE `mount_point` `mount_point` VARCHAR(200) NOT NULL DEFAULT ''"; +$db->query($sql); +$output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; +log_message('info', (string)$db->getLastQuery()); + +$sql = "SELECT * FROM `roles`"; +$roles = $db->query($sql)->getResult(); +$output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n"; +log_message('info', (string)$db->getLastQuery()); + +foreach ($roles as $role) { + if ($role->name === 'org_admin' or $role->name === 'user') { + $permissions = json_decode($role->permissions); + if ($role->name === 'org_admin') { + $permissions->executables = 'crud'; + } + if ($role->name === 'user') { + $permissions->executable = 'r'; + } + $this->rolesModel->update(intval($role->id), $permissions); + } +} + // set our versions $sql = "UPDATE `configuration` SET `value` = '20240512' WHERE `name` = 'internal_version'"; $db->query($sql); diff --git a/app/Views/componentsRead.php b/app/Views/componentsRead.php index b17e083f5..2b376a4fe 100644 --- a/app/Views/componentsRead.php +++ b/app/Views/componentsRead.php @@ -30,6 +30,9 @@ } else if ($data[0]->type === 'policy' and $key === 'options') { $resource->{$key} = html_entity_decode($resource->{$key}); echo read_text_box($key, $resource->{$key}); + } else if ($data[0]->type === 'change_log' and $key === 'db_row') { + $link = ""; + echo read_field($key, $resource->{$key}, '', false, $label, $link); } else { $label = ''; if ($key === 'id') { diff --git a/app/Views/configurationRead.php b/app/Views/configurationRead.php index 74d29fcff..a11280bb3 100644 --- a/app/Views/configurationRead.php +++ b/app/Views/configurationRead.php @@ -19,7 +19,7 @@ editable, $dictionary->columns->editable, false) ?> type, $dictionary->columns->type, false) ?> type !== 'bool') { ?> - value, $dictionary->columns->value, $update, '', '', '', $resource->type) ?> + value), $dictionary->columns->value, $update, '', '', '', $resource->type) ?> type === 'bool') { ?> value, $dictionary->columns->value, $update, '', array()) ?> diff --git a/app/Views/devicesRead.php b/app/Views/devicesRead.php index c5ad4e4ec..4851e9afe 100644 --- a/app/Views/devicesRead.php +++ b/app/Views/devicesRead.php @@ -126,7 +126,7 @@ + +