diff --git a/.docker/prod.Dockerfile b/.docker/prod.Dockerfile index 98bd6b9e5..204d14036 100644 --- a/.docker/prod.Dockerfile +++ b/.docker/prod.Dockerfile @@ -2,8 +2,14 @@ ARG VERSION=edge ARG GVM_LIBS_VERSION=oldstable ARG DEBIAN_FRONTEND=noninteractive ARG IMAGE_REGISTRY=ghcr.io +# when set it will added to the cmake command +# As an example: +# FEATURE_TOGGLES="-DOPENVASD=1" +# enables openvasd feature toggle. +ARG FEATURE_TOGGLE="" FROM ${IMAGE_REGISTRY}/greenbone/gvmd-build:${VERSION} as builder +ARG FEATURE_TOGGLE COPY . /source WORKDIR /source @@ -11,7 +17,7 @@ WORKDIR /source RUN mkdir /build && \ mkdir /install && \ cd /build && \ - cmake -DCMAKE_BUILD_TYPE=Release /source && \ + cmake -DCMAKE_BUILD_TYPE=Release $FEATURE_TOGGLE /source && \ make DESTDIR=/install install FROM greenbone/gvm-libs:${GVM_LIBS_VERSION} diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 7b534424d..88aa3ef3e 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -14,6 +14,11 @@ jobs: images: name: Production Images runs-on: ubuntu-latest + strategy: + matrix: + build: + - default + - openvasd steps: - name: Checkout repository uses: actions/checkout@v4 @@ -41,8 +46,9 @@ jobs: type=ref,event=pr # when a new git tag is created set stable and a latest tags - type=raw,value=latest,enable=${{ steps.latest.outputs.is-latest-tag == 'true' }} - type=raw,value=stable,enable=${{ steps.latest.outputs.is-latest-tag == 'true' }} + type=raw,value=latest,enable=${{ steps.latest.outputs.is-latest-tag == 'true' && matrix.build == 'default'}} + type=raw,value=stable,enable=${{ steps.latest.outputs.is-latest-tag == 'true' && matrix.build == 'default'}} + type=raw,value=edge-openvasd,enable=${{ steps.latest.outputs.is-latest-tag == 'false' && matrix.build == 'openvasd' }} - name: Set container build options id: container-opts run: | @@ -53,6 +59,11 @@ jobs: echo "version=edge" >> $GITHUB_OUTPUT echo "gvm-libs-version=oldstable-edge" >> $GITHUB_OUTPUT fi + if [[ "${{ matrix.build }}" = 'openvasd' ]]; then + echo 'ft=-DOPENVASD=1' >> $GITHUB_OUTPUT + else + echo 'ft=-DOPENVASD=0' >> $GITHUB_OUTPUT + fi - name: Login to Docker Registry if: github.event_name != 'pull_request' uses: docker/login-action@v3 @@ -71,6 +82,7 @@ jobs: build-args: | VERSION=${{ steps.container-opts.outputs.version }} GVM_LIBS_VERSION=${{ steps.container-opts.outputs.gvm-libs-version }} + FEATURE_TOGGLE=${{ steps.container-opts.outputs.ft }} IMAGE_REGISTRY=${{ vars.IMAGE_REGISTRY }} file: .docker/prod.Dockerfile platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 000000000..599b2294d --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,55 @@ +name: Build and Push to Greenbone Registry + +on: + push: + branches: [ main ] + tags: ["v*"] + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + building: + runs-on: self-hosted-generic + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: greenbone/actions/is-latest-tag@v3 + id: latest + + - name: Set container build options + id: container-opts + run: | + if [[ "${{ github.ref_type }}" = 'tag' ]]; then + echo "version=stable" >> $GITHUB_OUTPUT + echo "gvm-libs-version=oldstable" >> $GITHUB_OUTPUT + else + echo "version=edge" >> $GITHUB_OUTPUT + echo "gvm-libs-version=oldstable-edge" >> $GITHUB_OUTPUT + fi + + - name: Build and Push Container + id: build-and-push + uses: greenbone/actions/container-build-push-generic@v3 + with: + build-docker-file: .docker/prod.Dockerfile + build-args: | + VERSION=${{ steps.container-opts.outputs.version }} + GVM_LIBS_VERSION=${{ steps.container-opts.outputs.gvm-libs-version }} + IMAGE_REGISTRY=${{ vars.IMAGE_REGISTRY }} + image-url: community/gvmd + image-labels: | + org.opencontainers.image.vendor=Greenbone + org.opencontainers.image.base.name=greenbone/gvm-libs + image-tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=edge + type=ref,event=pr + type=raw,value=latest,enable=${{ steps.latest.outputs.is-latest-tag == 'true' }} + type=raw,value=stable,enable=${{ steps.latest.outputs.is-latest-tag == 'true' }} + registry: ${{ secrets.GREENBONE_REGISTRY }} + registry-username: ${{ secrets.GREENBONE_REGISTRY_USER }} + registry-password: ${{ secrets.GREENBONE_REGISTRY_TOKEN }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 772712ac4..8af58ee08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,7 @@ include (CPack) ## Variables -set (GVMD_DATABASE_VERSION 255) +set (GVMD_DATABASE_VERSION 256) set (GVMD_SCAP_DATABASE_VERSION 21) @@ -235,6 +235,11 @@ if (NOT GVM_DEFAULT_DROP_USER) set (GVM_DEFAULT_DROP_USER "") endif (NOT GVM_DEFAULT_DROP_USER) + +if (NOT OPENVASD) + set (OPENVASD 0) +endif (NOT OPENVASD) + message ("-- Install prefix: ${CMAKE_INSTALL_PREFIX}") ## Version @@ -275,7 +280,7 @@ set (HARDENING_FLAGS "-Wformat -Wformat-security -D_FORTIFY_SOURCE=2 set (LINKER_HARDENING_FLAGS "-Wl,-z,relro -Wl,-z,now") # To find unused functions, add: -flto -fwhole-program -ffunction-sections -Wl,--gc-sections -Wl,--print-gc-sections -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -D_BSD_SOURCE -D_ISOC99_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE -D_FILE_OFFSET_BITS=64") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -D_BSD_SOURCE -D_ISOC99_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE -D_FILE_OFFSET_BITS=64 -DOPENVASD=${OPENVASD}") set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror -Wshadow ${COVERAGE_FLAGS} ${DEBUG_FUNCTION_NAMES_FLAGS}") set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${HARDENING_FLAGS} ${COVERAGE_FLAGS}") diff --git a/src/gmp.c b/src/gmp.c index 0c326f1a8..ef2b612ee 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -12282,7 +12282,7 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) SEND_GET_START("credential"); while (1) { - const char *private_key, *public_key, *login, *type, *cert; + const char *login, *type, *cert; gchar *formats_xml; ret = get_next (&credentials, &get_credentials_data->get, @@ -12296,8 +12296,6 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) } SEND_GET_COMMON (credential, &get_credentials_data->get, &credentials); - private_key = credential_iterator_private_key (&credentials); - public_key = credential_iterator_public_key (&credentials); login = credential_iterator_login (&credentials); type = credential_iterator_type (&credentials); cert = credential_iterator_certificate (&credentials); @@ -12376,6 +12374,10 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) case CREDENTIAL_FORMAT_KEY: { + const char *public_key; + + public_key = credential_iterator_public_key (&credentials); + if (public_key && strcmp (public_key, "")) { SENDF_TO_CLIENT_OR_FAIL @@ -12384,8 +12386,9 @@ handle_get_credentials (gmp_parser_t *gmp_parser, GError **error) else { char *pub; - const char *pass; + const char *pass, *private_key; + private_key = credential_iterator_private_key (&credentials); pass = credential_iterator_password (&credentials); pub = gvm_ssh_public_from_private (private_key, pass); SENDF_TO_CLIENT_OR_FAIL @@ -18610,9 +18613,13 @@ handle_get_tasks (gmp_parser_t *gmp_parser, GError **error) auto_delete ? auto_delete : "0", auto_delete_data ? auto_delete_data : "0"); + g_free (assets_apply_overrides); + g_free (assets_min_qod); g_free (in_assets); g_free (max_checks); g_free (max_hosts); + g_free (auto_delete); + g_free (auto_delete_data); } count++; diff --git a/src/gvmd.c b/src/gvmd.c index 34a720efd..8a8d1e0ec 100644 --- a/src/gvmd.c +++ b/src/gvmd.c @@ -2300,6 +2300,9 @@ gvmd (int argc, char** argv, char *env[]) else printf ("Sentry support disabled\n"); } +#if OPENVASD == 1 + printf ("OpenVASD is enabled\n"); +#endif printf ("Copyright (C) 2009-2021 Greenbone AG\n"); printf ("License: AGPL-3.0-or-later\n"); printf @@ -2484,6 +2487,7 @@ gvmd (int argc, char** argv, char *env[]) /** * LDAP debugging */ + if (ldap_debug) { if (ldap_enable_debug () == 0) diff --git a/src/lsc_crypt.c b/src/lsc_crypt.c index d4e1a0b8a..e64adad0b 100644 --- a/src/lsc_crypt.c +++ b/src/lsc_crypt.c @@ -581,6 +581,7 @@ lsc_crypt_release (lsc_crypt_ctx_t ctx) lsc_crypt_flush (ctx); if (ctx->encctx) /* Check required for gpgme < 1.3.1 */ gpgme_release (ctx->encctx); + g_free (ctx->enckey_uid); g_free (ctx); } diff --git a/src/manage.c b/src/manage.c index 12ae1c6a0..0af8a5486 100644 --- a/src/manage.c +++ b/src/manage.c @@ -5085,6 +5085,8 @@ manage_sync (sigset_t *sigmask_current, wait_for_pid (scap_pid, "SCAP sync"); wait_for_pid (cert_pid, "CERT sync"); + update_scap_extra (); + lockfile_unlock (&lockfile); } } @@ -5977,6 +5979,54 @@ get_nvt_xml (iterator_t *nvts, int details, int pref_count, free (default_timeout); } + if (nvt_iterator_epss_cve (nvts)) + { + buffer_xml_append_printf + (buffer, + "" + "" + "%0.5f" + "%0.5f" + "", + nvt_iterator_epss_score (nvts), + nvt_iterator_epss_percentile (nvts), + nvt_iterator_epss_cve (nvts)); + + if (nvt_iterator_has_epss_severity (nvts)) + { + buffer_xml_append_printf + (buffer, + "%0.1f", + nvt_iterator_epss_severity (nvts)); + } + + buffer_xml_append_printf + (buffer, + "" + "" + "" + "%0.5f" + "%0.5f" + "", + nvt_iterator_max_epss_score (nvts), + nvt_iterator_max_epss_percentile (nvts), + nvt_iterator_max_epss_cve (nvts)); + + if (nvt_iterator_has_max_epss_severity (nvts)) + { + buffer_xml_append_printf + (buffer, + "%0.1f", + nvt_iterator_max_epss_severity (nvts)); + } + + buffer_xml_append_printf + (buffer, + "" + "" + ""); + } + xml_string_append (buffer, close_tag ? "" : ""); msg = g_string_free (buffer, FALSE); } diff --git a/src/manage.h b/src/manage.h index 01c864eec..a272cb20d 100644 --- a/src/manage.h +++ b/src/manage.h @@ -1982,6 +1982,36 @@ nvt_iterator_solution_type (iterator_t*); const char* nvt_iterator_solution_method (iterator_t*); +double +nvt_iterator_epss_score (iterator_t*); + +double +nvt_iterator_epss_percentile (iterator_t*); + +const char* +nvt_iterator_epss_cve (iterator_t*); + +double +nvt_iterator_epss_severity (iterator_t*); + +gboolean +nvt_iterator_has_epss_severity (iterator_t*); + +double +nvt_iterator_max_epss_score (iterator_t*); + +double +nvt_iterator_max_epss_percentile (iterator_t*); + +const char* +nvt_iterator_max_epss_cve (iterator_t*); + +double +nvt_iterator_max_epss_severity (iterator_t*); + +gboolean +nvt_iterator_has_max_epss_severity (iterator_t*); + char* nvt_default_timeout (const char *); diff --git a/src/manage_acl.c b/src/manage_acl.c index 18996e780..e2953d8f1 100644 --- a/src/manage_acl.c +++ b/src/manage_acl.c @@ -1078,6 +1078,7 @@ acl_where_owned_user (const char *user_id, const char *user_sql, if (permissions == NULL || permissions->len == 0) { /* Treat filters with no permissions keyword as "any". */ + g_string_free (permission_or, TRUE); permission_or = g_string_new ("t ()"); index = 1; } diff --git a/src/manage_configs.c b/src/manage_configs.c index e88f7b023..d7de250af 100644 --- a/src/manage_configs.c +++ b/src/manage_configs.c @@ -620,7 +620,11 @@ should_sync_configs () && strlen (config_path) >= (36 /* UUID */ + strlen (".xml")) && g_str_has_suffix (config_path, ".xml") && should_sync_config_from_path (config_path, FALSE, &config)) - return TRUE; + { + g_dir_close (dir); + return TRUE; + } + g_dir_close (dir); return FALSE; } diff --git a/src/manage_migrators.c b/src/manage_migrators.c index 9d5436716..3053fd2fe 100644 --- a/src/manage_migrators.c +++ b/src/manage_migrators.c @@ -3176,6 +3176,46 @@ migrate_254_to_255 () return 0; } +/** + * @brief Migrate the database from version 255 to version 256. + * + * @return 0 success, -1 error. + */ +int +migrate_255_to_256 () +{ + sql_begin_immediate (); + + /* Ensure that the database is currently version 255. */ + + if (manage_db_version () != 255) + { + sql_rollback (); + return -1; + } + + /* Update the database. */ + + // Add new columns + + sql ("ALTER TABLE nvts ADD COLUMN epss_cve TEXT;"); + sql ("ALTER TABLE nvts ADD COLUMN epss_score DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN epss_percentile DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN epss_severity DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN max_epss_cve TEXT;"); + sql ("ALTER TABLE nvts ADD COLUMN max_epss_score DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN max_epss_percentile DOUBLE PRECISION;"); + sql ("ALTER TABLE nvts ADD COLUMN max_epss_severity DOUBLE PRECISION;"); + + /* Set the database version to 256. */ + + set_db_version (256); + + sql_commit (); + + return 0; +} + #undef UPDATE_DASHBOARD_SETTINGS /** @@ -3237,6 +3277,7 @@ static migrator_t database_migrators[] = { {253, migrate_252_to_253}, {254, migrate_253_to_254}, {255, migrate_254_to_255}, + {256, migrate_255_to_256}, /* End marker. */ {-1, NULL}}; diff --git a/src/manage_pg.c b/src/manage_pg.c index 851769370..19d3463f7 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -1868,7 +1868,16 @@ create_tables_nvt (const gchar *suffix) " solution_method text," " detection text," " qod integer," - " qod_type text);", + " qod_type text," + " epss_cve TEXT," + " epss_score DOUBLE PRECISION," + " epss_percentile DOUBLE PRECISION," + " epss_severity DOUBLE PRECISION," + " max_epss_cve TEXT," + " max_epss_score DOUBLE PRECISION," + " max_epss_percentile DOUBLE PRECISION," + " max_epss_severity DOUBLE PRECISION" + ");", suffix); } diff --git a/src/manage_port_lists.c b/src/manage_port_lists.c index 39f2d1775..26f7c8cc5 100644 --- a/src/manage_port_lists.c +++ b/src/manage_port_lists.c @@ -537,7 +537,11 @@ should_sync_port_lists () && strlen (port_list_path) >= (36 /* UUID */ + strlen (".xml")) && g_str_has_suffix (port_list_path, ".xml") && should_sync_port_list_from_path (port_list_path, FALSE, &port_list)) - return TRUE; + { + g_dir_close (dir); + return TRUE; + } + g_dir_close (dir); return FALSE; } diff --git a/src/manage_report_formats.c b/src/manage_report_formats.c index efc471633..8cc94feb0 100644 --- a/src/manage_report_formats.c +++ b/src/manage_report_formats.c @@ -905,7 +905,11 @@ should_sync_report_formats () && should_sync_report_format_from_path (report_format_path, FALSE, &report_format)) - return TRUE; + { + g_dir_close (dir); + return TRUE; + } + g_dir_close (dir); return FALSE; } diff --git a/src/manage_sql_nvts.c b/src/manage_sql_nvts.c index 95714193d..ccebce74f 100644 --- a/src/manage_sql_nvts.c +++ b/src/manage_sql_nvts.c @@ -41,6 +41,7 @@ #include "manage_preferences.h" #include "manage_sql.h" #include "manage_sql_configs.h" +#include "manage_sql_secinfo.h" #include "sql.h" #include "utils.h" @@ -1214,6 +1215,153 @@ DEF_ACCESS (nvt_iterator_detection, GET_ITERATOR_COLUMN_COUNT + 19); */ DEF_ACCESS (nvt_iterator_solution_method, GET_ITERATOR_COLUMN_COUNT + 20); +/** + * @brief Get the EPSS score selected by severity from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The EPSS score. + */ +double +nvt_iterator_epss_score (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 21); + return ret; +} + +/** + * @brief Get the EPSS percentile selected by severity from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The EPSS percentile. + */ +double +nvt_iterator_epss_percentile (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 22); + return ret; +} + +/** + * @brief Get the CVE of the EPSS score by severity from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return CVE-ID of the EPSS score, or NULL if iteration is complete. + * Freed by cleanup_iterator. + */ +DEF_ACCESS (nvt_iterator_epss_cve, GET_ITERATOR_COLUMN_COUNT + 23); + +/** + * @brief Get the maximum severity of CVEs with EPSS info from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The severity score. + */ +double +nvt_iterator_epss_severity (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 24); + return ret; +} + +/** + * @brief Get whether the NVT has a severity for the max severity EPSS score. + * + * @param[in] iterator Iterator. + * + * @return Whether the severity exists. + */ +gboolean +nvt_iterator_has_epss_severity (iterator_t* iterator) +{ + gboolean ret; + if (iterator->done) return -1; + ret = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 24) != NULL; + return ret; +} + +/** + * @brief Get the maximum EPSS score from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The maximum EPSS score. + */ +double +nvt_iterator_max_epss_score (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 25); + return ret; +} + +/** + * @brief Get the maximum EPSS percentile from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return The maximum EPSS percentile. + */ +double +nvt_iterator_max_epss_percentile (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 26); + return ret; +} + +/** + * @brief Get the CVE of the maximum EPSS score from an NVT iterator. + * + * @param[in] iterator Iterator. + * + * @return CVE-ID of the maximum EPSS score, or NULL if iteration is complete. + * Freed by cleanup_iterator. + */ +DEF_ACCESS (nvt_iterator_max_epss_cve, GET_ITERATOR_COLUMN_COUNT + 27); + +/** + * @brief Get the severity of the maximum EPSS score from an NVT iterator. + * @param[in] iterator Iterator. + * + * @return The severity score. + */ +double +nvt_iterator_max_epss_severity (iterator_t* iterator) +{ + double ret; + if (iterator->done) return -1; + ret = iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 28); + return ret; +} + +/** + * @brief Get whether the NVT has a severity for the max EPSS score. + * + * @param[in] iterator Iterator. + * + * @return Whether the severity exists. + */ +gboolean +nvt_iterator_has_max_epss_severity (iterator_t* iterator) +{ + gboolean ret; + if (iterator->done) return -1; + ret = iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 28) != NULL; + return ret; +} + /** * @brief Get the default timeout of an NVT. * @@ -2314,8 +2462,10 @@ nvts_feed_version_status_internal (const gchar *update_socket, scanner_feed_version = osp_scanner_feed_version (update_socket); g_debug ("%s: scanner_feed_version: %s", __func__, scanner_feed_version); - if (scanner_feed_version == NULL) + if (scanner_feed_version == NULL) { + g_free (db_feed_version); return -1; + } if (scanner_feed_version_out && scanner_feed_version) *scanner_feed_version_out = g_strdup (scanner_feed_version); @@ -2327,6 +2477,8 @@ nvts_feed_version_status_internal (const gchar *update_socket, return 1; } + g_free (db_feed_version); + g_free (scanner_feed_version); return 0; } @@ -2532,6 +2684,9 @@ manage_rebuild (GSList *log_config, const db_conn_info_t *database) break; } + if (ret == 0) + update_scap_extra (); + feed_lockfile_unlock (&lockfile); manage_option_cleanup (); diff --git a/src/manage_sql_nvts.h b/src/manage_sql_nvts.h index e9db88fad..bbe4d39a6 100644 --- a/src/manage_sql_nvts.h +++ b/src/manage_sql_nvts.h @@ -31,7 +31,9 @@ { GET_ITERATOR_FILTER_COLUMNS, "version", "cve", \ "family", "cvss_base", "severity", "cvss", "script_tags", "qod", \ "qod_type", "solution_type", "solution", "summary", "insight", \ - "affected", "impact", "detection", "solution_method", NULL } + "affected", "impact", "detection", "solution_method", "epss_score", \ + "epss_percentile", "max_epss_score", "max_epss_percentile", \ + NULL } /** * @brief NVT iterator columns. @@ -62,6 +64,18 @@ { "impact", NULL, KEYWORD_TYPE_STRING }, \ { "detection", NULL, KEYWORD_TYPE_STRING }, \ { "solution_method", NULL, KEYWORD_TYPE_STRING }, \ + { "coalesce (epss_score, 0.0)", "epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (epss_percentile, 0.0)", "epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "epss_cve", NULL, KEYWORD_TYPE_STRING }, \ + { "epss_severity", NULL, KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (max_epss_score, 0.0)", "max_epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (max_epss_percentile, 0.0)", "max_epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "max_epss_cve", NULL, KEYWORD_TYPE_STRING }, \ + { "max_epss_severity", NULL, KEYWORD_TYPE_DOUBLE }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } @@ -94,6 +108,18 @@ { "impact", NULL, KEYWORD_TYPE_STRING }, \ { "detection", NULL, KEYWORD_TYPE_STRING }, \ { "solution_method", NULL, KEYWORD_TYPE_STRING }, \ + { "coalesce (epss_score, 0.0)", "epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (epss_percentile, 0.0)", "epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "epss_cve", NULL, KEYWORD_TYPE_STRING }, \ + { "epss_severity", NULL, KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (max_epss_score, 0.0)", "max_epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (max_epss_percentile, 0.0)", "max_epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "max_epss_cve", NULL, KEYWORD_TYPE_STRING }, \ + { "max_epss_severity", NULL, KEYWORD_TYPE_DOUBLE }, \ { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \ } diff --git a/src/manage_sql_secinfo.c b/src/manage_sql_secinfo.c index 455fc3dbc..fdf76db8c 100644 --- a/src/manage_sql_secinfo.c +++ b/src/manage_sql_secinfo.c @@ -2491,7 +2491,6 @@ static int insert_cve_from_entry (element_t entry, element_t last_modified, GHashTable *hashed_cpes, int *transaction_size) { - gboolean cvss_is_v3; element_t published, summary, cvss, score, base_metrics, cvss_vector, list; double severity_dbl; gchar *quoted_id, *quoted_summary, *quoted_cvss_vector; @@ -2518,21 +2517,36 @@ insert_cve_from_entry (element_t entry, element_t last_modified, return -1; } - cvss = element_child (entry, "vuln:cvss3"); + gchar *base_metrics_element = "cvss:base_metrics"; + gchar *score_element = "cvss:score"; + gchar *cvss_vector_element = "cvss:vector-string"; + + cvss = element_child (entry, "vuln:cvss4"); if (cvss == NULL) { - cvss = element_child (entry, "vuln:cvss"); - cvss_is_v3 = FALSE; + cvss = element_child (entry, "vuln:cvss3"); + if (cvss == NULL) + { + cvss = element_child (entry, "vuln:cvss"); + } + else + { + base_metrics_element = "cvss3:base_metrics"; + score_element = "cvss3:base-score"; + cvss_vector_element = "cvss3:vector-string"; + } } else - cvss_is_v3 = TRUE; + { + base_metrics_element = "cvss4:base_metrics"; + score_element = "cvss4:base-score"; + cvss_vector_element = "cvss4:vector-string"; + } if (cvss == NULL) base_metrics = NULL; else - base_metrics = element_child (cvss, - cvss_is_v3 ? "cvss3:base_metrics" - : "cvss:base_metrics"); + base_metrics = element_child (cvss, base_metrics_element); if (base_metrics == NULL) { @@ -2541,8 +2555,8 @@ insert_cve_from_entry (element_t entry, element_t last_modified, } else { - score = element_child (base_metrics, - cvss_is_v3 ? "cvss3:base-score" : "cvss:score"); + score = element_child (base_metrics, score_element); + if (score == NULL) { g_warning ("%s: cvss:score missing for %s", __func__, id); @@ -2550,9 +2564,8 @@ insert_cve_from_entry (element_t entry, element_t last_modified, return -1; } - cvss_vector = element_child (base_metrics, - cvss_is_v3 ? "cvss3:vector-string" - : "cvss:vector-string"); + cvss_vector = element_child (base_metrics, cvss_vector_element); + if (cvss_vector == NULL) { g_warning ("%s: cvss:access-vector missing for %s", __func__, id); @@ -3571,6 +3584,65 @@ update_scap_placeholders () " WHERE cpe=cpes.id))" " WHERE cpes.title IS NULL;"); } + +/** + * @brief Update extra data for VTs based on SCAP and SCAP supplement data. + */ +static void +update_vt_scap_extra_data () +{ + g_info ("Assigning EPSS scores to VTs"); + + sql ("UPDATE nvts" + " SET epss_cve = NULL," + " epss_score = NULL," + " epss_percentile = NULL," + " epss_severity = NULL," + " max_epss_cve = NULL," + " max_epss_score = NULL," + " max_epss_percentile = NULL," + " max_epss_severity = NULL;"); + + sql ("WITH epss_candidates AS (" + " SELECT vt_oid, cve, severity, epss, percentile," + " rank() OVER (PARTITION BY vt_oid" + " ORDER BY severity DESC," + " epss DESC," + " scap.cves.modification_time DESC) AS rank" + " FROM (SELECT * FROM vt_refs WHERE type='cve') AS vt_cves" + " JOIN scap.epss_scores ON ref_id = cve" + " LEFT JOIN scap.cves ON scap.cves.name = cve" + " ORDER BY vt_oid" + ") " + "UPDATE nvts" + " SET epss_cve = epss_candidates.cve," + " epss_score = epss_candidates.epss," + " epss_percentile = epss_candidates.percentile," + " epss_severity = epss_candidates.severity" + " FROM epss_candidates" + " WHERE epss_candidates.vt_oid = nvts.oid" + " AND epss_candidates.rank = 1;"); + + sql ("WITH epss_candidates AS (" + " SELECT vt_oid, cve, severity, epss, percentile," + " rank() OVER (PARTITION BY vt_oid" + " ORDER BY epss DESC," + " severity DESC," + " scap.cves.modification_time DESC) AS rank" + " FROM (SELECT * FROM vt_refs WHERE type='cve') AS vt_cves" + " JOIN scap.epss_scores ON ref_id = cve" + " LEFT JOIN scap.cves ON scap.cves.name = cve" + " ORDER BY vt_oid" + ") " + "UPDATE nvts" + " SET max_epss_cve = epss_candidates.cve," + " max_epss_score = epss_candidates.epss," + " max_epss_percentile = epss_candidates.percentile," + " max_epss_severity = epss_candidates.severity" + " FROM epss_candidates" + " WHERE epss_candidates.vt_oid = nvts.oid" + " AND epss_candidates.rank = 1;"); +} /** * @brief Update CERT data that depends on SCAP. @@ -3906,6 +3978,25 @@ update_scap (gboolean reset_scap_db) return 0; } +/** + * @brief Update extra data in the SCAP DB that depends on other feeds. + */ +void +update_scap_extra () +{ + if (manage_scap_loaded () == 0) + { + g_info ("%s: SCAP database missing, skipping extra data update", + __func__); + return; + } + + g_debug ("%s: update SCAP extra data of VTs", __func__); + setproctitle ("Syncing SCAP: Updating VT extra data"); + + update_vt_scap_extra_data (); +} + /** * @brief Sync the SCAP DB. * @@ -3950,8 +4041,9 @@ rebuild_scap () return -1; ret = update_scap (TRUE); - if (ret == 1) - ret = 2; + + if (ret == 0) + update_scap_extra (); if (feed_lockfile_unlock (&lockfile)) { diff --git a/src/manage_sql_secinfo.h b/src/manage_sql_secinfo.h index 7e7a83ed6..5e8ad4761 100644 --- a/src/manage_sql_secinfo.h +++ b/src/manage_sql_secinfo.h @@ -195,4 +195,7 @@ get_secinfo_commit_size (); void set_secinfo_commit_size (int); +void +update_scap_extra (); + #endif /* not _GVMD_MANAGE_SQL_SECINFO_H */ diff --git a/src/schema_formats/HTML/HTML.xsl b/src/schema_formats/HTML/HTML.xsl index bd8a9d7da..88b58b7f2 100644 --- a/src/schema_formats/HTML/HTML.xsl +++ b/src/schema_formats/HTML/HTML.xsl @@ -342,7 +342,7 @@ along with this program. If not, see . -
+
@@ -427,7 +427,7 @@ along with this program. If not, see . -
    +
    • @@ -656,11 +656,14 @@ along with this program. If not, see . -
        +
          Empty single element. + + + @@ -693,11 +696,11 @@ along with this program. If not, see .
          • - Command +
            Command
          • - Response +
            Response
            diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index ba7bba56f..616a37f44 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -582,6 +582,7 @@ along with this program. If not, see . timeout default_timeout solution + epss preferences @@ -680,6 +681,112 @@ along with this program. If not, see . + + epss + Exploit Prediction Scoring System (EPSS) info if available + + max_severity + max_epss + + + max_severity + + EPSS info of the referenced CVE with the highest severity + + + In case there are multiple CVEs referenced by the NVT tied for the + highest severity, they are also sorted by EPSS score and modification + time and the first one is chosen. + + + score + percentile + cve + + + score + EPSS score of the CVE + + decimal + + + + percentile + EPSS percentile of the CVE + + decimal + + + + cve + The representative CVE chosen + + + id + CVE-ID of the CVE + text + + severity + + + severity + Severity (CVSS) score of the CVE if available + + severity + + + + + + max_epss + + EPSS info of the referenced CVE with the highest EPSS score + + + In case there are multiple CVEs referenced by the NVT tied for the + highest EPSS score, they are also sorted by severity and modification + time and the first one is chosen. + + + score + percentile + cve + + + score + EPSS score of the CVE + + decimal + + + + percentile + EPSS percentile of the CVE + + decimal + + + + cve + The representative CVE chosen + + + id + CVE-ID of the CVE + text + + severity + + + severity + Severity (CVSS) score of the CVE if available + + severity + + + + + preferences The list of preferences @@ -3883,6 +3990,15 @@ along with this program. If not, see . type The type of credential to create + +

            cc: Client certificate

            +

            pgp: PGP encryption key

            +

            pw: Password only

            +

            smime: S/MIME certificate

            +

            snmp: SNMP

            +

            up: User name + password

            +

            usk: User name + SSH key

            +
            cc @@ -10633,6 +10749,15 @@ END:VCALENDAR type The type of the credential + +

            cc: Client certificate

            +

            pgp: PGP encryption key

            +

            pw: Password only

            +

            smime: S/MIME certificate

            +

            snmp: SNMP

            +

            up: User name + password

            +

            usk: User name + SSH key

            +
            cc @@ -12199,6 +12324,34 @@ END:VCALENDAR integer Version of the NVT (deprected) + + epss_score + decimal + + EPSS score of highest severity CVE (see epss/max_severity) + + + + epss_percentile + decimal + + EPSS percentile of highest severity CVE (see epss/max_severity) + + + + max_epss_score + decimal + + Highest EPSS score of referenced CVEs (see epss/max_epss) + + + + max_epss_percentile + decimal + + Highest EPSS percentile of referenced CVEs (see epss/max_epss) + + type is "cve" @@ -12222,6 +12375,16 @@ END:VCALENDAR iso_time Time the CVE was published, alias for created + + epss_score + decimal + EPSS score the CVE + + + epss_percentile + decimal + EPSS percentile of the CVE + type is "cpe" @@ -13793,6 +13956,7 @@ END:VCALENDAR timeout default_timeout solution + epss preferences @@ -13969,6 +14133,112 @@ END:VCALENDAR text
            + + epss + Exploit Prediction Scoring System (EPSS) info if available + + max_severity + max_epss + + + max_severity + + EPSS info of the referenced CVE with the highest severity + + + In case there are multiple CVEs referenced by the NVT tied for the + highest severity, they are also sorted by EPSS score and modification + time and the first one is chosen. + + + score + percentile + cve + + + score + EPSS score of the CVE + + decimal + + + + percentile + EPSS percentile of the CVE + + decimal + + + + cve + The representative CVE chosen + + + id + CVE-ID of the CVE + text + + severity + + + severity + Severity (CVSS) score of the CVE if available + + severity + + + + + + max_epss + + EPSS info of the referenced CVE with the highest EPSS score + + + In case there are multiple CVEs referenced by the NVT tied for the + highest EPSS score, they are also sorted by severity and modification + time and the first one is chosen. + + + score + percentile + cve + + + score + EPSS score of the CVE + + decimal + + + + percentile + EPSS percentile of the CVE + + decimal + + + + cve + The representative CVE chosen + + + id + CVE-ID of the CVE + text + + severity + + + severity + Severity (CVSS) score of the CVE if available + + severity + + + + + preferences List of preferences of the NVT