[crazy?] completely neutered self-signed certificate verification administering akash hosting providers?

Undescribed Horrific Abuse, One Victim & Survivor of Many gmkarl at gmail.com
Wed Jul 19 21:09:08 PDT 2023


Of course I should talk with akash, which is my plan, but I'm posting
here at the moment.

Akash is a blockchain hosting provider. They recently added support
for GPU compute. I'm writing code to verify connections to akash nodes
by renters. Provider certificates are registered on-chain and used for
client communications, but I don't understand how the protocol
produces security.

The code clients use for verifying a provider certificate when
executing administrative actions is here:
https://github.com/akash-network/provider/blob/44c85af39a56a43830efbdcbe7a2fd83c1d9776b/gateway/rest/client.go#L290L355

I don't understand how the verification provides security. -> I am not
very familiar with TLS and X509 and am very, very, very confused. <-

The first and primary authentication is that the common name is the
account address in bech32 format. It reports a hijacked certificate if
this is not the case:

>	// validation
>	var prov sdk.Address
>	if prov, err = sdk.AccAddressFromBech32(cert.Subject.CommonName); err != nil {
>		return errors.Wrap(err, "tls: invalid certificate's subject common name")
>	}
>
>	// 1. CommonName in issuer and Subject must be the same
>	if cert.Subject.CommonName != cert.Issuer.CommonName {
>		return errors.Wrap(err, "tls: invalid certificate's issuer common name")
>	}
>
>	if !c.addr.Equals(prov) {
>		return errors.Errorf("tls: hijacked certificate")
>	}

I don't understand how this helps prove the provider owns the
certificate. Couldn't anybody set the common name of a certificate to
an account address? Wouldn't it be important here to sign material
with the private key of the account, rather than using the address?

Then it verifies the certificate is active on-chain, but it compares
only the serial number rather than a fingerprint:

>	// 2. serial number must be in
>	if cert.SerialNumber == nil {
>		return errors.Wrap(err, "tls: invalid certificate serial number")
>	}
>
>	// 3. look up certificate on chain. it must not be revoked
>	var resp *ctypes.QueryCertificatesResponse
>	resp, err = c.cclient.Certificates(
>		context.Background(),
>		&ctypes.QueryCertificatesRequest{
>			Filter: ctypes.CertificateFilter{
>				Owner:  prov.String(),
>				Serial: cert.SerialNumber.String(),
>				State:  "valid",
>			},
>		},
>	)
>	if err != nil {
>		return errors.Wrap(err, "tls: unable to fetch certificate from chain")
>	}
>	if (len(resp.Certificates) != 1) || !resp.Certificates[0].Certificate.IsState(ctypes.CertificateValid) {
>		return errors.New("tls: attempt to use non-existing or revoked certificate")
>	}

I don't understand how this helps prove the provider owns the
certificate. Couldn't anybody set the serial number of a certificate
to the value active on-chain? Wouldn't it be necessary to use a digest
of the certificate to verify it is the same one?

Finally, it places the certificate in a pool of its own, and uses that
same pool to verify that same certificate:

>	certPool := x509.NewCertPool()
>	certPool.AddCert(cert)
>
>	opts := x509.VerifyOptions{
>		DNSName:                   c.host.Hostname(),
>		Roots:                     certPool,
>		CurrentTime:               time.Now(),
>		KeyUsages:                 []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
>		MaxConstraintComparisions: 0,
>	}
>
>	if _, err = cert.Verify(opts); err != nil {
>		return errors.Wrap(err, "tls: unable to verify certificate")
>	}

I don't understand how this helps prove the provider owns the
certificate. Couldn't anybody craft a certificate that verifies
itself? Shouldn't there be some cryptographic path between the
on-chain material and the off-chain material?

Note: every provider and every provider's hostname can be enumerated
on-chain, so an attacker can easily identify if there are providers
that are easy to intercept, or enumerate all providers to intercept
them all. (Might be this cli command, haven't verified:
https://github.com/akash-network/docs/blob/master/cli/provider-services_query_provider_list.md
)

To me it looks like this system could have the function of making it
very easy to intercept and mutate traffic between all akash providers
and clients, optionally presenting a fake provider to clients that
pretends to be the real one.


More information about the cypherpunks mailing list