Skip to content

Finding Public Keys

ticarpi edited this page Nov 14, 2019 · 2 revisions

In order to try some of the attack paths for tokens with asymmetric encryption we may need to find the Public Key. There are a number of possible methods.

SSL key reuse

In some cases the token might be signed with the Private Key of the webserver's SSL connection. Grabbing the x509 and extracting the Public Key from SSL is simple enough:

$ openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem
$ openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem

API exposure

To verify a token a service may expose the Public Key via an API endpoint such as "/API/v1/keys". The location should be listed is the API's docs (if you have access to them), or you may see traffic to this endpoint in your proxy history.

JWKS common locations

Another common alternative is exposing a key (or set of keys) in a JWKS (JSON Web Key Store) file. Some common locations for this would be:

  • /.well-known/jwks.json
  • /openid/connect/jwks.json
  • /jwks.json
  • /api/keys
  • /api/v1/keys

Other locations for JWKS files may be platform-specific, so it's worth checking the docs (or Googling).

URL from jku claim or x5u claim

There are two standard header claims that can direct the service to the Public Key for verification:

  • jku - a claim pointing towards the JWKS URL
  • x5u - a claim pointing towards the X509 certificate location (could be in a JWKS file)

Clues from iss claim

A further claim that could hint at the location of a Public Key is the iss payload claim, which shows the name or URL of the body that created the JWT, which may be an external service or API. Use this information to direct your search towards the likely locations for the Issuer's Public Key.

Verbose errors

Finally you may just be lucky enough to spot a verbose error from the application (or external Issuer). To try to force an error you should submit a mixture of 'broken' tokens:

  • Broken signature
  • Invalid Base64 format (leave in the padding)
  • Invalid Base64 mode (use URL-safe, standard, out URL-encoded)
  • Invalid claim values (wrong URLs, etc.)
  • Invalid algorithms ("alg")
  • Invalid JWT type ("typ")
  • Wrong value mode (string/integer/float/Boolean)
  • Try anything you can think of to break it!