Skip to content

Commit

Permalink
Add: Kerberos credential for targets
Browse files Browse the repository at this point in the history
Targets now have the krb5_credential element that can be used to pass
Kerberos 5 credentials to the scanner for authenticated scans.

This allows scans of Windows systems that no longer allow the old SMB
authentication method.
  • Loading branch information
timopollmeier committed Dec 2, 2024
1 parent 2d79e64 commit b34dbad
Show file tree
Hide file tree
Showing 6 changed files with 413 additions and 9 deletions.
135 changes: 134 additions & 1 deletion src/gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,7 @@ typedef struct
char *esxi_credential_id; ///< ESXi credential for new target.
char *esxi_lsc_credential_id; ///< ESXi credential (deprecated).
char *snmp_credential_id; ///< SNMP credential for new target.
char *krb5_credential_id; ///< Kerberos 5 credential for new target.
char *name; ///< Name of new target.
} create_target_data_t;

Expand Down Expand Up @@ -982,6 +983,7 @@ create_target_data_reset (create_target_data_t *data)
free (data->esxi_credential_id);
free (data->esxi_lsc_credential_id);
free (data->snmp_credential_id);
free (data->krb5_credential_id);
free (data->name);

memset (data, 0, sizeof (create_target_data_t));
Expand Down Expand Up @@ -2883,6 +2885,7 @@ typedef struct
char *esxi_credential_id; ///< ESXi credential for target.
char *esxi_lsc_credential_id; ///< ESXi credential for target (deprecated).
char *snmp_credential_id; ///< SNMP credential for target.
char *krb5_credential_id; ///< Kerberos 5 credential for target.
char *target_id; ///< Target UUID.
} modify_target_data_t;

Expand Down Expand Up @@ -2913,6 +2916,7 @@ modify_target_data_reset (modify_target_data_t *data)
free (data->esxi_credential_id);
free (data->esxi_lsc_credential_id);
free (data->snmp_credential_id);
free (data->krb5_credential_id);
free (data->target_id);

memset (data, 0, sizeof (modify_target_data_t));
Expand Down Expand Up @@ -4295,6 +4299,7 @@ typedef enum
CLIENT_CREATE_TARGET_NAME,
CLIENT_CREATE_TARGET_PORT_LIST,
CLIENT_CREATE_TARGET_PORT_RANGE,
CLIENT_CREATE_TARGET_KRB5_CREDENTIAL,
CLIENT_CREATE_TARGET_SMB_CREDENTIAL,
CLIENT_CREATE_TARGET_SNMP_CREDENTIAL,
CLIENT_CREATE_TARGET_SSH_CREDENTIAL,
Expand Down Expand Up @@ -4532,6 +4537,7 @@ typedef enum
CLIENT_MODIFY_TARGET_REVERSE_LOOKUP_UNIFY,
CLIENT_MODIFY_TARGET_NAME,
CLIENT_MODIFY_TARGET_PORT_LIST,
CLIENT_MODIFY_TARGET_KRB5_CREDENTIAL,
CLIENT_MODIFY_TARGET_SMB_CREDENTIAL,
CLIENT_MODIFY_TARGET_SNMP_CREDENTIAL,
CLIENT_MODIFY_TARGET_SSH_CREDENTIAL,
Expand Down Expand Up @@ -6636,6 +6642,12 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context,
&modify_target_data->port_list_id);
set_client_state (CLIENT_MODIFY_TARGET_PORT_LIST);
}
else if (strcasecmp ("KRB5_CREDENTIAL", element_name) == 0)
{
append_attribute (attribute_names, attribute_values, "id",
&modify_target_data->krb5_credential_id);
set_client_state (CLIENT_MODIFY_TARGET_KRB5_CREDENTIAL);
}
else if (strcasecmp ("SSH_CREDENTIAL", element_name) == 0)
{
append_attribute (attribute_names, attribute_values, "id",
Expand Down Expand Up @@ -7647,6 +7659,12 @@ gmp_xml_handle_start_element (/* unused */ GMarkupParseContext* context,
gvm_append_string (&create_target_data->port_range, "");
set_client_state (CLIENT_CREATE_TARGET_PORT_RANGE);
}
else if (strcasecmp ("KRB5_CREDENTIAL", element_name) == 0)
{
append_attribute (attribute_names, attribute_values, "id",
&create_target_data->krb5_credential_id);
set_client_state (CLIENT_CREATE_TARGET_KRB5_CREDENTIAL);
}
else if (strcasecmp ("SSH_CREDENTIAL", element_name) == 0)
{
append_attribute (attribute_names, attribute_values, "id",
Expand Down Expand Up @@ -17862,18 +17880,20 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error)
char *ssh_name, *ssh_uuid, *smb_name, *smb_uuid;
char *esxi_name, *esxi_uuid, *snmp_name, *snmp_uuid;
char *ssh_elevate_name, *ssh_elevate_uuid;
char *krb5_name, *krb5_uuid;
const char *port_list_uuid, *port_list_name, *ssh_port;
const char *hosts, *exclude_hosts, *reverse_lookup_only;
const char *reverse_lookup_unify, *allow_simultaneous_ips;
credential_t ssh_credential, smb_credential;
credential_t esxi_credential, snmp_credential;
credential_t ssh_elevate_credential;
credential_t ssh_elevate_credential, krb5_credential;
int port_list_trash, max_hosts, port_list_available;
int ssh_credential_available;
int smb_credential_available;
int esxi_credential_available;
int snmp_credential_available;
int ssh_elevate_credential_available;
int krb5_credential_available;

ret = get_next (&targets, &get_targets_data->get, &first,
&count, init_target_iterator);
Expand All @@ -17891,6 +17911,7 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error)
snmp_credential = target_iterator_snmp_credential (&targets);
ssh_elevate_credential
= target_iterator_ssh_elevate_credential (&targets);
krb5_credential = target_iterator_krb5_credential (&targets);

ssh_credential_available = 1;
if (ssh_credential)
Expand Down Expand Up @@ -18048,6 +18069,38 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error)
ssh_elevate_uuid = NULL;
}

krb5_credential_available = 1;
if (krb5_credential)
{
if (get_targets_data->get.trash
&& target_iterator_krb5_trash (&targets))
{
krb5_name
= trash_credential_name (krb5_credential);
krb5_uuid
= trash_credential_uuid (krb5_credential);
krb5_credential_available
= trash_credential_readable (krb5_credential);
}
else
{
credential_t found;

krb5_name = credential_name (krb5_credential);
krb5_uuid = credential_uuid (krb5_credential);
if (find_credential_with_permission (krb5_uuid,
&found,
"get_credentials"))
abort ();
krb5_credential_available = (found > 0);
}
}
else
{
krb5_name = NULL;
krb5_uuid = NULL;
}

port_list_uuid = target_iterator_port_list_uuid (&targets);
port_list_name = target_iterator_port_list_name (&targets);
port_list_trash = target_iterator_port_list_trash (&targets);
Expand Down Expand Up @@ -18158,6 +18211,18 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error)
SEND_TO_CLIENT_OR_FAIL ("<permissions/>");

SENDF_TO_CLIENT_OR_FAIL ("</ssh_elevate_credential>"
"<krb5_credential id=\"%s\">"
"<name>%s</name>"
"<trash>%i</trash>",
krb5_uuid ? krb5_uuid : "",
krb5_name ? krb5_name : "",
(get_targets_data->get.trash
&& target_iterator_krb5_trash (&targets)));

if (krb5_credential_available == 0)
SEND_TO_CLIENT_OR_FAIL ("<permissions/>");

SENDF_TO_CLIENT_OR_FAIL ("</krb5_credential>"
"<reverse_lookup_only>"
"%s"
"</reverse_lookup_only>"
Expand Down Expand Up @@ -18215,6 +18280,8 @@ handle_get_targets (gmp_parser_t *gmp_parser, GError **error)
free (esxi_uuid);
free (ssh_elevate_name);
free (ssh_elevate_uuid);
free (krb5_name);
free (krb5_uuid);
}
cleanup_iterator (&targets);
filtered = get_targets_data->get.id
Expand Down Expand Up @@ -22963,6 +23030,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
credential_t ssh_credential = 0, ssh_elevate_credential = 0;
credential_t smb_credential = 0;
credential_t esxi_credential = 0, snmp_credential = 0;
credential_t krb5_credential = 0;
target_t new_target;

if (create_target_data->copy)
Expand Down Expand Up @@ -23139,6 +23207,31 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
return;
}
}
else if (create_target_data->krb5_credential_id
&& find_credential_with_permission
(create_target_data->krb5_credential_id,
&krb5_credential,
"get_credentials"))
SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("create_target"));
else if (create_target_data->krb5_credential_id
&& krb5_credential == 0)
{
if (send_find_error_to_client
("create_target", "Credential",
create_target_data->snmp_credential_id,
gmp_parser))
{
error_send_to_client (error);
return;
}
}
else if (create_target_data->smb_credential_id
&& create_target_data->krb5_credential_id)
SEND_TO_CLIENT_OR_FAIL
(XML_ERROR_SYNTAX ("create_target",
"Targets cannot have both an SMB and"
" Kerberos 5 credential"));

/* Create target from host string. */
else switch (create_target
(create_target_data->name,
Expand All @@ -23156,6 +23249,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
smb_credential,
esxi_credential,
snmp_credential,
krb5_credential,
create_target_data->reverse_lookup_only,
create_target_data->reverse_lookup_unify,
create_target_data->alive_tests,
Expand Down Expand Up @@ -23265,6 +23359,13 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
" different from the SSH credential"));
log_event_fail ("target", "Target", NULL, "created");
break;
case 16:
SEND_TO_CLIENT_OR_FAIL
(XML_ERROR_SYNTAX ("create_target",
"Kerberos 5 credential must be of type"
" 'krb5'"));
log_event_fail ("target", "Target", NULL, "created");
break;
case 99:
SEND_TO_CLIENT_OR_FAIL
(XML_ERROR_SYNTAX ("create_target",
Expand Down Expand Up @@ -23304,6 +23405,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
CLOSE (CLIENT_CREATE_TARGET, NAME);
CLOSE (CLIENT_CREATE_TARGET, PORT_LIST);
CLOSE (CLIENT_CREATE_TARGET, PORT_RANGE);
CLOSE (CLIENT_CREATE_TARGET, KRB5_CREDENTIAL);
CLOSE (CLIENT_CREATE_TARGET, SSH_CREDENTIAL);
CLOSE (CLIENT_CREATE_TARGET, SSH_LSC_CREDENTIAL);
CLOSE (CLIENT_CREATE_TARGET, SSH_ELEVATE_CREDENTIAL);
Expand Down Expand Up @@ -25763,6 +25865,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
? modify_target_data->esxi_credential_id
: modify_target_data->esxi_lsc_credential_id,
modify_target_data->snmp_credential_id,
modify_target_data->krb5_credential_id,
modify_target_data->reverse_lookup_only,
modify_target_data->reverse_lookup_unify,
modify_target_data->alive_tests,
Expand Down Expand Up @@ -26012,6 +26115,35 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
log_event_fail ("target", "Target",
modify_target_data->target_id, "modified");
break;
case 26:
log_event_fail ("target", "Target",
modify_target_data->target_id,
"modified");
if (send_find_error_to_client
("modify_target", "Credential",
modify_target_data->krb5_credential_id,
gmp_parser))
{
error_send_to_client (error);
return;
}
break;
case 27:
SEND_TO_CLIENT_OR_FAIL
(XML_ERROR_SYNTAX ("modify_target",
"Kerberos 5 credential must be of type"
" 'krb5'"));
log_event_fail ("target", "Target",
modify_target_data->target_id, "modified");
break;
case 28:
SEND_TO_CLIENT_OR_FAIL
(XML_ERROR_SYNTAX ("modify_target",
"Targets cannot have both an SMB and"
" Kerberos 5 credential"));
log_event_fail ("target", "Target",
modify_target_data->target_id, "modified");
break;
case 99:
SEND_TO_CLIENT_OR_FAIL
(XML_ERROR_SYNTAX ("modify_target",
Expand Down Expand Up @@ -26051,6 +26183,7 @@ gmp_xml_handle_end_element (/* unused */ GMarkupParseContext* context,
CLOSE (CLIENT_MODIFY_TARGET, HOSTS);
CLOSE (CLIENT_MODIFY_TARGET, NAME);
CLOSE (CLIENT_MODIFY_TARGET, PORT_LIST);
CLOSE (CLIENT_MODIFY_TARGET, KRB5_CREDENTIAL);
CLOSE (CLIENT_MODIFY_TARGET, SSH_CREDENTIAL);
CLOSE (CLIENT_MODIFY_TARGET, SSH_LSC_CREDENTIAL);
CLOSE (CLIENT_MODIFY_TARGET, SSH_ELEVATE_CREDENTIAL);
Expand Down
61 changes: 60 additions & 1 deletion src/manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -2396,6 +2396,61 @@ target_osp_snmp_credential (target_t target)
return NULL;
}

/**
* @brief Get the Kerberos 5 credential of a target as an osp_credential_t
*
* @param[in] target The target to get the credential from.
*
* @return Pointer to a newly allocated osp_credential_t
*/
static osp_credential_t *
target_osp_krb5_credential (target_t target)
{
credential_t credential;
credential = target_credential (target, "krb5");
if (credential)
{
iterator_t iter;
osp_credential_t *osp_credential;

init_credential_iterator_one (&iter, credential);
if (!next (&iter))
{
g_warning ("%s: Kerberos 5 Credential not found.", __func__);
cleanup_iterator (&iter);
return NULL;
}
if (strcmp (credential_iterator_type (&iter), "krb5"))
{
g_warning ("%s: Kerberos 5 Credential not of type 'krb5'.",
__func__);
cleanup_iterator (&iter);
return NULL;
}

osp_credential = osp_credential_new ("up", "krb5", NULL);
osp_credential_set_auth_data (osp_credential,
"username",
credential_iterator_login (&iter)
?: "");
osp_credential_set_auth_data (osp_credential,
"password",
credential_iterator_password (&iter)
?: "");
osp_credential_set_auth_data (osp_credential,
"kdc",
credential_iterator_kdc (&iter)
?: "");
osp_credential_set_auth_data (osp_credential,
"realm",
credential_iterator_realm (&iter)
?: "");
cleanup_iterator (&iter);
return osp_credential;
}
return NULL;
}

/**
* @brief Prepare a report for resuming an OSP scan
*
Expand Down Expand Up @@ -2571,7 +2626,7 @@ launch_osp_openvas_task (task_t task, target_t target, const char *scan_id,
GSList *osp_targets, *vts;
GHashTable *vts_hash_table;
osp_credential_t *ssh_credential, *smb_credential, *esxi_credential;
osp_credential_t *snmp_credential;
osp_credential_t *snmp_credential, *krb5_credential;
gchar *max_checks, *max_hosts, *hosts_ordering;
GHashTable *scanner_options;
int ret, empty;
Expand Down Expand Up @@ -2663,6 +2718,10 @@ launch_osp_openvas_task (task_t task, target_t target, const char *scan_id,
if (snmp_credential)
osp_target_add_credential (osp_target, snmp_credential);

krb5_credential = target_osp_krb5_credential (target);
if (krb5_credential)
osp_target_add_credential (osp_target, krb5_credential);

/* Initialize vts table for vulnerability tests and their preferences */
vts = NULL;
vts_hash_table
Expand Down
Loading

0 comments on commit b34dbad

Please sign in to comment.