Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
We have been using some CTF regex recently, and I thought it was worth sharing.
During our first DerbyCon CTF, we ended up missing a few flags that could have gotten us the win.
While that stung, we wanted to make sure it didn’t happen again. For this specific issue, we had our regex guru, RecViking, get to work on a solution.
In the end, he whipped together a one-liner for us to use, and I ended up finding at least one new flag with it during our DerbyCon 9 victory!
If you’ve never competed in a DerbyCon CTF, then the following is an example of what the flags look like.
NiceIDORExploitYo349
These flags are camel case, long, and have some numbers in the middle/at the end.
You can find the command that RecViking came up below to find these for us. Note that this will search the entire disk, but you can narrow it down to specific directories if you’d like.
egrep -r -o -e "[A-Z]([A-Z0-9]*[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*" / | sed -n '/.\{12\}/p' | sort | uniq
The grep command will look for camel case patterns that might resemble flags, and then the sed command just narrows down the results to anything over 12 characters. We ran into a lot of broken ASCII inside of binary files, and all the flags that we had saved were at least 14 characters.
As I’m not the regex expert, I recommend you check out the explanation on regex101 if you want to understand it further.
While I do not have all the flags from the DerbyCon 9 CTF, I did grab some from our Trello board.
FinalLap RedDot DoesNotMatter PapersPlease PapersPlease DerpMail Kc57LovesDotNetObfuscation Kc57Kc57Kc57Kc57 StormbeatherintheUncannyX-Men170 TheRedirectMasta PerlFTWLarryRules IReadYourEmails7331 DESTROYallSOFtWare!! Mutantsgotclawsinthe212 GeneNationandthe198 IceIceBabyIceCubeIceT993 OMGCanHazSomePointz2332 HerpDerp8234DerpHerp ItIsIllegalToHackDis23444 DerpyAdm fileserve files DerpyConIzDaB3stConferenceEVAR1337 NiceIDORExploitYo349 DerpyDB HerpDerpyConAdmin D3rpyC0n Congr4tzYouG0t@Dm1n8888 TableNameForBigMoney777858 ColumnNameForTheWin939 IfYouGotThisYouAreAmazing999333 YouAreTheTrueSQLMaster77727 YouReadTheSourceCodeDerpDerp ATicketToTheShow WooYouAreAStaffMember WooYouGotIn! WellYouAreOnTheConsoleNowMyFriend DoesAnyoneRememberPwndU DerpyCon HeyYouDeserveAFlagForYourWebShell AhYouHaveUsedTheSrcLuke OkNowYouRootedMyBoxDadGum GoodYoureStillReadingHTMLComments WebminOnTheBeach ProcFlagProcFlagProc R007LOGINSHELLZ LOGINSHELLZ DoesNotMatter AmaraAquillafromBC44 Livingunderthe10110
I’m not certain which of these were found with our one-liner, but I know that at least one was.
While these flags were obviously in different file types, grep would be able to search my test file just fine.
doyler@mbp:~/Documents/grep$ sort -u test.txt | wc -l 48
When I ran this command in my test directory, I managed to find 87.5% (42/48) of my saved flags!
doyler@mbp:~/Documents/grep$ egrep -r -o -e "[A-Z]([A-Z0-9]*[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*" ./ | sed -n '/.\{12\}/p' | sort | uniq .//test.txt:ATicketToTheShow .//test.txt:AhYouHaveUsedTheSrcLuke .//test.txt:AmaraAquillafromBC44 .//test.txt:ColumnNameForTheWin939 .//test.txt:Congr4tzYouG0t .//test.txt:D3rpyC0n .//test.txt:DESTROYallSOFtWare .//test.txt:DerpMail .//test.txt:DerpyAdm .//test.txt:DerpyCon .//test.txt:DerpyConIzDaB3stConferenceEVAR1337 .//test.txt:DerpyDB .//test.txt:DoesAnyoneRememberPwndU .//test.txt:DoesNotMatter .//test.txt:FinalLap .//test.txt:GeneNationandthe198 .//test.txt:GoodYoureStillReadingHTMLComments .//test.txt:HerpDerp8234DerpHerp .//test.txt:HerpDerpyConAdmin .//test.txt:HeyYouDeserveAFlagForYourWebShell .//test.txt:IReadYourEmails7331 .//test.txt:IceIceBabyIceCubeIceT993 .//test.txt:IfYouGotThisYouAreAmazing999333 .//test.txt:ItIsIllegalToHackDis23444 .//test.txt:Kc57Kc57Kc57Kc57 .//test.txt:Kc57LovesDotNetObfuscation .//test.txt:NiceIDORExploitYo349 .//test.txt:OMGCanHazSomePointz2332 .//test.txt:OkNowYouRootedMyBoxDadGum .//test.txt:PapersPlease .//test.txt:PerlFTWLarryRules .//test.txt:ProcFlagProcFlagProc .//test.txt:RedDot .//test.txt:StormbeatherintheUncannyX .//test.txt:TableNameForBigMoney777858 .//test.txt:TheRedirectMasta .//test.txt:WebminOnTheBeach .//test.txt:WellYouAreOnTheConsoleNowMyFriend .//test.txt:WooYouAreAStaffMember .//test.txt:WooYouGotIn .//test.txt:YouAreTheTrueSQLMaster77727 .//test.txt:YouReadTheSourceCodeDerpDerp doyler@mbp:~/Documents/grep$ egrep -r -o -e "[A-Z]([A-Z0-9]*[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*" ./ | sed -n '/.\{12\}/p' | sort | uniq | wc -l 42
When I inverted the matches, I was able to see the six flags that my command did not not return.
doyler@mbp:~/Documents/grep$ egrep -r -o -v "[A-Z]([A-Z0-9]*[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*" ./ | sed -n '/.\{12\}/p' | sort | uniq | wc -l 6 doyler@mbp:~/Documents/grep$ egrep -r -o -v "[A-Z]([A-Z0-9]*[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*" ./ | sed -n '/.\{12\}/p' | sort | uniq .//test.txt:LOGINSHELLZ .//test.txt:Livingunderthe10110 .//test.txt:Mutantsgotclawsinthe212 .//test.txt:R007LOGINSHELLZ .//test.txt:files .//test.txt:fileserve
As you can see, these flags were either not long enough, or not quite camel case.
This strategy is even more useful in CTFs with a standard flag format.
For example, here is an example of me running this command during a CTF that RecViking was setting up.
ctfuser@ip-172-26-10-254:~$ egrep -r -o -e "flag{.*" / 2>/dev/null | sed -n '/.\{12\}/p' | sort | uniq /home/ctfuser/.bash_history:flag{FLAG GOES HERE} /home/ctfuser/.bashrc:flag{FLAG GOES HERE} /home/ctfuser2/flag.txt:flag{FLAG GOES HERE} /usr/bin/find:flag{FLAG GOES HERE} /usr/bin/find:flag{FLAG GOES HERE}" /usr/bin/nmap:flag{FLAG GOES HERE} /usr/bin/nmap:flag{FLAG GOES HERE}" /var/skel/.bash_history:flag{FLAG GOES HERE} /var/skel/.bashrc:flag{FLAG GOES HERE} /var/www/html/admin/index.html:flag{FLAG GOES HERE} /var/www/html/index.html:flag{FLAG GOES HERE} /var/www/html/robots.txt:flag{FLAG GOES HERE}: / Binary file /proc/1361/cmdline matches Binary file /proc/1361/task/1361/cmdline matches Binary file /var/cache/snapd/commands.db matches
While this will not work in most Jeopardy style CTFs, it is great to run for something that is scenario-based, like our EverSec CTF.
This was a command that we got from RecViking, but I wanted to share it now that DerbyCon is over.
While less relevant to my future CTFs, I also thought about trying to use something like YARA rules to do something similar.
If you have any other examples of indirectly searching for flags, then I’d love to hear them!
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he’s done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!
He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.
This page contains links to products that I may receive compensation from at no additional cost to you. View my Affiliate Disclosure page here. As an Amazon Associate, I earn from qualifying purchases.
Great article! I use this online regex tester to check my regular expressions: https://extendsclass.com/regex-tester.html
Thanks! And cool, that will definitely be one that I add to my toolbox. I’m loving regex101 so far though.