diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml index b927fd34d..3133f6ced 100644 --- a/.github/workflows/build-container.yml +++ b/.github/workflows/build-container.yml @@ -52,7 +52,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and push - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . push: true diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 88aa3ef3e..e59303eff 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -75,7 +75,7 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build and push Container image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . push: ${{ github.event_name != 'pull_request' && (github.ref_type == 'tag' || github.ref_name == 'main') }} diff --git a/src/gmp.c b/src/gmp.c index e846eec84..f98cc69f6 100644 --- a/src/gmp.c +++ b/src/gmp.c @@ -9108,6 +9108,42 @@ results_xml_append_cert (GString *buffer, iterator_t *results, const char *oid, } } +/** + * @brief Append an EPSS info element to a results XML buffer. + * + * @param[in] results Results iterator. + * @param[in] buffer XML buffer to add to. + */ +static void +results_xml_append_epss (iterator_t *results, GString *buffer) +{ + buffer_xml_append_printf (buffer, + "" + "" + "%0.5f" + "%0.5f" + "" + "%0.1f" + "" + "" + "" + "%0.5f" + "%0.5f" + "" + "%0.1f" + "" + "" + "", + result_iterator_epss_score (results), + result_iterator_epss_percentile (results), + result_iterator_epss_cve (results), + result_iterator_epss_severity (results), + result_iterator_max_epss_score (results), + result_iterator_max_epss_percentile (results), + result_iterator_max_epss_cve (results), + result_iterator_max_epss_severity (results)); +} + /** * @brief Append an NVT element to an XML buffer. * @@ -9138,14 +9174,19 @@ results_xml_append_nvt (iterator_t *results, GString *buffer, int cert_loaded) "" "" "" - "%s" - "", + "%s", oid, oid, severity ? severity : "", severity ? severity : "", result_iterator_port (results), oid); + + if (result_iterator_epss_cve (results)) + results_xml_append_epss (results, buffer); + + buffer_xml_append_printf (buffer, ""); + g_free (severity); return; } @@ -9285,6 +9326,9 @@ results_xml_append_nvt (iterator_t *results, GString *buffer, int cert_loaded) buffer_xml_append_printf (buffer, "/>"); } + if (result_iterator_epss_cve (results)) + results_xml_append_epss (results, buffer); + first = 1; xml_append_nvt_refs (buffer, result_iterator_nvt_oid (results), &first); @@ -11675,7 +11719,6 @@ handle_get_assets (gmp_parser_t *gmp_parser, GError **error) gchar *routes_xml; asset = get_iterator_resource (&assets); - /* Assets are currently always writable. */ if (send_get_common ("asset", &get_assets_data->get, &assets, gmp_parser->client_writer, gmp_parser->client_writer_data, diff --git a/src/manage.h b/src/manage.h index ce3a5ea6d..9e7bbbce9 100644 --- a/src/manage.h +++ b/src/manage.h @@ -1522,6 +1522,30 @@ result_iterator_may_have_overrides (iterator_t*); int result_iterator_may_have_tickets (iterator_t*); +double +result_iterator_epss_score (iterator_t*); + +double +result_iterator_epss_percentile (iterator_t*); + +const char* +result_iterator_epss_cve (iterator_t*); + +double +result_iterator_epss_severity (iterator_t*); + +double +result_iterator_max_epss_score (iterator_t*); + +double +result_iterator_max_epss_percentile (iterator_t*); + +const char* +result_iterator_max_epss_cve (iterator_t*); + +double +result_iterator_max_epss_severity (iterator_t*); + gchar ** result_iterator_cert_bunds (iterator_t*); diff --git a/src/manage_pg.c b/src/manage_pg.c index 31d1201c7..16189a2e0 100644 --- a/src/manage_pg.c +++ b/src/manage_pg.c @@ -1806,6 +1806,59 @@ create_view_vulns () " WHERE uuid in (SELECT * FROM used_nvts)"); } +/** + * @brief Create or replace the result_vt_epss view. + */ +void +create_view_result_vt_epss () +{ + sql ("DROP MATERIALIZED VIEW IF EXISTS result_vt_epss;"); + + if (sql_int ("SELECT EXISTS (SELECT * FROM information_schema.tables" + " WHERE table_catalog = '%s'" + " AND table_schema = 'scap'" + " AND table_name = 'cves')" + " ::integer;", + sql_database ())) + sql ("CREATE MATERIALIZED VIEW result_vt_epss AS (" + " SELECT cve AS vt_id," + " epss AS epss_score," + " percentile AS epss_percentile," + " cve AS epss_cve," + " cves.severity AS epss_severity," + " epss AS max_epss_score," + " percentile AS max_epss_percentile," + " cve AS max_epss_cve," + " cves.severity AS max_epss_severity" + " FROM scap.epss_scores" + " JOIN scap.cves ON cve = cves.uuid" + " UNION ALL" + " SELECT oid AS vt_id," + " epss_score," + " epss_percentile," + " epss_cve," + " epss_severity," + " max_epss_score," + " max_epss_percentile," + " max_epss_cve," + " max_epss_severity" + " FROM nvts);"); + else + sql ("CREATE MATERIALIZED VIEW result_vt_epss AS (" + " SELECT oid AS vt_id," + " epss_score," + " epss_percentile," + " epss_cve," + " max_epss_score," + " max_epss_percentile," + " max_epss_cve" + " FROM nvts);"); + + sql ("SELECT create_index ('result_vt_epss_by_vt_id'," + " 'result_vt_epss', 'vt_id');"); + +} + #undef VULNS_RESULTS_WHERE @@ -3024,6 +3077,8 @@ create_tables () create_view_vulns (); + create_view_result_vt_epss (); + /* Create indexes. */ sql ("SELECT create_index ('config_preferences_by_config'," diff --git a/src/manage_sql.c b/src/manage_sql.c index e6a7e72c1..100030655 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -5266,7 +5266,7 @@ append_column (GArray *columns, const gchar *column_name, * resource. * * @return 0 success, 1 failed to find resource, 2 failed to find filter, - * 3 invalid stat_column, 4 invalid group_column, 5 invalid type, + * 3 invalid data_column, 4 invalid group_column, 5 invalid type, * 6 trashcan not used by type, 7 invalid text column, 8 invalid * subgroup_column, -1 error. */ @@ -22198,7 +22198,8 @@ where_qod (int min_qod) "description", "task", "report", "cvss_base", "nvt_version", \ "severity", "original_severity", "vulnerability", "date", "report_id", \ "solution_type", "qod", "qod_type", "task_id", "cve", "hostname", \ - "path", "compliant", NULL } + "path", "compliant", "epss_score", "epss_percentile", "max_epss_score", \ + "max_epss_percentile", NULL } // TODO Combine with RESULT_ITERATOR_COLUMNS. /** @@ -22497,6 +22498,32 @@ where_qod (int min_qod) " 'undefined')", \ "compliant", \ KEYWORD_TYPE_STRING }, \ + /* ^ 45 = 35 */ \ + { "coalesce (result_vt_epss.epss_score, 0.0)", \ + "epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (result_vt_epss.epss_percentile, 0.0)", \ + "epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "result_vt_epss.epss_cve", \ + "epss_cve", \ + KEYWORD_TYPE_STRING }, \ + { "coalesce (result_vt_epss.epss_severity, 0.0)", \ + "epss_severity", \ + KEYWORD_TYPE_DOUBLE }, \ + { "coalesce (result_vt_epss.max_epss_score, 0.0)", \ + "max_epss_score", \ + KEYWORD_TYPE_DOUBLE }, \ + /* ^ 50 = 40 */ \ + { "coalesce (result_vt_epss.max_epss_percentile, 0.0)", \ + "max_epss_percentile", \ + KEYWORD_TYPE_DOUBLE }, \ + { "result_vt_epss.max_epss_cve", \ + "max_epss_cve", \ + KEYWORD_TYPE_STRING }, \ + { "coalesce (result_vt_epss.max_epss_severity, 0.0)", \ + "max_epss_severity", \ + KEYWORD_TYPE_DOUBLE }, \ /** * @brief Result iterator columns. @@ -23196,7 +23223,9 @@ init_result_get_iterator (iterator_t* iterator, const get_data_t *get, "results", "nvts"); - extra_tables = g_strdup_printf (" LEFT OUTER JOIN nvts" + extra_tables = g_strdup_printf (" LEFT OUTER JOIN result_vt_epss" + " ON results.nvt = result_vt_epss.vt_id" + " LEFT OUTER JOIN nvts" " ON results.nvt = nvts.oid %s," " LATERAL %s AS lateral_new_severity", opts_tables, @@ -23300,7 +23329,9 @@ result_count (const get_data_t *get, report_t report, const char* host) "results", "nvts"); - extra_tables = g_strdup_printf (" LEFT OUTER JOIN nvts" + extra_tables = g_strdup_printf (" LEFT OUTER JOIN result_vt_epss" + " ON results.nvt = result_vt_epss.vt_id" + " LEFT OUTER JOIN nvts" " ON results.nvt = nvts.oid %s," " LATERAL %s AS lateral_new_severity", opts_tables, @@ -23765,6 +23796,118 @@ DEF_ACCESS (result_iterator_nvt_family, GET_ITERATOR_COLUMN_COUNT + 33); */ DEF_ACCESS (result_iterator_nvt_tag, GET_ITERATOR_COLUMN_COUNT + 34); +/** + * @brief Get EPSS score of highest severity CVE from a result iterator. + * + * @param[in] iterator Iterator. + * + * @return EPSS score of the highest severity CVE. + */ +double +result_iterator_epss_score (iterator_t* iterator) +{ + if (iterator->done) return 0.0; + return iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 36); +} + +/** + * @brief Get EPSS percentile of highest severity CVE from a result iterator. + * + * @param[in] iterator Iterator. + * + * @return EPSS percentile of the highest severity CVE. + */ +double +result_iterator_epss_percentile (iterator_t* iterator) +{ + if (iterator->done) return 0.0; + return iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 37); +} + +/** + * @brief Get highest severity CVE with EPSS score from a result iterator. + * + * @param[in] iterator Iterator. + * + * @return Highest severity CVE with EPSS score. + */ +const gchar * +result_iterator_epss_cve (iterator_t* iterator) +{ + if (iterator->done) return NULL; + return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 38); +} + +/** + * @brief Get the highest severity of EPSS CVEs from a result iterator. + * + * @param[in] iterator Iterator. + * + * @return Highest severity of referenced CVEs with EPSS. + */ +double +result_iterator_epss_severity (iterator_t* iterator) +{ + if (iterator->done) return 0.0; + return iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 39); +} + +/** + * @brief Get maximum EPSS score of referenced CVEs from a result iterator. + * + * @param[in] iterator Iterator. + * + * @return Maximum EPSS score. + */ +double +result_iterator_max_epss_score (iterator_t* iterator) +{ + if (iterator->done) return 0.0; + return iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 40); +} + +/** + * @brief Get maximum EPSS percentile of referenced CVEs from a result iterator. + * + * @param[in] iterator Iterator. + * + * @return Maximum EPSS percentile. + */ +double +result_iterator_max_epss_percentile (iterator_t* iterator) +{ + if (iterator->done) return 0.0; + return iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 41); +} + +/** + * @brief Get the CVE with the maximum EPSS score from a result iterator. + * + * @param[in] iterator Iterator. + * + * @return CVE with maximum EPSS score. + */ +const gchar * +result_iterator_max_epss_cve (iterator_t* iterator) +{ + if (iterator->done) return NULL; + return iterator_string (iterator, GET_ITERATOR_COLUMN_COUNT + 42); +} + +/** + * @brief Get severity of CVE with maximum EPSS score from a result iterator. + * + * @param[in] iterator Iterator. + * + * @return Severity of CVE with maximum EPSS score. + */ +double +result_iterator_max_epss_severity (iterator_t* iterator) +{ + if (iterator->done) return 0.0; + return iterator_double (iterator, GET_ITERATOR_COLUMN_COUNT + 43); +} + /** * @brief Get CERT-BUNDs from a result iterator. * @@ -23776,7 +23919,7 @@ gchar ** result_iterator_cert_bunds (iterator_t* iterator) { if (iterator->done) return 0; - return iterator_array (iterator, GET_ITERATOR_COLUMN_COUNT + 36); + return iterator_array (iterator, GET_ITERATOR_COLUMN_COUNT + 44); } /** @@ -23790,7 +23933,7 @@ gchar ** result_iterator_dfn_certs (iterator_t* iterator) { if (iterator->done) return 0; - return iterator_array (iterator, GET_ITERATOR_COLUMN_COUNT + 37); + return iterator_array (iterator, GET_ITERATOR_COLUMN_COUNT + 45); } /** @@ -27954,6 +28097,8 @@ init_v2_delta_iterator (report_t report, iterator_t *results, report_t delta, extra_tables = g_strdup_printf (" JOIN comparison " " ON results.id = COALESCE (result1_id," " result2_id)" + " LEFT OUTER JOIN result_vt_epss" + " ON results.nvt = result_vt_epss.vt_id" " LEFT OUTER JOIN nvts" " ON results.nvt = nvts.oid %s," " LATERAL %s AS lateral_new_severity", @@ -58055,7 +58200,9 @@ type_build_select (const char *type, const char *columns_str, "results", "nvts"); - opts_table = g_strdup_printf (" LEFT OUTER JOIN nvts" + opts_table = g_strdup_printf (" LEFT OUTER JOIN result_vt_epss" + " ON results.nvt = result_vt_epss.vt_id" + " LEFT OUTER JOIN nvts" " ON results.nvt = nvts.oid %s," " LATERAL %s AS lateral_new_severity", original, diff --git a/src/manage_sql.h b/src/manage_sql.h index 9b6c7d81d..6e9b68a65 100644 --- a/src/manage_sql.h +++ b/src/manage_sql.h @@ -295,7 +295,7 @@ typedef struct /** * @brief Delta results columns offset for result iterator. */ -#define RESULT_ITERATOR_DELTA_COLUMN_OFFSET GET_ITERATOR_COLUMN_COUNT + 38 +#define RESULT_ITERATOR_DELTA_COLUMN_OFFSET GET_ITERATOR_COLUMN_COUNT + 46 /* Variables */ @@ -508,6 +508,9 @@ create_view_vulns (); void create_indexes_nvt (); +void +create_view_result_vt_epss (); + int config_family_entire_and_growing (config_t, const char*); diff --git a/src/manage_sql_nvts.c b/src/manage_sql_nvts.c index 302654bb7..d1e437577 100644 --- a/src/manage_sql_nvts.c +++ b/src/manage_sql_nvts.c @@ -1987,7 +1987,10 @@ update_nvts_from_vts (element_t *get_vts_response, sql ("ALTER TABLE nvts_rebuild RENAME TO nvts;"); create_view_vulns (); + create_indexes_nvt (); + + create_view_result_vt_epss (); } set_nvts_check_time (count_new_vts, count_modified_vts); diff --git a/src/manage_sql_secinfo.c b/src/manage_sql_secinfo.c index fdf76db8c..fd8c13c76 100644 --- a/src/manage_sql_secinfo.c +++ b/src/manage_sql_secinfo.c @@ -3707,6 +3707,7 @@ update_scap_end () /* View 'vulns' contains references into the SCAP schema, so it is * removed by the CASCADE. */ create_view_vulns (); + create_view_result_vt_epss (); } else sql ("ALTER SCHEMA scap2 RENAME TO scap;"); @@ -3745,6 +3746,7 @@ abort_scap_update () /* View 'vulns' contains references into the SCAP schema, so it is * removed by the CASCADE. */ create_view_vulns (); + create_view_result_vt_epss (); /* Update CERT data that depends on SCAP. */ update_cert_data (); } diff --git a/src/schema_formats/XML/GMP.xml.in b/src/schema_formats/XML/GMP.xml.in index 49fe30bff..770120a01 100644 --- a/src/schema_formats/XML/GMP.xml.in +++ b/src/schema_formats/XML/GMP.xml.in @@ -523,6 +523,9 @@ along with this program. If not, see . expiration_time issuer md5_fingerprint + sha256_fingerprint + subject + serial time_status @@ -558,6 +561,21 @@ along with this program. If not, see . MD5 fingerprint of the certificate text + + sha256_fingerprint + SHA-256 fingerprint of the certificate + text + + + subject + Name of the certificate + text + + + serial + Serial number of certificate + text + nvt @@ -1667,6 +1685,7 @@ along with this program. If not, see . severities cpe tags + epss refs @@ -1704,6 +1723,112 @@ along with this program. If not, see . Tags associated with the NVT 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 + + + + + refs List of references of various types for this vulnerability test @@ -7803,6 +7928,7 @@ END:VCALENDAR data_type data_column group_column + subgroup_column text_column group @@ -7826,6 +7952,11 @@ END:VCALENDAR The column the data is grouped by text + + subgroup_column + The column to further group the resources by + text + text_column A simple text column @@ -7982,10 +8113,8 @@ END:VCALENDAR Aggregate data for all resources of the selected type count - min - max - mean - sum + c_count + stats count @@ -7993,24 +8122,52 @@ END:VCALENDAR integer - min - Overall minimum value of the data column - text - - - max - Overall maximum value of the data column - text - - - mean - Overall arithmetic mean of the numeric values of the data - text + c_count + Cumulative number of resources + For overall this is always the same as count. + integer - sum - Overall sum of the numeric values of the data column - text + stats + Statistics of a data column + + + column + Name of the column the stats apply to + text + + min + max + mean + sum + c_sum + + + min + Overall minimum value of the data column + text + + + max + Overall maximum value of the data column + text + + + mean + Overall arithmetic mean of the numeric values of the data + text + + + sum + Overall sum of the numeric values of the data column + text + + + c_sum + Cumulative sum of the numeric values of the data column + For overall this is always the same as sum. + text + @@ -8394,6 +8551,7 @@ END:VCALENDAR method filter tasks + active owner @@ -8553,7 +8711,7 @@ END:VCALENDAR method - The method by which he alert must occur + The method by which the alert must occur text data @@ -8660,6 +8818,11 @@ END:VCALENDAR + + active + Whether the alert is active + boolean + filters @@ -9043,7 +9206,7 @@ END:VCALENDAR details - Whether to include additional information (e.g., tags) + Whether to include additional information (e.g. tags) boolean @@ -9083,6 +9246,7 @@ END:VCALENDAR permissions user_tags identifiers + type host os @@ -9169,6 +9333,7 @@ END:VCALENDAR type data deleted + name type @@ -9185,6 +9350,11 @@ END:VCALENDAR Whether the source has been deleted boolean + + name + User name when source type is User, else empty + boolean + os @@ -9204,13 +9374,20 @@ END:VCALENDAR + + type + Either "host" or "os" + + xsd:token { pattern = "host|os" } + + host A host severity detail - routes + routes severity @@ -9373,7 +9550,7 @@ END:VCALENDAR Hosts on which this OS has been detected as the best match - asset + asset asset @@ -9408,7 +9585,7 @@ END:VCALENDAR in_use - Whether any tasks are using the asset + Whether the asset is in use boolean @@ -10011,7 +10188,7 @@ END:VCALENDAR writable - Whether any tasks are using the config, including trashcan tasks + Whether the config may be modified boolean @@ -10162,10 +10339,11 @@ END:VCALENDAR nvt name + hr_name id type value - default + default alt @@ -10190,6 +10368,11 @@ END:VCALENDAR The compact name of the preference as used by the scanner name + + hr_name + The human readable name of the preference + name + id The ID of the preference @@ -10394,20 +10577,31 @@ END:VCALENDAR + + mabel + Full and fast - All NVT's; optimized by using previously collected information. - 2012-11-23T10:44:00+01:00 - 2013-01-23T10:44:00+01:00 + Most NVT's; optimized by using previously collected information. Version 20201215. + 2023-03-06T11:26:30-05:00 + 2024-01-23T10:02:26-05:00 + 0 + 1 + + + Everything + + - 4 + 56 1 - 12 + 88005 1 - 1 - 0 + 0 + scan + 0 ... @@ -10422,44 +10616,64 @@ END:VCALENDAR + + mabel + Full and fast - All NVT's; optimized by using previously collected information. + + Most NVT's; optimized by using previously collected information. Version 20201215. + + 2023-03-06T11:26:30-05:00 + 2024-01-23T10:02:26-05:00 + 0 + 1 + + + Everything + + - 4 + 56 1 - 12 + 88005 1 - 1 - - - Web Servers - - ... - + 0 + scan + 0 - Credentials - 8 - 8 + AIX Local Security Checks + 1 + 1 1 ... + 88014 + 88005 - - Services + + PostgreSQL Detection (TCP) 1 - Network connection timeout : + Postgres Username: + Postgres Username: entry - 5 + postgres + postgres ... + + + Web Servers + + ... + ... @@ -10575,6 +10789,11 @@ END:VCALENDAR ID of filter to use to filter query uuid + + details + Whether to include certificate info + boolean + scanners Whether to include a list of scanners using the credentials @@ -10648,11 +10867,13 @@ END:VCALENDAR certificate_info scanners targets - - public_key - package - certificate - + + + public_key + package + certificate + + owner @@ -11235,7 +11456,7 @@ END:VCALENDAR type - Type of single feed to get: NVT, CERT or SCAP + Type of single feed to get: NVT, CERT, SCAP or GVMD_DATA text @@ -11265,7 +11486,7 @@ END:VCALENDAR type - The type of feed: NVT, CERT or SCAP + The type of feed: NVT, CERT, SCAP or GVMD_DATA text @@ -11299,18 +11520,12 @@ END:VCALENDAR Present if a sync of this type is underway timestamp - user timestamp Time sync started text - - user - Name of user who is performing sync - text -