HTX Investigator's Challenge 2021
Last updated
Last updated
The HTX Investigator's Challenge is a Singaporean CTF competition hosted by the Home Team Science and Technology Agency (HTX).
The event ran for 12 hours from 8am to 8pm on 20 December 2021, and included various cybersecurity challenges.
My team, Social Engineering Experts, topped the scoreboard, with a total of 43,380 points.
We didn't qualify for the prizes due to eligibility criteria. The official champions for the HTXIC 2021 are the good folks from T0X1C V4P0R.
Since this has already sent some shockwaves in the local CTF community, and will inevitably lead to more questions in the next few days, I thought I'd spend some time writing about the situation and addressing some anticipated questions.
The eligibility criteria for the HTXIC challenge are as follows.
The team comprised of 5 members currently serving our National Service (NS) with the army, and all of us were Junior College (JC) graduates.
We were not 100% sure whether Institutes of Higher Learning included Junior Colleges, and seeing our friends who are also currently serving NS - but having graduated from polytechnics - signing up, we were eager to participate as well.
We decided to put in our registration regardless, declaring our JCs and year of graduation (2019) in the registration form, with the assumption that the shortlisting process would take the eligibility criteria into consideration.
Post-CTF, we found out that we were ineligible for the challenge. However, the organizers have allowed us to claim that we emerged "top of the scoreboard".
Overall, we did have fun with HTXIC. The people we met at HTX have been nothing but nice to us and were receptive to our feedback.
We mentioned that we would love to see more local CTFs that cater to NSFs like us, and hope that future CTFs could consider this.
I've added brief writeups for some challenges.
This challenge required us to find out the account balance of the admin.
Looking carefully at the responses received from the web application, we would realise that the /checkbalance
endpoint is vulnerable to a class of vulnerabilities known as XS Leaks.
If the queried amount is more than the actual balance in the user's account, the user is redirected. Otherwise, no redirection occurs. It would be possible to get the length of the window's history to check whether this redirection is occurred, allowing us to perform an "XS Search" on the user's account balance.
To obey the Same Origin Policy (SOP), we would need to do the following:
From the exploit server, open http://10.8.201.87:5000/checkbalance?amount=${num}
as a new window.
Wait for the site to load. Depending on the balance, the window may be redirected to /
.
Change the window's location back to the exploit server, so that both the original and new windows are of the same origin
We can now check the window's history.length
attribute to determine if a redirect occurred in step 2.
After some trial and error, here's my final script.
On line 25, I started with larger intervals, then slowly narrowed down the exact value by decreasing the interval range.
The Tenant and Management login pages were both vulnerable to SQL injection.
Using SQLMap, we could dump the users table in the database.
Taking a closer look at the users, we could see that each one has a different role. Logging in as different users allows us to perform various actions. As the vendor user, we have the ability to add to the food listing.
This allows us to upload an image, and the validation for this is flawed. It seemed to be checking for the existence of the .jpg
extension, but using .jpg.php
passes this check and allows us to upload a PHP webshell that we can access at http://10.8.201.87/HTXIC/vendor/images/
.
Using a PHP reverse shell payload, we were able to get a bash shell into the system.
The systemctl
binary had the SUID bit set, allowing us to escalate to root privileges by creating a service.
Performing a directory scan reveals that there is a /cmd.php
endpoint.
This seems to allow us to perform command injection, but there appears to be a blacklist filter. Fortunately, the cat cmd.php
command works, allowing us to view the blacklist.
To overcome the blacklist, we used a base64-encoded payload, which is then decoded by Python on the server.
There is a blacklist filter for #
and =
. Using test' or 1-- -
gives us account credentials, but logging in with these does not give us the flag.
We could use a UNION
based injection to dump the database and get the flag.
username=test' or 1 UNION SELECT *, null from flag-- -&password=test' or 1 UNION SELECT *, null from flag-- -
We were given CSV files containing network traffic data, as well as a shapefile containing cameras in Singapore. We are tasked to find where most of the attacks are originating from, and the number of cameras within a 1.3km radius.
First, we obtain the most common src_ip
, and find its corresponding latitude and longitude.
After, we can parse the shapefile using geopandas, and use the haversine formula to determine the great-circle distance between each camera and the src_ip
location based on the latitude and longitudes.
You are given a dataset consisting the basic information of a list of individuals (refer to DATABASE_FINAL). Some of these individuals have been identified to participate in terrorism related activities.
Using the dataset, fit a model identifying FINAL_OUTCOME =1 using all the variables (refer to variable list). Using the fitted model, apply it on the list of Grand Prix participants to screen out the top 5 individuals who are likely to participate in terrorism related activities based on the highest probabilities score (refer to GRAND_PRIX_DATA).
I initially tried to train my own model from scratch, but I realised that the fitted model coefficients were already given to us. (what was the point of the training data then?)
We could thus simply create a simple linear regression model:
Prepare for some ugly hardcoding...
What's curious though, was that the numerical variables weren't normalized. I initially normalized both the numerical variables, but only after much trial and error did I arrive at the "correct" model.
We are given the string:
%109y69&o1#01U11_6(v32%E1,&01^b88E1@05e-1$1!6n32\T1#16!R10%4i&114!c69.K_1!01~e*@d
Extracting only alphabetical characters yields yoUvEbEenTRicKed
. However, between these letters are numbers that represent ASCII codes.
The decoded message is mEet eXit thrEe
.