Description
### Impact
When using client authentication method "private_key_jwt" [[1]](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication), OpenId specification says the following about assertion `jti`:
> A unique identifier for the token, which can be used to prevent reuse of the token. These tokens MUST only be used once, unless conditions for reuse were negotiated between the parties
Hydra does not seem to check the uniqueness of this `jti` value. Here is me sending the same token request twice, hence with the same `jti` assertion, and getting two access tokens:
```
$ curl --insecure --location --request POST 'https://localhost/_/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=c001d00d-5ecc-beef-ca4e-b00b1e54a111' \
--data-urlencode 'scope=application openid' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion=eyJhb [...] jTw'
{"access_token":"zeG0NoqOtlACl8q5J6A-TIsNegQRRUzqLZaYrQtoBZQ.VR6iUcJQYp3u_j7pwvL7YtPqGhtyQe5OhnBE2KCp5pM","expires_in":3599,"scope":"application openid","token_type":"bearer"}⏎
$ curl --insecure --location --request POST 'https://localhost/_/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=c001d00d-5ecc-beef-ca4e-b00b1e54a111' \
--data-urlencode 'scope=application openid' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion=eyJhb [...] jTw'
{"access_token":"wOYtgCLxLXlELORrwZlmeiqqMQ4kRzV-STU2_Sollas.mwlQGCZWXN7G2IoegUe1P0Vw5iGoKrkOzOaplhMSjm4","expires_in":3599,"scope":"application openid","token_type":"bearer"}
```
### Patches
This issue is patched in 0.31.0.
### Workarounds
Do not allow clients to use `private_key_jwt`.
### References
https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication
Affected Software
Related
{"id": "GHSA-V3Q9-2P3M-7G43", "vendorId": null, "type": "github", "bulletinFamily": "software", "title": "Token reuse in Ory fosite", "description": "### Impact\n\nWhen using client authentication method \"private_key_jwt\" [[1]](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication), OpenId specification says the following about assertion `jti`:\n\n> A unique identifier for the token, which can be used to prevent reuse of the token. These tokens MUST only be used once, unless conditions for reuse were negotiated between the parties\n\nHydra does not seem to check the uniqueness of this `jti` value. Here is me sending the same token request twice, hence with the same `jti` assertion, and getting two access tokens:\n\n```\n$ curl --insecure --location --request POST 'https://localhost/_/oauth2/token' \\\n --header 'Content-Type: application/x-www-form-urlencoded' \\\n --data-urlencode 'grant_type=client_credentials' \\\n --data-urlencode 'client_id=c001d00d-5ecc-beef-ca4e-b00b1e54a111' \\\n --data-urlencode 'scope=application openid' \\\n --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \\\n --data-urlencode 'client_assertion=eyJhb [...] jTw'\n{\"access_token\":\"zeG0NoqOtlACl8q5J6A-TIsNegQRRUzqLZaYrQtoBZQ.VR6iUcJQYp3u_j7pwvL7YtPqGhtyQe5OhnBE2KCp5pM\",\"expires_in\":3599,\"scope\":\"application openid\",\"token_type\":\"bearer\"}\u23ce\n$ curl --insecure --location --request POST 'https://localhost/_/oauth2/token' \\\n --header 'Content-Type: application/x-www-form-urlencoded' \\\n --data-urlencode 'grant_type=client_credentials' \\\n --data-urlencode 'client_id=c001d00d-5ecc-beef-ca4e-b00b1e54a111' \\\n --data-urlencode 'scope=application openid' \\\n --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \\\n --data-urlencode 'client_assertion=eyJhb [...] jTw'\n{\"access_token\":\"wOYtgCLxLXlELORrwZlmeiqqMQ4kRzV-STU2_Sollas.mwlQGCZWXN7G2IoegUe1P0Vw5iGoKrkOzOaplhMSjm4\",\"expires_in\":3599,\"scope\":\"application openid\",\"token_type\":\"bearer\"}\n```\n\n### Patches\n\nThis issue is patched in 0.31.0.\n\n### Workarounds\n\nDo not allow clients to use `private_key_jwt`.\n\n### References\n\nhttps://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication", "published": "2021-05-24T16:57:52", "modified": "2023-08-29T23:07:24", "epss": [{"cve": "CVE-2020-15222", "epss": 0.00193, "percentile": 0.56905, "modified": "2023-12-02"}], "cvss": {"score": 5.8, "vector": "AV:N/AC:M/Au:N/C:P/I:P/A:N"}, "cvss2": {"cvssV2": {"version": "2.0", "vectorString": "AV:N/AC:M/Au:N/C:P/I:P/A:N", "accessVector": "NETWORK", "accessComplexity": "MEDIUM", "authentication": "NONE", "confidentialityImpact": "PARTIAL", "integrityImpact": "PARTIAL", "availabilityImpact": "NONE", "baseScore": 5.8}, "severity": "MEDIUM", "exploitabilityScore": 8.6, "impactScore": 4.9, "acInsufInfo": false, "obtainAllPrivilege": false, "obtainUserPrivilege": false, "obtainOtherPrivilege": false, "userInteractionRequired": true}, "cvss3": {"cvssV3": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "NONE", "baseScore": 8.1, "baseSeverity": "HIGH"}, "exploitabilityScore": 2.8, "impactScore": 5.2}, "href": "https://github.com/advisories/GHSA-v3q9-2p3m-7g43", "reporter": "GitHub Advisory Database", "references": ["https://github.com/ory/fosite/security/advisories/GHSA-v3q9-2p3m-7g43", "https://nvd.nist.gov/vuln/detail/CVE-2020-15222", "https://github.com/ory/fosite/commit/0c9e0f6d654913ad57c507dd9a36631e1858a3e9", "https://github.com/ory/fosite/releases/tag/v0.31.0", "https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication", "https://pkg.go.dev/vuln/GO-2021-0110", "https://github.com/advisories/GHSA-v3q9-2p3m-7g43"], "cvelist": ["CVE-2020-15222"], "immutableFields": [], "lastseen": "2023-12-02T17:28:57", "viewCount": 125, "enchantments": {"dependencies": {"references": [{"type": "cve", "idList": ["CVE-2020-15222"]}, {"type": "osv", "idList": ["OSV:GHSA-V3Q9-2P3M-7G43", "OSV:GO-2021-0092", "OSV:GO-2021-0110"]}, {"type": "prion", "idList": ["PRION:CVE-2020-15222"]}, {"type": "veracode", "idList": ["VERACODE:30665"]}]}, "score": {"value": 7.9, "vector": "NONE"}, "backreferences": {"references": [{"type": "cve", "idList": ["CVE-2020-15222"]}, {"type": "kitploit", "idList": ["KITPLOIT:3449843613571411531"]}]}, "exploitation": null, "affected_software": {"major_version": [{"name": "github.com/ory/fosite", "version": 0}]}, "epss": [{"cve": "CVE-2020-15222", "epss": 0.00175, "percentile": 0.53076, "modified": "2023-05-01"}], "vulnersScore": 7.9}, "_state": {"dependencies": 1701544388, "score": 1701538863, "affected_software_major_version": 0, "epss": 0}, "_internal": {"score_hash": "a8fe60ba7e66da0c511e7ec1a8467154"}, "affectedSoftware": [{"version": "0.31.0", "operator": "lt", "ecosystem": "GO", "name": "github.com/ory/fosite"}]}
{"osv": [{"lastseen": "2023-08-29T23:18:18", "description": "### Impact\n\nWhen using client authentication method \"private_key_jwt\" [[1]](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication), OpenId specification says the following about assertion `jti`:\n\n> A unique identifier for the token, which can be used to prevent reuse of the token. These tokens MUST only be used once, unless conditions for reuse were negotiated between the parties\n\nHydra does not seem to check the uniqueness of this `jti` value. Here is me sending the same token request twice, hence with the same `jti` assertion, and getting two access tokens:\n\n```\n$ curl --insecure --location --request POST 'https://localhost/_/oauth2/token' \\\n --header 'Content-Type: application/x-www-form-urlencoded' \\\n --data-urlencode 'grant_type=client_credentials' \\\n --data-urlencode 'client_id=c001d00d-5ecc-beef-ca4e-b00b1e54a111' \\\n --data-urlencode 'scope=application openid' \\\n --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \\\n --data-urlencode 'client_assertion=eyJhb [...] jTw'\n{\"access_token\":\"zeG0NoqOtlACl8q5J6A-TIsNegQRRUzqLZaYrQtoBZQ.VR6iUcJQYp3u_j7pwvL7YtPqGhtyQe5OhnBE2KCp5pM\",\"expires_in\":3599,\"scope\":\"application openid\",\"token_type\":\"bearer\"}\u23ce\n$ curl --insecure --location --request POST 'https://localhost/_/oauth2/token' \\\n --header 'Content-Type: application/x-www-form-urlencoded' \\\n --data-urlencode 'grant_type=client_credentials' \\\n --data-urlencode 'client_id=c001d00d-5ecc-beef-ca4e-b00b1e54a111' \\\n --data-urlencode 'scope=application openid' \\\n --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \\\n --data-urlencode 'client_assertion=eyJhb [...] jTw'\n{\"access_token\":\"wOYtgCLxLXlELORrwZlmeiqqMQ4kRzV-STU2_Sollas.mwlQGCZWXN7G2IoegUe1P0Vw5iGoKrkOzOaplhMSjm4\",\"expires_in\":3599,\"scope\":\"application openid\",\"token_type\":\"bearer\"}\n```\n\n### Patches\n\nThis issue is patched in 0.31.0.\n\n### Workarounds\n\nDo not allow clients to use `private_key_jwt`.\n\n### References\n\nhttps://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 8.1, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.2}, "published": "2021-05-24T16:57:52", "type": "osv", "title": "Token reuse in Ory fosite", "bulletinFamily": "software", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "PARTIAL", "baseScore": 5.8, "vectorString": "AV:N/AC:M/Au:N/C:P/I:P/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 4.9, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-15222"], "modified": "2023-08-29T23:07:22", "id": "OSV:GHSA-V3Q9-2P3M-7G43", "href": "https://osv.dev/vulnerability/GHSA-v3q9-2p3m-7g43", "cvss": {"score": 5.8, "vector": "AV:N/AC:M/Au:N/C:P/I:P/A:N"}}, {"lastseen": "2022-09-23T18:58:53", "description": "Uniqueness of JWT IDs (jti) are not checked, allowing the JWT to be\nreplayed.\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "HIGH", "baseScore": 8.1, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.2}, "published": "2021-07-28T18:08:05", "type": "osv", "title": "GO-2021-0110", "bulletinFamily": "software", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "PARTIAL", "baseScore": 5.8, "vectorString": "AV:N/AC:M/Au:N/C:P/I:P/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 4.9, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-15222"], "modified": "2022-09-23T18:53:37", "id": "OSV:GO-2021-0110", "href": "https://osv.dev/vulnerability/GO-2021-0110", "cvss": {"score": 5.8, "vector": "AV:N/AC:M/Au:N/C:P/I:P/A:N"}}, {"lastseen": "2022-05-30T14:14:01", "description": "Uniqueness of JWT IDs (jti) are not checked, allowing the JWT to be\nreplayed.\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "HIGH", "baseScore": 8.1, "privilegesRequired": "NONE", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N", "userInteraction": "REQUIRED", "version": "3.1"}, "impactScore": 5.2}, "published": "2021-04-14T20:04:52", "type": "osv", "title": "GO-2021-0092", "bulletinFamily": "software", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "PARTIAL", "baseScore": 5.8, "vectorString": "AV:N/AC:M/Au:N/C:P/I:P/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "acInsufInfo": false, "impactScore": 4.9, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-15222"], "modified": "2022-05-13T18:33:00", "id": "OSV:GO-2021-0092", "href": "https://osv.dev/vulnerability/GO-2021-0092", "cvss": {"score": 5.8, "vector": "AV:N/AC:M/Au:N/C:P/I:P/A:N"}}], "prion": [{"lastseen": "2023-11-22T01:21:27", "description": "In ORY Fosite (the security first OAuth2 & OpenID Connect framework for Go) before version 0.31.0, when using \"private_key_jwt\" authentication the uniqueness of the `jti` value is not checked. When using client authentication method \"private_key_jwt\", OpenId specification says the following about assertion `jti`: \"A unique identifier for the token, which can be used to prevent reuse of the token. These tokens MUST only be used once, unless conditions for reuse were negotiated between the parties\". Hydra does not seem to check the uniqueness of this `jti` value. This problem is fixed in version 0.31.0.", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 8.1, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.2}, "published": "2020-09-24T17:15:00", "type": "prion", "title": "Design/Logic Flaw", "bulletinFamily": "NVD", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "PARTIAL", "baseScore": 5.8, "vectorString": "AV:N/AC:M/Au:N/C:P/I:P/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 4.9, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-15222"], "modified": "2021-11-18T17:51:00", "id": "PRION:CVE-2020-15222", "href": "https://www.prio-n.com/kb/vulnerability/CVE-2020-15222", "cvss": {"score": 5.8, "vector": "AV:N/AC:M/Au:N/C:P/I:P/A:N"}}], "veracode": [{"lastseen": "2022-07-26T16:29:48", "description": "github.com/ory/fosite uses insecure session management. The vulnerability exists as it fails to validate the uniqueness of this jti value in `private_key_jwt` client authentication method, allowing an attacker to send the same token request twice with the same `jti` assertion to get two access tokens.\n", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 8.1, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.2}, "published": "2021-05-25T05:21:21", "type": "veracode", "title": "Insecure Session Management", "bulletinFamily": "software", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "PARTIAL", "baseScore": 5.8, "vectorString": "AV:N/AC:M/Au:N/C:P/I:P/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 4.9, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-15222"], "modified": "2021-11-18T20:11:53", "id": "VERACODE:30665", "href": "https://sca.analysiscenter.veracode.com/vulnerability-database/security/1/1/sid-30665/summary", "cvss": {"score": 5.8, "vector": "AV:N/AC:M/Au:N/C:P/I:P/A:N"}}], "cve": [{"lastseen": "2023-12-02T15:29:51", "description": "In ORY Fosite (the security first OAuth2 & OpenID Connect framework for Go) before version 0.31.0, when using \"private_key_jwt\" authentication the uniqueness of the `jti` value is not checked. When using client authentication method \"private_key_jwt\", OpenId specification says the following about assertion `jti`: \"A unique identifier for the token, which can be used to prevent reuse of the token. These tokens MUST only be used once, unless conditions for reuse were negotiated between the parties\". Hydra does not seem to check the uniqueness of this `jti` value. This problem is fixed in version 0.31.0.", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "HIGH", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "HIGH", "privilegesRequired": "NONE", "baseScore": 8.1, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N", "version": "3.1", "userInteraction": "REQUIRED"}, "impactScore": 5.2}, "published": "2020-09-24T17:15:00", "type": "cve", "title": "CVE-2020-15222", "cwe": ["CWE-345"], "bulletinFamily": "NVD", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.6, "obtainAllPrivilege": false, "userInteractionRequired": true, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "MEDIUM", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "PARTIAL", "baseScore": 5.8, "vectorString": "AV:N/AC:M/Au:N/C:P/I:P/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "NONE"}, "impactScore": 4.9, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2020-15222"], "modified": "2021-11-18T17:51:00", "cpe": [], "id": "CVE-2020-15222", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-15222", "cvss": {"score": 5.8, "vector": "AV:N/AC:M/Au:N/C:P/I:P/A:N"}, "cpe23": []}]}