Cookie Consent by
Home NSEC 2021 - Knight's Siege Arsenal Monitoring Hub

NSEC 2021 - Knight's Siege Arsenal Monitoring Hub


The Knight's Siege Arsenal ended up being my favorite track during the CTF event. This particular track followed an infrastructure approach, with multiple nodes, pivots, privilege escalations, all while integrating the overall medieval storyline of North Sectoria. Personally that immersion, not to mention quality of the designed challenge, is what elevated this particular track to favorite status and I am looking forward to further challenges by the designer - Simon Décosse.

Time to dive into the challenge itself!

Flag 1 - Brute

Right off the bat we are presented with the layout of the infrastructure we will be working with. There are three separate instances: a central management server, and two agent nodes.

Additionally we are able to get a copy of the instance configurations. Without knowing more about the Manager/Agent interaction this seems like a good area to start on.

Immediately it becomes evident that we are working with an OSSEC Host Intrusion Detection system. Looking at the central manager configuration we can get a good idea of what to expect.

Based on the main page and this configuration we can see that eastern-trebuchet.ctf should have a getflag endpoint. Additionally under the ossec active responses it seems that we should be able to execute the action by triggering rule 102. To do so we will need to trigger rule 101, which is requesting the getflag url (rule 101), with a frequency of 3 within a short timeframe.

Alright let's spam ctrl+f5 a few times and see if this works out.

Flag 2 - RCE

Looking back the ossec configuration we notice another rule set created for agent 002, or southern-ballista.ctf. This time we see from the central configuration that exec-logger is triggered by rule 201, which looks for invalid ssh users and leverages a syslog subprocess to write them down to users.txt.

First let's see it in action by SSH'ing over as a user that shouldn't exist. Sure enough this gets captured by the rule set.

Excellent! Now in theory we should be able to reach the user.txt endpoint since according to it is storing it at /opt/user.txt. Let's take a look (keep in mind this was a previous screenshot when using kali as the username).

At this point in theory if we are able to include command execution into the user portion of our SSH request, which gets logged to /var/log/auth.log it should be run by subprocess and return the output to our /opt/user.txt. Let's try that out with a simple ls and see if it works.

Great, we should be able to make some progress from here.

Note - this is where we ended going off rails. Our initial attempts of geting a reverse shell we're not working and we ended finishing this flag and flag 3 leveraging "hardmode" of not having a shell. While not the most efficient nor speediest of solution I rather enjoyed taking this approach and making it work.

After a bit of poking and experimenting a few facts were gathered.

  • Slashes were being stripped in the commands
  • Spaces were hit or miss, sometimes working, sometimes being stripped
  • Environment variables were leveragable

With the third point in mind we were able to find a nice alternative to using whitespaces by using ${IFS} and using ${PWD} as an alternative to slashes in our user's environment variables.

Now with more freedom to explore around we found the location of flag.txt, however cat seemed to also be stripped in the command execution. Instead we leveraged head and were able to acquire the second flag.

Flag 3 - RSA

In theory by this point we should have had shell access, but as mentioned above we liked inflicting even more pain on ourselves and do this entire next section without remote shell access!

In our sysadmin user's homedirectory we find an interesting notepad folder. By checking the leftover bash history we can see that there is something happening with this notepad folder worth investigating.

Alright let's get all of this over to our local machine for further analysis. The encrypt/decrypt files and the public key were easy enough to list out as we had previously done, however the .enc files were binary/hex based and weren't playing nice. In this case we base64 encoded them all and brought them back over to convert back to original format.

If we combine this with the files and public key we brought over:

It starts to become clear we will be factoring our 256 bit RSA public key.

A quick search later and I found this blog that would ultimately give us everything we need to recover the private key. Without spending too much time going over the RSA details we are looking for four factors: p, q, n, e. We have n (modulus) and e (exponent) from the public key and our challenge is to factor n into two prime numbers: p, q. This is the security premise of RSA, that factoring p and q from n should be too computationally complex to be broken "quick enough". However in this case since our key is a small 256 bit this factoring should be feasible.

Getting a copy of yafu installed I put in our modulus and exponent then kicked it off. It took less than 100 seconds to properly factor our private key information.

With the information in place I put together a small script based on the blog post to generate our private key file.

Let's check to see if our new private key is valid.

Looking good! As an extra validation we also can see our modulus is correct. All that is left is to run the decrypt script using our newly minted private key.

Drat, not a flag! Oh well this is still a step forward and gives us a hint with where to look next - the SSH keys.

While the private key wasn't directly present on sysadmin's home, there was a nice backup file that was definitely enticing.

Sure enough extracting the contents of the file gives a nice, juicy private key.

All that was left was to use it and SSH over to central-dovecot.ctf and claim our flag!

As an extra perk this also means we have a shell connection... no more user.txt abuse here!

Flag Bonus - Cred Spray

This one was definitely a gimme, but could easily have been overlooked. With our SSH credentials from the previous flag, if we took a step back and logged on to eastern-trebuchet.ctf there was an additional flag.txt right in the home directory for us.

Flag 5 - PHP

Ah the final flag... this one ended up being a pain and really shouldn't have been. Full disclosure I was only able to finish it after the submissions closed however I still wanted to finish it up out of principal at this point.

Initially I believed the escalation path would be related to CVE-2014-5284 and I ended up losing a lot of time seeing how I could make this work.

What I should have realized quickly while running through the usual priv-escalation enumeration scripts was a world-writeable PHP file in /var/www/html/download. Owned by www-data this would allow us a lateral pivot on the host. Why does this matter? As sysadmin we were not able to access the main ossec folders like /var/ossec however on further investigation our good old www-data user was part of the ossec group. Hum... that should have been more evident to me.

By modifying index.php we can arbitrarily run anything as www-data. Apparently I have something against reverse shells as I went with a direct flag capture approach - by reading the file directly.

And thus brings to an end the track!


As I mentioned at the start this was by far my favorite track during this year's NSEC CTF. It is possible that the infrastructure based scenario tugged at my infra background, and I really hope to see similar style challenges in future events.

I want to thank Simon Décosse for an excellent challenge, and the entire NSEC team for making this event a huge success. I'm already looking forward to next year's edition!

As always thanks folks, until next time!

This post is licensed under CC BY 4.0 by the author.