Blocking bad symbols from user input is often done to aid security. Avatar from #glacierctf offers a new example on how to bypass that. Let's write a calculator in Python and pass user input to eval() only allowing these chars:
" ( ) = - + * / > < { } f
Looks safe, right?
It's not. Let's build this from the ground up. We first need some zeros and ones. How about this?
()==()
I am just comparing two empty tuples. That gives me a "True" result ;D Likewise, we can do the following:
()>()
That gives me a "False" result.
Booleans are almost numbers, so let's do some math with them. What's that?
(()==())+(()==())
Just a weird way of encoding the number 2 in Python.
You see where this is going: The first screenshot shows some code to encode each digit with just ( ) = + * > ... cool, right?
There is a cool trick to move from numbers to letters now. Python allows us to format strings with f-strings and there is the {:c} presentation type that converts integers to unicode characters. Here is an example:
f"{100:c}"
That prints the letter with ASCII code 100 "d"
This gives us a method to write arbitrary strings with this minimal set of characters ;) The full write-up explains how we encode our payload, and eventually get a shell without built-in functions. https://sigflag.at/blog/2023/writeup-glacierctf23-avatar/