WIP rcmd in H&D

This commit is contained in:
fbsanchez 2020-04-30 15:00:25 +02:00
parent 026562e7ee
commit 900e25eef1
3 changed files with 185 additions and 4 deletions

View File

@ -491,6 +491,7 @@ class HostDevices extends Wizard
$parent_recursion = get_parameter_switch('parent_recursion'); $parent_recursion = get_parameter_switch('parent_recursion');
$vlan_enabled = get_parameter_switch('vlan_enabled'); $vlan_enabled = get_parameter_switch('vlan_enabled');
$wmi_enabled = get_parameter_switch('wmi_enabled'); $wmi_enabled = get_parameter_switch('wmi_enabled');
$rcmd_enabled = get_parameter_switch('rcmd_enabled');
$resolve_names = get_parameter_switch('resolve_names'); $resolve_names = get_parameter_switch('resolve_names');
$snmp_version = get_parameter('snmp_version', null); $snmp_version = get_parameter('snmp_version', null);
$community = get_parameter('community', null); $community = get_parameter('community', null);
@ -538,6 +539,7 @@ class HostDevices extends Wizard
$this->task['parent_recursion'] = $parent_recursion; $this->task['parent_recursion'] = $parent_recursion;
$this->task['vlan_enabled'] = $vlan_enabled; $this->task['vlan_enabled'] = $vlan_enabled;
$this->task['wmi_enabled'] = $wmi_enabled; $this->task['wmi_enabled'] = $wmi_enabled;
$this->task['rcmd_enabled'] = $rcmd_enabled;
$this->task['resolve_names'] = $resolve_names; $this->task['resolve_names'] = $resolve_names;
$this->task['snmp_version'] = $snmp_version; $this->task['snmp_version'] = $snmp_version;
$this->task['snmp_auth_user'] = $snmp_auth_user; $this->task['snmp_auth_user'] = $snmp_auth_user;

View File

@ -276,6 +276,9 @@ sub data_consumer ($$) {
task_id => $task->{'id_rt'}, task_id => $task->{'id_rt'},
vlan_cache_enabled => $task->{'vlan_enabled'}, vlan_cache_enabled => $task->{'vlan_enabled'},
wmi_enabled => $task->{'wmi_enabled'}, wmi_enabled => $task->{'wmi_enabled'},
rcmd_enabled => $task->{'rcmd_enabled'},
rcmd_timeout => $pa_config->{'rcmd_timeout'},
rcmd_timeout_bin => $pa_config->{'rcmd_timeout_bin'},
auth_strings_array => \@auth_strings, auth_strings_array => \@auth_strings,
autoconfiguration_enabled => $task->{'autoconfiguration_enabled'}, autoconfiguration_enabled => $task->{'autoconfiguration_enabled'},
main_event_id => $main_event, main_event_id => $main_event,
@ -402,6 +405,8 @@ sub exec_recon_script ($$$) {
sub PandoraFMS::Recon::Base::guess_os($$) { sub PandoraFMS::Recon::Base::guess_os($$) {
my ($self, $device) = @_; my ($self, $device) = @_;
return $self->{'os_id'}{$device} if defined($self->{'os_id'}{$device});
$DEVNULL = '/dev/null' if (!defined($DEVNULL)); $DEVNULL = '/dev/null' if (!defined($DEVNULL));
$DEVNULL = '/NUL' if ($^O =~ /win/i && !defined($DEVNULL)); $DEVNULL = '/NUL' if ($^O =~ /win/i && !defined($DEVNULL));
@ -510,6 +515,9 @@ sub PandoraFMS::Recon::Base::test_module($$) {
) { ) {
# Generic, plugins. (21-23 ASYNC) # Generic, plugins. (21-23 ASYNC)
if ($test->{'id_modulo'} == 6) { if ($test->{'id_modulo'} == 6) {
return 0 unless $self->wmi_responds($addr);
# WMI commands. # WMI commands.
$value = $self->call( $value = $self->call(
'wmi_get_value', 'wmi_get_value',
@ -527,9 +535,31 @@ sub PandoraFMS::Recon::Base::test_module($$) {
} elsif ($test->{'id_tipo_modulo'} >= 34 && $test->{'id_tipo_modulo'} <= 37) { } elsif ($test->{'id_tipo_modulo'} >= 34 && $test->{'id_tipo_modulo'} <= 37) {
# Remote command. # Remote command.
# XXX TODO: Test remote commands. return 0 unless $self->rcmd_responds($addr);
# Disabled until we can ensure result.
return 0; my $target_os = pandora_get_os($self->{'dbh'}, $test->{'custom_string_2'});
$value = enterprise_hook(
'remote_execution_module',
[
# pa_config,
$self->{'pa_config'},
# dbh,
$self->{'dbh'},
# module,
$test,
# target_os,
$target_os,
# ip_target,
$test->{'ip_target'},
# tcp_port
$test->{'tcp_port'}
]
);
chomp($value);
return 0 unless defined($value);
} elsif ($test->{'id_tipo_modulo'} >= 8 && $test->{'id_tipo_modulo'} <= 11) { } elsif ($test->{'id_tipo_modulo'} >= 8 && $test->{'id_tipo_modulo'} <= 11) {
# TCP # TCP
@ -917,6 +947,15 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) {
$component->{'plugin_pass'} = $self->{'snmp_auth_pass'}; $component->{'plugin_pass'} = $self->{'snmp_auth_pass'};
} }
if ($component->{'type'} >= 34 && $component->{'type'} <= 37) {
# Update module credentials.
$component->{'custom_string_1'} = $self->rcmd_credentials_key($device);
$component->{'custom_string_2'} = pandora_get_os_by_id(
$self->{'dbh'},
$self->guess_os($device)
);
}
$component->{'__module_component'} = 1; $component->{'__module_component'} = 1;
# 3. Try to register module into monitoring list. # 3. Try to register module into monitoring list.
@ -1012,7 +1051,10 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) {
|| $force_creation || $force_creation
) { ) {
my $parent_id; my $parent_id;
my $os_id = $self->guess_os($data->{'agent'}{'direccion'}); my $os_id = $data->{'agent'}{'id_os'};
if (is_empty($os_id)) {
$os_id = $self->guess_os($data->{'agent'}{'direccion'});
}
$self->call('message', "Agent accepted: ".$data->{'agent'}{'nombre'}, 5); $self->call('message', "Agent accepted: ".$data->{'agent'}{'nombre'}, 5);
@ -1337,6 +1379,9 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) {
next if is_empty($label); next if is_empty($label);
# Retrieve target agent OS version.
$self->{'agents_found'}->{$addr}{'agent'}{'id_os'} = $self->guess_os($addr);
$self->call('update_progress', $progress); $self->call('update_progress', $progress);
$progress += $step; $progress += $step;
# Store temporally. Wait user approval. # Store temporally. Wait user approval.

View File

@ -160,6 +160,12 @@ sub new {
# Globally enable/disable WMI scans. # Globally enable/disable WMI scans.
wmi_enabled => 0, wmi_enabled => 0,
# Globally enable/disable RCMD scans.
rcmd_enabled => 0,
rcmd_timeout => 4,
rcmd_timeout_bin => '/usr/bin/timeout',
auth_strings_array => [], auth_strings_array => [],
wmi_timeout => 3, wmi_timeout => 3,
timeout_cmd => '', timeout_cmd => '',
@ -1429,6 +1435,12 @@ sub test_capabilities($$) {
# Add wmi scan if enabled. # Add wmi scan if enabled.
$self->wmi_discovery($addr); $self->wmi_discovery($addr);
} }
# WMI discovery.
if (is_enabled($self->{'rcmd_enabled'})) {
# Add wmi scan if enabled.
$self->rcmd_discovery($addr);
}
} }
################################################################################ ################################################################################
@ -2268,6 +2280,105 @@ sub wmi_credentials_calculation {
return undef; return undef;
} }
################################################################################
# Returns the credentials with which the host responds to WMI queries or
# undef if it does not respond to WMI.
################################################################################
sub rcmd_credentials {
my ($self, $target) = @_;
return $self->{'rcmd_auth'}{$target};
}
################################################################################
# Returns the credentials KEY with which the host responds to WMI queries or
# undef if it does not respond to WMI.
################################################################################
sub rcmd_credentials_key {
my ($self, $target) = @_;
return $self->{'rcmd_auth_key'}{$target};
}
################################################################################
# Calculate WMI credentials for target, 1 if calculated, undef if cannot
# connect to target. Credentials could be empty (-N)
################################################################################
sub rcmd_credentials_calculation {
my ($self, $target) = @_;
my $rcmd = PandoraFMS::Recon::Util::enterprise_new(
'PandoraFMS::RemoteCmd',[{
'psexec' => $self->{'parent'}->{'pa_config'}->{'psexec'},
'winexe' => $self->{'parent'}->{'pa_config'}->{'winexe'},
'plink' => $self->{'parent'}->{'pa_config'}->{'plink'}
}]
);
if (!$rcmd) {
# Library not available.
$self->call('message', "PandoraFMS::RemoteCmd library not available", 10);
return undef;
}
my $id_os = $self->call('guess_os', $target);
$rcmd->set_host($target);
$rcmd->set_os($id_os);
# Test all credentials selected.
foreach my $key_index (@{$self->{'auth_strings_array'}}) {
my $cred = $self->call('get_credentials', $key_index);
next if ref($cred) ne 'HASH';
$rcmd->clean_ssh_lib();
my $username;
my $domain;
if($cred->{'username'} =~ /^(.*?)\\(.*)$/) {
$domain = $1;
$username = $2;
} else {
$username = $cred->{'username'};
}
$rcmd->set_credentials(
{
'user' => $username,
'pass' => $cred->{'password'},
'domain' => $domain
}
);
$rcmd->set_timeout(
$self->{'rcmd_timeout_bin'},
$self->{'rcmd_timeout'}
);
my $result;
eval {
$result = $rcmd->rcmd('echo 1');
chomp($result);
my $out = '';
$out = $result if !is_empty($result);
$self->call('message', "Trying [".$key_index."] in [". $target."] [".$id_os."]: [$out]", 10);
};
if ($@) {
$self->call('message', "Failed while trying [".$key_index."] in [". $target."] [".$id_os."]:" . @_, 10);
}
if (!is_empty($result) && $result == "1") {
$self->{'rcmd_auth'}{$target} = $cred;
$self->{'rcmd_auth_key'}{$target} = $key_index;
$self->{'rcmd'}{$target} = 1;
$self->{'summary'}->{'RCMD'} += 1;
$self->call('message', "RCMD available for $target", 10);
return 1;
}
}
# Not found.
return 0;
}
################################################################################ ################################################################################
# Tests wmi capability for addr. # Tests wmi capability for addr.
################################################################################ ################################################################################
@ -2282,6 +2393,20 @@ sub wmi_discovery {
} }
################################################################################
# Tests credentials against addr.
################################################################################
sub rcmd_discovery {
my ($self, $addr) = @_;
# Initialization.
$self->{'rcmd'} = {} unless ref($self->{'rcmd'}) eq 'HASH';
# Calculate credentials.
$self->rcmd_credentials_calculation($addr);
}
################################################################################ ################################################################################
# Extra: WMI imported methods. DO NOT EXPORT TO AVOID DOUBLE DEF. # Extra: WMI imported methods. DO NOT EXPORT TO AVOID DOUBLE DEF.
################################################################################ ################################################################################
@ -2371,6 +2496,15 @@ sub wmi_responds {
return 0; return 0;
} }
################################################################################
# Checks if target is reachable using rcmd.
################################################################################
sub rcmd_responds {
my ($self, $target) = @_;
return 1 if is_enabled($self->{'rcmd'}{$target});
return 0;
}
################################################################################ ################################################################################
# Performs a WMI request and returns the requested column of the first row. # Performs a WMI request and returns the requested column of the first row.
# Returns undef on error. # Returns undef on error.