Skip to content

Exploiting a vulnerability

When you use auth.py to send an authorization request to the server, the server calls verify_request to check the credentials and certificates in your request, and ultimately verifies your authorization proof. However, there is a bug in this implementation that can be exploited to allow anybody to convince the server to verify arbitrary access requests.

Familiarize yourself with this code, particularly the implementation of verify_request, to identify the vulnerability. Then provide an implementation of generate_exploit in src/exploit.py that exploits the vulnerability by constructing an AccessRequest for the resource <bigsecret.txt> that the server will successfully verify.

You will know that you have completed this task when the server returns the appropriate credential, as shown below (#andrewid will be replaced by your ID).

************************ Credential ************************
statement: open(#andrewid, <bigsecret.txt>)
signator: #root
signature: [63:7f:5f:b7:11:4e:b8:e7:55:dd:96:01:8d:13:88:75]
************************************************************

To see how AccessRequest objects are made, consult the documentation for AccessRequest.make_for_proof in crypto.py. You will need: * A proof of |- #root says open(#andrewid, <bigsecret.txt>) * The set of credentials needed to prove the above sequent, as Credential objects. * The set of certificates needed to verify the credentials needed for the request.

Note that the credentials provided with the lab will not allow you to prove the sequent listed above. As part of this exploit, you will need to generate one or more credentials and possibly one or more new certificates.

  • Credentials are constructed by Credential.from_formula. Given a formula P and agent #A, calling Credential.from_formula(P, #A) will return a Credential object representing the signature of P with the private key of #A. The only private key that you have access to is your own, and you should be able to complete the task by calling from_formula to sign with your own agent.
  • Certificates are constructed by calling Certificate.make_for_key with three arguments: a public key to create the certificate for, an agent to associate with the public key, and an agent whose private key will be used to sign the certificate.
  • You can also generate new users, with private keys stored locally in private_keys, by calling new_user in src/crypto.py. For example, calling new_user(Agent('#andrew'), Agent('#mfredrik')) will create an agent called #andrew, with a private key stored in private_keys/andrew.pem, and a certificate stored in certs/andrew.cert. The certificate will be signed with the private key of #mfredrik, so in order for this call to succeed, mfredrik.pem must be in the private_keys directory. This means that you can make new agents with certificates signed by your private key, but because you do not have private keys for #ca or #root, calling new_user(Agent('#ca'), Agent('#ca')) will fail. However, new_user does allow you to create a new user with a self-signed certificate, so calling new_user(Agent('#andrew'), Agent('#andrew')) will succeed, and will result in andrew.cert and andrew.pem being placed in the appropriate directories as described above.

You will also find code that generates AccessRequest objects in generate_request, in auth.py. You may be able to use this function to construct the request, but it may be more straightforward to use the code in that function as an example to work from.

Example API usage To recap the APIs for creating credentials and agents described above, suppose that an agent `#andrew` (hypothetically) wished to use a policy which required that the "normal" certificate authority, `#ca`, in addition to their own "private" authority `#andrew_ca`, *both* issued certificates for a key before they were willing to trust it. `#andrew` would begin by constructing a new agent to represent their private CA:
private_ca = new_user(Agent('#andrew_ca'), Agent('#andrew_ca'))
To have the private CA sign `#scotty`'s public key, they would load `#scotty`'s public key from their existing certificate, and construct a new certificate by signing it with the private CA's key:
scotty_normal_cert = Certificate.load_certificate(Agent('#scotty'))
scotty_private_cert = Certificate.make_for_key(scotty_normal_cert.public_key, Agent('#scotty'), Agent('#andrew_ca'))
This would yield a new certificate, stored in `scotty_private_cert`:
============================= Public Key Certificate =============================
key: [ae:dc:02:99:da:01:bd:ca:09:5f:6b:c8:90:b2:ff:e0]
agent: #scotty
*********************************** Credential ***********************************
statement: iskey(#scotty, [ae:dc:02:99:da:01:bd:ca:09:5f:6b:c8:90:b2:ff:e0])
signator: #andrew_ca
signature: [c9:b7:6c:35:1f:22:9d:35:27:78:5a:2b:86:09:59:c6]
**********************************************************************************
==================================================================================
`#andrew` might give them a credential that they are allowed to open a resource, created using `Credential.from_formula`:
scotty_cred = Credential.from_formula(parse('open(#scotty, <res>)'), Agent('#andrew'))
With this credential, `#scotty` could prove that they are able to access ``, according to `#andrew`'s policy, and construct an access request that contains all of the necessary credentials.
pf = prove(parse('ca(#ca), ca(#andrew_ca), ... |- #andrew says open(#scotty, <res>)'))
andrew_cert = Certificate.load_certificate(Agent('#andrew'))
normal_ca = Certificate.load_certificate(Agent('#ca'))
request = AccessRequest.make_for_proof(pf, Agent('#scotty'), [scotty_cred], [scotty_normal_cert, scotty_private_cert, andrew_cert, normal_ca, private_ca])
This would yield the following access request.
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Request <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
signature:
*********************************** Credential ***********************************
statement: (#andrew says open(#scotty, <res>))
signator: #scotty
signature: [6b:84:0b:93:b8:9d:a9:1b:3b:0b:52:96:0e:e2:d7:b3]
**********************************************************************************

credentials:
*********************************** Credential ***********************************
statement: open(#scotty, <res>)
signator: #andrew
signature: [94:92:3c:37:a5:65:ec:c4:a5:8c:71:6a:37:9d:45:73]
**********************************************************************************

certificates:
============================= Public Key Certificate =============================
key: [68:d7:6c:b7:95:fb:a4:f7:a7:4f:12:44:6f:27:c5:40]
agent: #ca
*********************************** Credential ***********************************
statement: iskey(#ca, [68:d7:6c:b7:95:fb:a4:f7:a7:4f:12:44:6f:27:c5:40])
signator: #ca
signature: [52:9d:bf:45:d3:78:be:73:c0:33:57:b8:9f:df:fe:ca]
**********************************************************************************
==================================================================================
============================= Public Key Certificate =============================
key: [09:e7:53:10:07:50:de:25:7f:bc:9f:f2:94:b1:51:7f]
agent: #andrew_ca
*********************************** Credential ***********************************
statement: iskey(#andrew_ca, [09:e7:53:10:07:50:de:25:7f:bc:9f:f2:94:b1:51:7f])
signator: #andrew_ca
signature: [97:3c:4c:c4:70:12:cb:5f:2b:fb:04:11:9f:4c:40:c0]
**********************************************************************************
==================================================================================
============================= Public Key Certificate =============================
key: [62:da:f9:fd:d6:6d:89:62:cc:f7:65:f4:5d:6f:e3:cb]
agent: #andrew
*********************************** Credential ***********************************
statement: iskey(#andrew, [62:da:f9:fd:d6:6d:89:62:cc:f7:65:f4:5d:6f:e3:cb])
signator: #ca
signature: [df:3c:72:1f:2e:1a:41:6b:31:34:e7:8e:b3:fc:88:ef]
**********************************************************************************
==================================================================================
============================= Public Key Certificate =============================
key: [5a:e0:7b:85:39:93:da:aa:e9:c3:ec:13:4c:f5:46:81]
agent: #scotty
*********************************** Credential ***********************************
statement: iskey(#scotty, [5a:e0:7b:85:39:93:da:aa:e9:c3:ec:13:4c:f5:46:81])
signator: #ca
signature: [48:e6:7f:c7:38:a5:4b:d2:49:dc:0d:62:0e:d3:44:92]
**********************************************************************************
==================================================================================
============================= Public Key Certificate =============================
key: [5a:e0:7b:85:39:93:da:aa:e9:c3:ec:13:4c:f5:46:81]
agent: #scotty
*********************************** Credential ***********************************
statement: iskey(#scotty, [5a:e0:7b:85:39:93:da:aa:e9:c3:ec:13:4c:f5:46:81])
signator: #andrew_ca
signature: [b0:8a:f0:35:a4:ec:60:57:e6:9b:04:15:b8:0a:35:05]
**********************************************************************************
==================================================================================
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>