Solving Apollo 1337 from San Diego CTF 2021

Posted on Mon 10 May 2021 in CTF by 0xm4v3rick


The author note for this CTF challenge.

1
2
3
4
Apollo 1337
Hey there intern! We have a rocket launch scheduled for noon today and the launch interface is down. You'll need to directly use the API to launch the rocket. No, we don't have any documentation. And     quickly, our shareholders are watching!
Website
https://space.sdc.tf/

Visiting the website shows below page indicating frontend and backend status for the website.

landing

As mentioned in the challenge note we will need to use the API, so lets look at the requests generated. We see a status API showing information about the health of the services.

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
GET /api/status?verbose= HTTP/2
Host: space.sdc.tf
Cookie: __cfduid=d78c68cc9fdea32fb380f38f0ab1825a21620452158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://space.sdc.tf/
Te: trailers
Connection: close

Response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
HTTP/2 200 OK
Date: Mon, 10 May 2021 04:26:50 GMT
Content-Type: application/json; charset=utf-8
Etag: W/"62-Psu3r0I1RtWvipMsnje4R4c3EqQ"
Vary: Accept-Encoding
Via: 1.1 google
Cf-Cache-Status: DYNAMIC
Cf-Request-Id: 09f6202db000004ae6c5a60000000001
Expect-Ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=WDZCmPIVBqPrVD05F5RqOiX74KykdTJ7WtAttSKScS439NAfEhz34z63qWUzQU0jZCdY3cwvA3nsVH%2BZ8QCtuSYfqsGPJdYhYRB6f9A%3D"}],"group":"cf-nel","max_age":604800}
Nel: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
Cf-Ray: 64d0695c49ad4ae6-HYD
Alt-Svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

{"status":"health","longStatus":"Healthy. All routes are functioning properly.","version":"1.0.0"}

Not much information available here. You will notice a get parameter verbose with no value in the request. If you have used sqlmap or such tools you would notice verbosity usually ranges from 1 to n depending on the tool. So lets try providing 1 as value for the verbose parameter.

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
GET /api/status?verbose=1 HTTP/2
Host: space.sdc.tf
Cookie: __cfduid=d78c68cc9fdea32fb380f38f0ab1825a21620452158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://space.sdc.tf/
Te: trailers
Connection: close

Response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
HTTP/2 200 OK
Date: Sat, 08 May 2021 06:08:53 GMT
Content-Type: application/json; charset=utf-8
Etag: W/"e3-jMu7i7AkcsLoz7i0SVBQzLxLr4I"
Vary: Accept-Encoding
Via: 1.1 google
Cf-Cache-Status: DYNAMIC
Cf-Request-Id: 09ec30e10100002e779a2f6000000001
Expect-Ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=MJvYv4dKRoKmfL5Jv%2Fx%2B0QhcW5XFEffkA9JYcDYdVF4bdgi8cPDgqEb5Rng4OxAg4myNma5%2BPgzeK0TnSqtb8XNy%2FhwNaPKwzZZIAds%3D"}]}
Nel: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
Cf-Ray: 64c08414cb452e77-BOM
Alt-Svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

{
   "status":"health",
   "longStatus":"Healthy. All routes are functioning properly.",
   "version":"1.0.0",
   "routes":[
      {
     "path":"/status",
     "status":"healthy"
      },
      {
     "path":"/rocketLaunch",
     "status":"healthy"
      },
      {
     "path":"/fuel",
     "status":"healthy"
      }
   ]
}

Now we see a lot more information available to us, which includes 2 new endpoints - /rocketLaunch and /fuel. Lets query the /rocketLaunch endpoint.

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
GET /api/rocketLaunch HTTP/2
Host: space.sdc.tf
Cookie: __cfduid=d78c68cc9fdea32fb380f38f0ab1825a21620452158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://space.sdc.tf/
Te: trailers
Connection: close

Response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
HTTP/2 400 Bad Request
Date: Sat, 08 May 2021 05:39:30 GMT
Content-Length: 25
Etag: "19-SVOfstlPsXCdH4leAIVRqoZbYqg"
Via: 1.1 google
Cf-Cache-Status: DYNAMIC
Cf-Request-Id: 09ec16012700004ada98104000000001
Expect-Ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To: {"max_age":604800,"group":"cf-nel","endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=hI2Bwnxp19DS3Ab9SnIWpCZJ9s1wgOZhERFWg5VMdLFlDLH4R57JOb7MncfLZN3px%2Bb%2BDUX%2FMvK%2FU73NPDhWIt7hls1WGzFSbf%2BDqDI%3D"}]}
Nel: {"max_age":604800,"report_to":"cf-nel"}
Server: cloudflare
Cf-Ray: 64c0591508c54ada-HYD
Alt-Svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

request body must be json

We get an error suggesting that the request body must be json. So lets go ahead and do that. From here on the challenge is all about troubleshooting based on the errors we get. We add Content-Type: application/json and a json body to the request as well as making it a POST request since it requires a request body.

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
POST /api/rocketLaunch HTTP/2
Host: space.sdc.tf
Cookie: __cfduid=d78c68cc9fdea32fb380f38f0ab1825a21620452158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://space.sdc.tf/
Te: trailers
Connection: close
Content-Type: application/json
Content-Length: 9

{"x":"y"}

Response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
HTTP/2 400 Bad Request
Date: Sat, 08 May 2021 05:42:51 GMT
Content-Length: 20
Etag: "14-TBPT3N4WkgaLR8mc0RAXcU26ZAM"
Via: 1.1 google
Cf-Cache-Status: DYNAMIC
Cf-Request-Id: 09ec1911d300004aed96084000000001
Expect-Ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To: {"group":"cf-nel","endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=VqP%2FgdJ1wT7IEcEOMkYveux7cy%2F0pihioWDUg%2FO3ifwNRmyxT4gxi8vGEKSTRU8iwExg5mVjVqVOU2yIUwrP%2FSVaUXgVnNx99bDnEHA%3D"}],"max_age":604800}
Nel: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
Cf-Ray: 64c05dfc8c304aed-HYD
Alt-Svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

rocket not specified

We get another error asking us to add a rocket. So lets do that.

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
POST /api/rocketLaunch HTTP/2
Host: space.sdc.tf
Cookie: __cfduid=d78c68cc9fdea32fb380f38f0ab1825a21620452158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://space.sdc.tf/
Te: trailers
Connection: close
Content-Type: application/json
Content-Length: 14

{"rocket":"y"}

Response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
HTTP/2 400 Bad Request
Date: Sat, 08 May 2021 05:43:02 GMT
Content-Length: 41
Etag: "29-IJrJmM4FBfsLZi5Mi6TsnwYBLdY"
Via: 1.1 google
Cf-Cache-Status: DYNAMIC
Cf-Request-Id: 09ec193a8700004aed7433d000000001
Expect-Ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To: {"group":"cf-nel","endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=PcLh8HANUGlbAHr1kaVAUzvAv2qT0yCg5VMOY%2BFo39sa%2F7klwj3ss%2FttQBSyCE8%2BrXkWcXf4nvCt4J8OeyHE6ffQCU3k%2BBjSyJgPcMo%3D"}],"max_age":604800}
Nel: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
Cf-Ray: 64c05e3dab4f4aed-HYD
Alt-Svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

rocket not recognized (available: triton)

Since the rocket name is not correct, the error provides us with the name which we can use.

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
POST /api/rocketLaunch HTTP/2
Host: space.sdc.tf
Cookie: __cfduid=d78c68cc9fdea32fb380f38f0ab1825a21620452158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://space.sdc.tf/
Te: trailers
Connection: close
Content-Type: application/json
Content-Length: 19

{"rocket":"triton"}

Response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
HTTP/2 400 Bad Request
Date: Sat, 08 May 2021 05:43:11 GMT
Content-Length: 24
Etag: "18-4SZ7qR96LADOnmIcaDt9Ocnl2bE"
Via: 1.1 google
Cf-Cache-Status: DYNAMIC
Cf-Request-Id: 09ec195ebc00004aed5485e000000001
Expect-Ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To: {"group":"cf-nel","endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=jCFFlnfNbKeXYqFkEYm6CQrgxeyYH9sdDK8yk9NRI4eQYF0cgQLJsGVAWP417GFmaWoGSyKdBKgggJZokHLUNZZz2sDwYYAg9WW8KyA%3D"}],"max_age":604800}
Nel: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
Cf-Ray: 64c05e77993c4aed-HYD
Alt-Svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

launchTime not specified

Further error wants us to specify the launch time. After resolving few more errors such as launchTime not in hh:mm format and launchTime unapproved I was able to get a proper request going. Launch time is noon based on the challenge description. Any other time would result in unapproved error. We could have also tried the server date/time based on the response to see if it works if 12:00 was not working.

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
POST /api/rocketLaunch HTTP/2
Host: space.sdc.tf
Cookie: __cfduid=d78c68cc9fdea32fb380f38f0ab1825a21620452158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://space.sdc.tf/
Te: trailers
Connection: close
Content-Type: application/json
Content-Length: 40

{"rocket":"triton","launchTime":"12:00"}

Response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
HTTP/2 400 Bad Request
Date: Sat, 08 May 2021 05:45:43 GMT
Content-Length: 25
Etag: "19-mztLDY8Mq3B5NlRcCCz93/AW9/E"
Via: 1.1 google
Cf-Cache-Status: DYNAMIC
Cf-Request-Id: 09ec1bb20200004b0a94a2f000000001
Expect-Ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=vNRmX6pCeEMNbFdJFpBoha38myORB9sQFmLzXc%2FZpdhCQdYvYemzzkWTD2bYyZs3XCHAbShDYco72bq65PpQnXmHMzmKrPA79pUBmMk%3D"}],"max_age":604800,"group":"cf-nel"}
Nel: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
Cf-Ray: 64c0623009ce4b0a-HYD
Alt-Svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

fuel pumpID not specified

We now have to add pumpID value. We can get it by querying the /fuel endpoint or bruteforce the numerical value in this request. After trying available pumpIDs we get the one that works.

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
POST /api/rocketLaunch HTTP/2
Host: space.sdc.tf
Cookie: __cfduid=d78c68cc9fdea32fb380f38f0ab1825a21620452158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://space.sdc.tf/
Te: trailers
Connection: close
Content-Type: application/json
Content-Length: 51

{"rocket":"triton","launchTime":"12:00","pumpID":4}

Response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
HTTP/2 400 Bad Request
Date: Sat, 08 May 2021 05:47:00 GMT
Content-Length: 42
Etag: "2a-v5ExyC0zETE7PzLwSkFsUIYG9H0"
Via: 1.1 google
Cf-Cache-Status: DYNAMIC
Cf-Request-Id: 09ec1cddd000004af8321a7000000001
Expect-Ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=WYVsqRAJnviX%2FFIDgpJ0rK2EM9%2B%2Fjx6XFpN80Xc91zn6gWjEoL2y3sDIph3zLWiLPuMO0fy3NOs4xW0LUrflB%2BtyVL13ISK1N0cJ4Eg%3D"}]}
Nel: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
Cf-Ray: 64c0640fbda44af8-HYD
Alt-Svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

frontend authorization token not specified

Its now asking for a authorization token. So I went ahead and searched for token in the burp history. All the js files had a token as below

1
Token:"yiLYDykacWp9sgPMluQeKkANeRFXyU3ZuxBrj2BQ"

This is where I was stuck a bit and started thinking too much. I am used to dealing with auth tokens in request headers, hence I tried to add this token as a header. I tried various auth related headers and a few combinations of them but nothing worked. Than I took a step back and tried to approach it in a different way and thought of trying to add token as another json value with others and that worked resulting in below request and the flag.

Request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
POST /api/rocketLaunch HTTP/2
Host: space.sdc.tf
Cookie: __cfduid=d78c68cc9fdea32fb380f38f0ab1825a21620452158
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://space.sdc.tf/
Te: trailers
Connection: close
Content-Type: application/json
Content-Length: 106

{"rocket":"triton","launchTime":"12:00","pumpID":4,"token":"yiLYDykacWp9sgPMluQeKkANeRFXyU3ZuxBrj2BQ"}

Response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
HTTP/2 200 OK
Date: Sat, 08 May 2021 06:45:30 GMT
Content-Length: 50
Etag: "32-UMBTLpu/GF1MEJ81AK5sO97tnRU"
Via: 1.1 google
Cf-Cache-Status: DYNAMIC
Cf-Request-Id: 09ec526b3d0000d5932c28a000000001
Expect-Ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=Jf%2FOq5YiSaNHAG2nlYIxuXFPaaVftdWL0hK0QPfslFb98eji0%2BTuaT1S0%2FY2688hypXl6dZqHRMOUoWxuY4Fh%2B%2BWzAVQjxS1%2FmiTLXA%3D"}]}
Nel: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
Cf-Ray: 64c0b9bec975d593-BOM
Alt-Svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400

rocket launched. sdctf{0ne_sM@lL_sT3p_f0R_h@ck3r$}

This was how I approached the problem and solved it. Feel free to ping me on twitter for feedback or queries.
- 0xm4v3rick