Lack of TLS CertificateVerify
validation
Description
The Reclaim TLS implementation only validates the server's certificate chain when it receives a CertificateVerify
record. If the record is never received, the certificate chain is never validated and the connection proceeds normally. In particular, for TLS 1.2 connections where the server only uses its certificate for signing (all modern cipher suites), the CertificateVerify
record is never sent by the server. This means that the client never validates the server's certificate chain.
To test this vulnerability, we can use the following:
import { createClaim } from '@reclaimprotocol/reclaim-node'
const claim = await createClaim({
name: 'http',
params: {
url: 'https://self-signed.badssl.com/', // negotiates TLS 1.2
method: 'GET',
responseMatches: [{
type: 'contains',
value: '',
}],
responseRedactions: [],
},
secretParams: {
cookieStr: 'a'
},
ownerPrivateKey: '0x...'
})
console.log(claim)
This issue occurs in tls/src/make-tls-client.ts
:
case SUPPORTED_RECORD_TYPE_MAP.CERTIFICATE_VERIFY:
// ...
await verifyCertificateChain(certificates, host, rootCAs)
Impact
This allows an attacker who can intercept network packets between the node and the origin server to perform a man-in-the-middle (MITM) attack, compromising the confidentiality and integrity of all data transmitted.
Recommendations
The Reclaim TLS client should do the following:
When using TLS 1.2, validate the certificate chain after it receives a
ServerKeyExchange
message.When using TLS 1.3, refuse to proceed with the connection if it does not receive a
CertificateVerify
message.