oasis-tcs / csaf

OASIS CSAF TC: Supporting version control for Work Product artifacts developed by members of TC, including prose specifications and secondary artifacts like meeting minutes and productivity code
https://github.com/oasis-tcs/csaf
Other
148 stars 39 forks source link

Proposal for inclusion of a signature field #241

Open lukehinds opened 3 years ago

lukehinds commented 3 years ago

I would like to propose adding a signature / pubkey field to the csaf_2.0/json_schema to provide non-repudiation and some level of integrity verification of the claim.

This way it will allow assurance that the claims within the schema have a degree of tamper resistance. If someone is able to tamper with a csaf vuln report they could use that to mislead over vulnerability data and perform some level of targeted attack.

On the later note, we would be interested in having rekor consume csaf data and validate the signing and store the claims into an immutable , tamper resistant transparency log. We already have a custom schema interface which would mean the csaf claims can be version controlled and referenced https://github.com/sigstore/rekor/tree/main/pkg/types

rekor supports multiple signing tools, so we have flexibility there as well (pgp, minisign, x509, ssh, openidconnect etc)

Anyone not wanting to validate can ignore the field, likewise anyone not wanting to sign could mark it as NULL / leave empty , but those who do want guarantees can still get them.

mprpic commented 3 years ago

I'm a little confused as to how you imagine that field would be used. If I were to generate a CSAF document, then sign that document, and put that signature as a value of a hypothetical signature field then verifying that signature involves first stripping that field from the document and using the value to verify the modified document.

Normally, file signatures are provided in separate files so that the signature represents the state of the file in its complete form. You wouldn't expect to find the checksum of an ISO within the ISO itself, no? Maybe I'm just not understanding the ask here correctly :-)

lukehinds commented 3 years ago

@mprpic sorry, should have clarified. The signature would be generated by each value part of all key / values concatenated together and hashed and signed. So it is an attached signature, but not a signature of the entirety of the file itself (which is not possible as you rightly point out).

tschmidtb51 commented 3 years ago

Thank you for the suggestion.

I agree that signing CSAF documents is important to accomplish the goal of integrity protection. Given that there are a lot of signature wrapping attacks and signatures may not always be produced within the same (online) tool (e.g. Secvisogram, I prefer detached signatures as suggested in https://github.com/oasis-tcs/csaf/issues/152#issuecomment-733804674:

All files shall have a cryptographic hash (e.g. SHA-512 or SHA-3) as well as an OpenPGP signature file which are provided under the same file name which is extended by the appropriate extension. Example: File names

   Value of document/tracking/id: "Example Company - 2019-YH3234"
   File name of CSAF document: example_company_-_2019-yh3234.json
   File name of hash file: example_company_-_2019-yh3234.json.sha512
   File name of signature file: example_company_-_2019-yh3234.json.asc

Is rekor able to handle detached signatures?

lukehinds commented 3 years ago

Is rekor able to handle detached signatures?

Yes, very much, both in fact. The below is the generic type:

https://github.com/sigstore/rekor/blob/main/tests/rekor.json

So this could easily become:


{
    "kind": "CSAF",
    "apiVersion": "0.0.1",
    "spec": {
        "signature": {
            "format": "pgp",
            "content": "iQHKBAABCAA0FiEEcgCUXG78adj6hGUJJrfBoJ04pHoFAl+86RwWHGxoaW5kc0Bwcm90b25tYWlsLmNvbQAKCRAmt8GgnTikejcHC/9yyGEPh2D+MnNR8I8w0sfWChc6pGAQoS6qk/sfC/9GvF4OC7RIy6OwLr/lxyEZbOP2ngYjh/s5KjKxhZyApwwg13LmcbazGnXc3E76J55LoTfwoRa9fupH/M6HI56VFKwnu+AbMNW1s+DM47r7i5nIN6IX9kMpDe3B9XTUULff/yNUv0XtXU+VAf8ndF1w117YVWxf8TnU/HWvX74URQPN+syuyqK/NO1H1KhBVTzcIYd5H6kJu300jgkDypyyqQpd/pJYVwfeY8fCOaeCpfIPjKQ/4enCsAeBgKsAwfIbor8WiE86KoANYqROaW7uqiN+VPadbWVeN6bMpRIdEq8+NKQGlepSCRqbkVg4VKGOPgB3h5WbY9U1O1FVDnXyt7kWdEPEZjBX+V4DawshvNe5LIyqH5hJ1QNAFd0UStqKQt8EUZ/gAtQiXSGbxM1ACoYL9HblKW5b+kj/onKghekFoCoAfhMwRRqR5g/TS/Pc2/ztwYTIuhpQQfMXziTm64g=",
            "publicKey": {
                "content":"LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCgptUUdOQkYrY0lNMEJEQUNhOEc3UkQydjNtaXdNdHhWYVppM0pCVnVlVkFxSEtDNGVLb01TNUhNQ1JvK0haVlJBCjcwWG1zVHBYMVoxZ1pRdXVDMEdEWTI2aEJoZWpBcTNoeDJydjYvOHE5MEJ2V0dIOXRWZUdwTDFzYUltNTJnRVIKWHlWZ2d6NWtBQzBTNnZNbjdkcjJldEJrV1dQK09qMDVTMDJZWkJUWWd4cE9ieWVjVVNjcUtOVGpzbFpRQkgyZApTSHVrM28yWjdoTTQ5VTBsN3piV3c0b0lUK2xBUmNzYWpRVHdXamxpYVBEL0hSalQyblJPaEloaXRlZC93Z3l6CnlkSXE1ZTZzMThWTGNUNzVxV25yWlhOUFdGd2YyNVJYWTN1dGtXK0dXNW5RZU44MFEya1JFZ2t4RnM1QWQ1V1oKdkU3dDgvaHg1em1zbFo0dGZGNHNpM1FaZUlRQmFjWWJ3eE1QU0RmOW9GR3hkR0ZUODg5d0pMR2dXbXIxVGtQTQpjTjA2d3hBUkd0eE4wejYxRkpUaWpMV1JialczdW5JOWhjUWNVbE4vUSsxNm90SHBlS1ZnNG9XMDBDcnZXT0Q2CnFrTGNNRDQ5eVVEOGZTR0IrUkVuaUJhODlDOWtRVTRTS2Rnc0xML1ErSksrU3k5S21JRHJtMWE0RGZQMXBzZmUKTGphcnpzVlpmS1VIZndjQUVRRUFBYlFpVEhWclpTQklhVzVrY3lBOGJHaHBibVJ6UUhCeWIzUnZibTFoYVd3dQpZMjl0UG9rQjFBUVRBUWdBUGhZaEJISUFsRnh1L0duWStvUmxDU2Ezd2FDZE9LUjZCUUpmbkNETkFoc0RCUWtECndtY0FCUXNKQ0FjQ0JoVUtDUWdMQWdRV0FnTUJBaDRCQWhlQUFBb0pFQ2Ezd2FDZE9LUjZaMWtMLzFJSzB2ZGUKWlg1cjVTZWJOeFRJTlNBQXZZa3JLUnlKNWY3bE9NOWdMR0l1YzJGb05VbmpWUVQwcklHOTAxOWg0OHBDeTkxZgpYakREUk1ZOWd6RldXQ2dHblhoMWhXSTNNN0JKRjZZRTZ1NkRYR3N2dVVwR3JOZVpBRzZra2F6QXVBbm5WMGtDCjA4em9SckFaQ3ZscGFacnlkOGl0YityVitRS3A3QXcybEFJSDFlNmR3TTRSTEZqdmZrOExKWHhqSkFvUG13NmwKTHcxOGM3b1c2UkxPOVFYUThlTTZyMnZISHBtMFR1ZHZaeWFmTnVDMzJHRGxNWTR1MFYxRGI4THN5bVBzQWh1QQoySno0L0tQcTZ1S3dJdG1WSzRwbmRmRUR1NkQxVG9vRFlYaXB0WWFmZHZVMzNwVVF4d0hvZlRUZkU1elp3MlBlCmxIM25aZHNnSFhHUHhKTExNcU9wVzRDL2NNNlpRVmdZU3RWcjBudlU2NitRalF2c2tVWlIwNmRkRXpuQnBHSnMKdHBtajlBZS9HUlk4RU5uTjkvMkdmRXVydHozZEtOVVpvak15MTUzamNHMFUxenpoMTE1V0o3dDh3SEJ1NFM0cAowZ0UrUkFxeXRBY0laRGQyTlNOcno4VnI5RkU5eCtmYXQ5RVJsYm5kQUJFNWlWOHNLMCtGYW5Xd2dia0JqUVJmCm5DRE5BUXdBdEJvdGhmY1J6cjN4cjNQOXA3UUNNd0t1aW9udk1DbThXZ3dOUzRDcGhxbzVOT3IyaU1qa0xQMEoKb21nSkxWWDVOK2Jydjh5NEg4cllQd0tCMTZvL2hBOEliR2JwWXltM0ZjeWtUd2NiV2J0UFRMRXRkQ1VQTFlURApOQzVMR0pwZzNlODZZZlF0QU42L01uWnlZT21sRHgyV0d0dExkbXNBU0dWdXg2QVZKcUl2K3gwNlVLSkVtSzN0CmpsRVZLeWcxMlJFenllNUlUNnFFU0dwT3pvMllsV1VxSVR3L0FhUFEyWnhVYXh2WUZvVU9jd2djZG5Ia2dzaEkKT245aC9OSFVtUDMyV1F2cWtRTXVVYVBJTlJzQzgzS3ZUREdseWZTSFZGek1hNGhETWhFY1h6NGFjaW5kNVdUZQp6eUxnWmhPYjdjTmVDeDR4Y3J0UEI2VTdCUi9GVkx6TEJsQXp1emppRWhZd0pvM0FPTXFGb1I1bUFxaGx1dE5PCnNzeW9mYnFUZ0diU0xkamJYUC9hRXRnejJNVjluL29jMVNCOEhlWk8vMTdKeWduenJ1SUt5Ky9sT1dPenQralYKVkZwVnloMXVlOGxGN3ltS1I0dHNsK2lJVmJxblB2cE1oTE9JQnFYRm4yZ01Da0dvSkx5N09IbzJXQUVKR2x0MwpTd3BicmpqMUFCRUJBQUdKQWJ3RUdBRUlBQ1lXSVFSeUFKUmNidnhwMlBxRVpRa210OEdnblRpa2VnVUNYNXdnCnpRSWJEQVVKQThKbkFBQUtDUkFtdDhHZ25UaWtlaW5pREFDRUFma1pxLzRScDJhTkE0ZGJvSjdVRlhET2FSa1YKOU1Lb0VaRnFUTU5vdkRMNXhoTWxnbFBQdS9sK2RoVGd4ZGVKOUVWSG9lenRiODk2VS9wT3VCUnNuOVZ0VzRZLwpqZWlXN0V5TlhBZC9PcnZuRmJ4KzdpWExxdXBaSkpGVGkvajlSaFZZTnNtbDdzZWJUUGVCbkdEQTkxcWJDNHhICnBRVkRDdWp4NjlWeE81RTFMU29oQ00rTy81dkxCbThpMW8vbmJGbWJ5N1ZDeUtlUkRmaHRmOW5DODRxc0U5R3EKVTcvTFNpazliZnhNV2JwcTh5a250bVMzYTBzemM0YlZGcGV6QnBtTmIwQVZjQitUbTlnV21FemhpTHM2RktBTgpJbnFOdVh1Qkw5UENhYzcrbVUrYzJtQmdHT1JHZDFkWk8zUkM4OXpGM3hCQlluQ09lNWNBTUZsYzFYR3NsbHNJCmR6ZHJkWHZiTkJ6L2o3MXB1TjhvRlltL1hiVmNpZU8wVGZRaURjVHQ4S2lpUjlUQUQ5L1A1OTNSTWxMT0dTOHAKaHZKYmlGb1pmWEhjbHNaRkhtOERRUWE5NElad1RCOG00Z0JWME0yWFN2ZEhvMzBsc3FqdFphWmlTclJoNHJzaApuMTRwYkFhVGRhS0VQY3Z0dWZiVXVXMElqWWQya3BJVC90Zz0KPU9naHIKLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLQo="
             }
        },
        "data": {
            "url": "https://example.com/csaf_2.0/json_schema.json",
            "hash": {
                "algorithm": "sha256",
                "value": "45c7b11fcbf07dec1694adecd8c5b85770a12a6c8dfdcf2580a2db0c47c31779"
            }
        }
    }
}

So the above entry would be the digest of the csaf file and the public key / signature. The url is only used to retreive the file, this can also be sourced locally / inline (base64 encoded) as well and uploaded . This signing would be validated before entry is allowed (so we have some form of non-repudation). At a later point, someone could then perform an inclusion proof to make sure the entry is present or rekor could act as a tamper resistant audit system.

GPG is used for the above, but its very worth while considering x509.

tschmidtb51 commented 3 years ago

GPG is used for the above, but its very worth while considering x509.

IMHO: As CSAF is related to the CERT/PSIRT/security researcher community it is more likely that they will accept GPG than x509.

Anyway, wouldn't we need for x509 a full (public) PKI?

lukehinds commented 3 years ago

GPG is used for the above, but its very worth while considering x509.

IMHO: As CSAF is related to the CERT/PSIRT/security researcher community it is more likely that they will accept GPG than x509.

Anyway, wouldn't we need for x509 a full (public) PKI?

agree, that makes sense. As long as the users public key is well known (one of the short falls of GPG is web-of-trust / in person signing and the post covid world).

santosomar commented 3 years ago

Good point @lukehinds ! Although, I also agree with @tschmidtb51 , most PSIRT teams, security researchers, and coordination centers currently use GPG. The web-of-trust is also another concern. However, this may also highlight the use case of https://securitytxt.org/ and references to GPG/openPGP keys, etc...

lukehinds commented 3 years ago

https://securitytxt.org looks good, and nice to see any moves to progress matters. storing these things on a non tamper proof medium such as a website can be problematic though (thinking of the linux mint attack where the digests got swapped out on the hacked site).

sthagen commented 3 years ago

Nit: @lukehinds I assume that

GPG is used for the above, but its very worth while considering x509.

was intended to say PGP?

sthagen commented 3 years ago

I still am a bit confused as what exactly should be signed.

The signature would be generated by each value part of all key / values concatenated together and hashed and signed

That reads to me like one of many overlapping conventions out in the wild - because canonical JSON is not here (yet) ...

Some implementations host insert order (de)serializations others are still not able to combine key structure storage with insert order conservation.

... and reading "[...]like blockchain, without the large electricity bills." makes me šŸ˜• for today - but no worries, tomorrow is another day.

zmanion commented 3 years ago

Whether PGP or X.509, users can decide to trust one or more PKIs, webs of trust, TOFU, or verify individual keys manually... we won't solve that problem here, but should pick a functional signing mechanism and probably one of PGP or X.509. The trust model is beyond our control.

zmanion commented 3 years ago

My expertise being limited to 30 minutes of searching: Are JOSE/JWS/etc something that exists and we can use?

https://jose.readthedocs.io/en/latest/ https://www.iana.org/assignments/jose/jose.xhtml

Maybe this is not widely used/adopted?

lukehinds commented 3 years ago

I still am a bit confused as what exactly should be signed.

The signature would be generated by each value part of all key / values concatenated together and hashed and signed

That reads to me like one of many overlapping conventions out in the wild - because canonical JSON is not here (yet) ...

Some implementations host insert order (de)serializations others are still not able to combine key structure storage with insert order conservation.

... and reading "[...]like blockchain, without the large electricity bills." makes me šŸ˜• for today - but no worries, tomorrow is another day.

It's very simple and hardly out in the wild. Consider the manifest as an envelope , there is a body section (which contains the sbom) and the body is the section that is signed. TUF does this with its root role : https://raw.githubusercontent.com/theupdateframework/tuf/develop/tests/repository_data/repository/metadata/root.json

This then solves the whole issue of where to stick detached sigs and how to map them to that which they sign.

zmanion commented 3 years ago

I was about to say that a detached PGP signature of a JSON text file is OK and might be a simple enough starting point... but at least one concern is (trailing) spaces, tabs, etc. Simple PGP can tell you if you got the exactly the same file, but not if you got the same data with whitespace differences.

tschmidtb51 commented 3 years ago

It's very simple and hardly out in the wild. Consider the manifest as an envelope , there is a body section (which contains the sbom) and the body is the section that is signed. TUF does this with its root role : https://raw.githubusercontent.com/theupdateframework/tuf/develop/tests/repository_data/repository/metadata/root.json

This then solves the whole issue of where to stick detached sigs and how to map them to that which they sign.

We could probably put that on the roadmap for discussions for later versions of CSAF.

For CSAF 2.0, I guess it is the easiest to use what the people are already familiar with. In terms of signatures in the vulnerability disclosure field that is PGP... There are tools out there to create and check those signature and they are well understood. We don't have to provide anything new - it can be used "out-of-the-box" with known tools. Hopefully, this aids in adoption of the standard.

tschmidtb51 commented 3 years ago

I was about to say that a detached PGP signature of a JSON text file is OK and might be a simple enough starting point...

I agree here. A detached PGP signature is a simple starting point. By using this you can easily create a human-readable website (just by rendering the JSON data as e.g. Secvisogram does in its Preview tab) without having to decode base64 on the fly.

but at least one concern is (trailing) spaces, tabs, etc. Simple PGP can tell you if you got the exactly the same file, but not if you got the same data with whitespace differences.

To solve this problem, we need a defined (and well-understood) way of generating a canonical JSON. However, this introduces the possibility for a lot of attacks. E.g. a malicious JSON might have keyword multiple times - what is then checked for the signature might not be the same as the business logic uses...

Therefore, I suggest to use the easy solution (for now)...

lukehinds commented 3 years ago

Honest good intentioned view:

If you start off with PGP you're quickly going to hit it's limits and then the pain of a migration plan stemming its lack of any decent transparent key management. The issue being, there will be thousands of projects needing to generate SBOMS (and a lot of them also setting up keys for the first time) and they are all going to need a way to distribute public keys for users to verify integrity / non repudiation, which with PGP means some sort of web of trust or none at all / close your eyes and TOFU (which all to easily becomes the majority).

Key distribution will be done in a mish mash of different approaches, download it from a website (a medium that gets hacked all the time), or they will get stashed into a readme on a git repo, some will use Key servers. Users will to a degree often have to hope for the best, that it is who it is claimed to be. You're going to end up thinking, we need some sort of infra to manage this for us.

Go with x509 (even with its own shortcomings. You then you have PKIX which has a modern day applicable key management approach that can be leveraged.

sthagen commented 3 years ago

@santosomar I propose to close this issue without action as the discussion brought up valuable insights but no change within a month and I do not see any material changes to the editorial drafts before public review of CSD 01.