Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[CISA KEV] Fix for updating existing vulnerabilities #3316

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

security-penguin
Copy link

80 and 100 are the same confidence level (1- Confirmed by other sources) but if the score is already at 100 the hardcoded 80 prevents the object being updated.

Passing the update=True is also required to update existing vulnerabilities, otherwise this connector has to create the vulnerability and won't update exisiting vulnerabilities.

Proposed changes

  • Change the hardcoded 80 confidence value to 100 to ensure all existing entries can be updated.
  • Added update=True so that exisiting vulnerabilities will be updated

Related issues

Checklist

  • [ x] I consider the submitted work as finished
  • [ x] I tested the code for its functionality using different use cases
  • [x ] I added/update the relevant documentation (either on github or on notion)
  • [ x] Where necessary I refactored code to improve the overall quality

Further comments

80 and 100 are the same confidence level (1- Confirmed by other sources) but if the score is already at 100 the hardcoded 80 prevents the object being updated.

Passing the update=True is also required to update existing vulnerabilities, otherwise this connector has to create the vulnerability and won't update exisiting vulnerabilities.
@helene-nguyen helene-nguyen added the community use to identify PR from community label Jan 20, 2025
@richard-julien richard-julien force-pushed the master branch 2 times, most recently from 9818df2 to 0f4b30d Compare February 4, 2025 14:35
@flavienSindou flavienSindou added the filigran support [optional] use to identify an issue related to feature developed & maintained by Filigran. label Feb 4, 2025
@vikingSec
Copy link

Note: my employer and I independently tested this fix and it worked to fix our issues!

@romain-filigran romain-filigran added this to the PRs backlog milestone Feb 6, 2025
@romain-filigran romain-filigran changed the title Fix for updating existing vulnerabilities [CISA KEV] Fix for updating existing vulnerabilities Feb 6, 2025
Copy link
Member

@Powlinett Powlinett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @security-penguin, thanks for your contribution!

I was not able to reproduce the issue, neither on OCTI 6.4.5 or OCTI 6.5.0 (latest) 🫤

We suppose that the issue you encounter might be due to the confidence policies specific to your OCTI instance. Please find links to the official documentation, I hope it'll help:

https://docs.opencti.io/latest/usage/reliability-confidence/
https://docs.opencti.io/latest/administration/users/
https://filigran.io/fine-tune-your-confidence-level-policy-in-opencti-6-2/

About the PR itself:

  • confidence level are now defined by confidence policies in OCTI settings and should/will be removed from STIX objects in connectors (see doc above)
  • send_bundle's update arg should be removed as it's not used anymore internally (I admit it's very misleading as there's no deprecation warning, sorry about that)

Please let us know if you managed to fix the issue thanks to confidence policies changes, and so if we can close this issue/PR 😇
Feel free to ping us for any help 🙏

Thanks!

@security-penguin
Copy link
Author

@Powlinett thank you for your reply. Unfortunately as other people have replicated this already and said this PR resolves their issue I would guess that your experience is due to my poor explanation of the testing rather than the issue not being present.

Your statement on confidence being a problem is part of this multi step issue.

There is 2 core issues at play that I called out the specific lines to in the issue so I would as you re-read that and fully walk through the explanation, but at a high level:

  1. This connector hard codes it confidence at 80, so even if you give the connector account a 100 confidence (as per the document you helpfully linked to) it would not modify any CVE brought in by any other connectors with a confidence of 100. This is confirmed by the documentation you provided

  2. As I have linked to in the issue ticket, by default the PyCTI API helper will not update any object unless the update flag is set to True. As a result the CVE object created by say the NVD CVE connector will not be updated with the KEV flag being set from false to true. This is because it is an already set property on the object.

So to test please:

  1. in any version please setup the NVD CVE connector with a confidence of 100
  2. Once the NVD CVE connector has finished then run the NIST KEV connector
  3. No existing CVEs will be updated with the KEV flag.

I'd kindly ask in future that you add what steps you took to try to reproduce the issue, especially after others has commented that it fixed their issue. This would make it easier to understand where there was a miscommunication and what I may have done wrong in my testing. Clearly in this case my reproduction steps weren't clear enough.

@animedbz16
Copy link
Contributor

animedbz16 commented Feb 11, 2025

I can confirm that this PR fixes our issue as we are currently seeing that the CISA KEV connector is not able to update existing Vulnerabilities to modify the CISA KEV value to True because Vulnerability objects are being imported / created by other connectors.

We can see some Vulnerabilites are created by the CVE connector, while others may be created by Mandiant connector (which is creating these vulnerabilites to default them with a TLP of Amber+Strict, which I have opened a separate issue here for (#3349)

Initially I was thinking that maybe the CISA KEV conenctor was not able to update the vulnerabilites due to the TLP level, but it appears to be related to this confidence score and/or by not passing the update_existing: true in the bundle to OpenCTI.

I can confirm that we have deployed these changes to our environment running 6.4.10 and they are functioning as we would expect.

If the "solution" here is to manually adjust every connector's default confidence so that connectors function as intended, this does not seem like a solution since the issue arises in how each of these connectors is suggested to be configured and as @security-penguin has mentioned, it is not possible to adjust this hard coded confidence score within this connector.

Here is code in CVE connector that is setting confidence scores that is also hard coded, so you can see how if this sets 100, then CISA connector is now unable to update the Vulnerability.

confidence=(
100 if description is not None and len(description) > 0 else 60
),

Edit:

Here is Mandiant in how it is setting confidence:

ATTRIBUTION_SCOPES = {
"confirmed": 100,
"suspected": 75,
"possible": 50,
}
def get_confidence(attribution_scope):
return ATTRIBUTION_SCOPES.get(attribution_scope, 25)

Basically this creates a race condition on which connector creates the Vulnerability first... and Mandiant connector should not be taking TLP:CLEAR CVE Vulnerabilities and modifying them to become AMBER+STRICT.

And then it just seems to be that every connector should just be 100 confidence so that they can update things... so what is the point of the confidence?

@Powlinett
Copy link
Member

Powlinett commented Feb 12, 2025

Hi @security-penguin and @animedbz16, thanks for your comments 🙏

You're right thinking that the issue is due to confidence levels and not to the TLP markings, let me precise a bit more:

  1. Passing a confidence level in a STIX object in connectors have been deprecated since OpenCTI 6.0, and we are currently removing them from all the connectors.

    • When a confidence level is set directly on a STIX object and sent in a bundle, OpenCTI has no way to detect if the confidence level change is coming from a connector or an end user on the OpenCTI platform. In this configuration, OpenCTI handles any STIX object with a confidence level set as if it was the action of an end user on the OpenCTI platform and will override this value in the database.
    • In the same time, confidence policies for Groups and Users have been released to help manage authorized actions directly through OpenCTI settings. It means that the confidence level of a connector doesn't need to be set as an environment variable during deployment anymore (or worse, hard-coded), but must be set as the confidence level of the user representing the connector (or the Connector group - depending on what fits your needs).
    • The issue you encounter is probably due to the fact that several connectors still set the confidence level on STIX objects - whether it's hardcoded or set as an environment variable (e.g. Mandiant). And so, in CISA KEV connector, you need to set Vulnerabilities' confidence to 100 because it's the only way to bypass any other confidence level that might have been set by other connectors and that's why it solved your issue.
    • The long-term solution though, is to remove confidence field from every STIX objects in every connectors and to manage STIX objects' confidence level thanks to the confidence policies defined in OpenCTI settings.
    • I suggest you remove the confidence fields from STIX objects, and as your connector's confidence level is set to 100 it should be equivalent to your fix. Of course, we also have to update other connectors to definitely tackle this type of issue ([All connectors] Update all connectors to be aligned with confidence level changes #1816)
  2. update arg is still in PyCTI code because there's still legacy code depending on it that have not been updated yet, but it is really deprecated and should be removed from all connectors (efb345a). Many connectors don't use this arg anymore but the entities are still updated though 👍

Please let me know if these explanations are helpful 😊

@animedbz16
Copy link
Contributor

animedbz16 commented Feb 12, 2025

@Powlinett Appreciate your response here as it provides a lot of background of how OpenCTI is leveraging the confidence value in the context of connectors and how connectors have leveraged this in the past through hard-coding of the confidence value directly inside the connector or in how some connectors will allow the user to override the confidence value by allowing it to be configured at runtime through the configuration file or environment variable.

Since as you also mention that OpenCTI allows for the creation of user accounts to also set confidence values, it can then become unclear to OpenCTI if the confidence value is being set from the STIX object, connector, or the connector user associated with running the connector.

This conversation is definitely beyond the scope of this PR, but when looking at the STIX 2.1 documentation, confidence is defined as a common property that exists on a STIX Object (https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_xzbicbtscatx), such that:

The confidence property identifies the confidence that the creator has in the correctness of their data. The confidence value MUST be a number in the range of 0-100.

Appendix A contains a table of normative mappings to other confidence scales that MUST be used when presenting the confidence value in one of those scales.

If the confidence property is not present, then the confidence of the content is unspecified.

The issue here seems to primary stem from how the OpenCTI platform is implementing the restriction of not allowing objects to be updated based upon the confidence level.

Specifically in this use case, if CISA KEV connector is attempting to update a Vulnerability to maintain the CISA KEV value of True or False, why should it matter what confidence value is set on an existing Vulnerability. If CISA KEV where to run and attempt to set a CISA KEV value on a Vulnerability that does not exist, it will create the vulnerability because it needs to have the object there to set its value, but should we then assume the confidence of the Vulnerability itself should be based on the confidence of the CISA KEV connector or its user?

The CISA KEV connector is 100% responsible for maintaining the CISA KEV True / False value, so under what scenario would it matter what confidence value the existing Vulnerability has or what confidence value the CISA KEV connector is configured with when this connector is responsible for maintaining that data independent of the confidence of the Vulnerability.

CISA KEV is attempting make this update to the Vulnerability:

stix_vuln = stix2.Vulnerability(
id=Vulnerability.generate_id(vuln_cve),
name=f"{vuln_cve}",
description=f"{description}",
created_by_ref=self.created_by_stix["id"],
created=f"{created}",
confidence=80 if description is not None and len(description) > 0 else 50,
object_marking_refs=[f"{marking_id}"],
custom_properties={"x_opencti_cisa_kev": True},
)

So its setting several things, but when we look at the STIX 2.1 docs for what is required for Vulnerabilities (https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_q5ytzmajn6re), only the type and name are required and id being required as a common property for STIX Core Objects, but should CISA KEV connector be updating the Vulnerability optional description, when the CVE connector is doing this?

It feels like confidence is being used as a way to "prevent" connectors from stepping on each others toes as multiple connectors may update information about the underlying object.

But here CISA KEV is is mainly needing to set the custom_properties={"x_opencti_cisa_kev": True}, so shouldn't OpenCTI be able to know that the connector which has a CONNECTOR_SCOPE=cisa potentially be able to always and only by itself be able to solely manage / maintain the custom_properties for its scope?

https://github.com/OpenCTI-Platform/connectors/blob/70fde6fe39b8c82cd7545f18d7915a7aad0144fa/external-import/cisa-known-exploited-vulnerabilities/docker-compose.yml#L10C1-L10C29

The CONNECTOR_SCOPE value for external-import connectors has not really made sense to me since most of the time these have just be the name of the connector, but sometimes some connectors were using STIX Object Types, much like how the internal-enrichment connectors define the STIX object types within CONNECTOR_SCOPE, which then allows OpenCTI to know that a particular internal-enrichment connector should presented as a possible enrichment when viewing a specific object.

It seems that external-import connectors should define their own CONNECTOR_SCOPE so that this could be used as a reference to tell OpenCTI that this connector is allowed to manage any custom_properties within its scope... regardless of the overall confidence value that may be optionally set?

@Powlinett
Copy link
Member

Powlinett commented Feb 13, 2025

Hi @animedbz16 🙂


Specifically in this use case, if CISA KEV connector is attempting to update a Vulnerability to maintain the CISA KEV value of True or False, why should it matter what confidence value is set on an existing Vulnerability.
If CISA KEV where to run and attempt to set a CISA KEV value on a Vulnerability that does not exist, it will create the vulnerability because it needs to have the object there to set its value, but should we then assume the confidence of the Vulnerability itself should be based on the confidence of the CISA KEV connector or its user?

It matters because one connector could be considered more or less trustworthy than another.
Let's say Mandiant connector has a global confidence level of 80 (set on the user representing the connector in OpenCTI settings), then the Vulnerabilities created by this connector will have a confidence level of 80 (based on connector's confidence level).
Now, if CISA KEV connector has a global confidence level of 60 (also set on the user representing the connector in OpenCTI settings), should it be trusted to update the data of Vulnerabilities imported from Mandiant? Probably not, and that's why update/delete actions are allowed only for a user/connector with a confidence level greater than or equal to the entity's confidence level.


The CISA KEV connector is 100% responsible for maintaining the CISA KEV True / False value, so under what scenario would it matter what confidence value the existing Vulnerability has or what confidence value the CISA KEV connector is configured with when this connector is responsible for maintaining that data independent of the confidence of the Vulnerability.

We can set connector's different confidence levels for specific entity types, but we can't set different confidence levels for specific entity fields . As CISA KEV connector is responsible to set x_opencti_cisa_kev boolean but also other values like description, OpenCTI have to decide if an existing vulnerability can be updated by this connector based on its confidence level, without any distinction of which fields are actually updated. Plus, some customers will use CVE connector alongside CISA KEV one, but some others won't., so we can't just remove the vulnerabilities description provided by CISA KEV.


It feels like confidence is being used as a way to "prevent" connectors from stepping on each others toes as multiple connectors may update information about the underlying object.

Not only for this purpose, but yes indeed, it prevents trusted data to be replaced by data from less trustworthy source. If 2 connectors have the same confidence level though, the last update will overwrite any previous value.


The CONNECTOR_SCOPE value for external-import connectors has not really made sense to me since most of the time these have just be the name of the connector, but sometimes some connectors were using STIX Object Types, much like how the internal-enrichment connectors define the STIX object types within CONNECTOR_SCOPE, which then allows OpenCTI to know that a particular internal-enrichment connector should presented as a possible enrichment when viewing a specific object.

The main reason behind CONNECTOR_SCOPE env var is that trying to register a connector into OpenCTI without a scope results to an error:

Traceback (most recent call last):
  File "C:\Users\Username\filigran\connectors\external-import\cisa-known-exploited-vulnerabilities\src\main.py", line 330, in <module>
    connector = Cisa()
                ^^^^^^
  File "C:\Users\Username\filigran\connectors\external-import\cisa-known-exploited-vulnerabilities\src\main.py", line 32, in __init__
    self.helper = OpenCTIConnectorHelper(config)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Username\filigran\connectors\external-import\cisa-known-exploited-vulnerabilities\venv\Lib\site-packages\pycti\connector\opencti_connector_helper.py", line 958, in __init__
    connector_configuration = self.api.connector.register(self.connector)
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Username\filigran\connectors\external-import\cisa-known-exploited-vulnerabilities\venv\Lib\site-packages\pycti\api\opencti_api_connector.py", line 160, in register
    result = self.api.query(query, connector.to_input())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Username\filigran\connectors\external-import\cisa-known-exploited-vulnerabilities\venv\Lib\site-packages\pycti\api\opencti_api_client.py", line 371, in query
    raise ValueError(value_error)
ValueError: {'name': 'FUNCTIONAL_ERROR', 'error_message': 'Validation against schema failed on attribute [connector_scope]: this mandatory field cannot be nil'}

But in fact, external import connectors don't leverage scope at a functional level (unlike enrichment connectors). That's why most of the time, an external import connector's CONNECTOR_SCOPE will be set to the name of the connector itself, or sometimes it describes the type of entities that'll be handled by the connector, but for documentation purpose only.


It seems that external-import connectors should define their own CONNECTOR_SCOPE so that this could be used as a reference to tell OpenCTI that this connector is allowed to manage any custom_properties within its scope... regardless of the overall confidence value that may be optionally set?

custom_properties refers to any properties that are not in STIX spec and are not specific to one connector in particular. But I do understand that entities fields update could benefit from more granularity, maybe a suggestion of improvement to submit?



Let us know how you want to solve this PR so we can help with the other connectors 😇

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
community use to identify PR from community filigran support [optional] use to identify an issue related to feature developed & maintained by Filigran.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CISA KEV Connector does not update x_opencti_cisa_kev when CVE is already in the platform
7 participants