pythonJail
type
status
date
slug
tags
summary
category
icon
password
LEVEL 1
From the function filter, we sees that the symbol [" ' ` i b] is banned. Which means (Show subclasses with tuple)
().\__class\__.\__base\__.\__subclasses\__()
is not allowed. What's more, symbol ' and " is banned, so it come to us that we may can use
chr
to splicing a string that we wanted.Two possible payload:
getattr(getattr(getattr(getattr(()._class_,c),chr(95)+chr(95)+chr(115)+chr(117)+chr(98)+chr(99)+chr(108)+chr(97)+chr(115)+chr(115)+chr(101)+chr(115)+chr(95)+chr(95))()[-4],chr(95)+chr(95)+chr(105)+chr(110)+chr(105)+chr(116)+chr(95)+chr(95)),chr(95)+chr(95)+chr(103)+chr(108)+chr(111)+chr(98)+chr(97)+chr(108)+chr(115)+chr(95)+chr(95))[chr(115)+chr(121)+chr(115)+chr(116)+chr(101)+chr(109)](chr(115)+chr(104)) (().__class.__base.__subclasses__()[-4].__init__.__globals__'system')
open(chr(102)+chr(108)+chr(97)+chr(103)).read() from thisBlog
LEVEL 2
The length of the payload is limited to 13.
The answer according to 空白 is the function <c style="color: #FF0000">"breakpoint()"</c>, which I didn't figure out yet. However, there is another way. Use
eval(input())
so that the program receive once again for your input! Seems a little bit like /?cmd=system($_POST[1]);$1=ls
to escape the filter in php right?LEVEL 3
This time, the maximum length of our payload is down to 7.
I didn't quite understand yet, but function
help()
can help you passby the 7 words limit. Here is when I tried others' payload, quite amazing and when I am available I shall come back to study it.PYTHON2 INPUT JAIL
python2, another thing I am not familiar with...
Looking up others' write up...
LEVEL 2.5
We can use
breakpoint()
to go into pdb, and rce is possible.LAKE
Strange christen.(Crazyman seems to name it 'lake' from 'leak'?)
Use
globals()
to leak the key. And then get shell.L@KE
Another strange christen...
The maxinum length of payload is now 6, so only
help()
is possible.But unlike cases above, this time module 'os' is destory or whatever. Now we comes to the base reason why we use 'os' above.
help()
can actually get you into any module in the python file, which includes __main__
! And surely, the key can be found inside.OK, now we've go through the first four level( designed by crazyman, that is). From level 5, there provides no source code.
LEVEL 5
Just rce can give you the flag.(unexpected) Later we will see how it shall really be work out.
LEVEL 4
(Why is it 4 after 5 I don't know...)
4 bytes rce, seems impossible, so lets just guass it use
os.system(input_data)
to get your input and bingo.LAkE
This time it imports
sys
module with audit hook, and direct RCE function like pty.spawn、os.system、os.exec、os.posix_spawn、os.spawn、subprocess.Popen
is not available. Whats more, compile、eval、exec、open
is unfetchable. However, there use random.setstate()
to generate its random number, which is base on Mersenne Twister, and is crackable. In general, if we got the state of the random number generator, we can generate the same number. That leads two problems: There is only one 'eval' in the server code, but we need to execute more. How to restore the state BEFORE the random number is generated?First, we need to know a thing named Assignment Expresions in python, or rather, walrus operator. Then, we package those formula in a list. They will be calculate from left to right. As for function, we can replace it with
lambda
. Some case can be view below:Second, if we
import random
and print random.getstate
at the beginning, we got a tuple back. which may look like:(3, (..., 624), None)
. The first value '3' and the last value 'None' is fixed. Only 624 numbers in the middle is changed. So if we assign the conter zero, we get the random number.payload:
LEVEL 5.1
Dued to the unexpected solves in level5, crazyman gives another problem, stating level5.1.
nc
and dir()
(as it tells you to), found my_flag
, try list(getattr(my_flag,'flag))
, got a AttributeError: 'flag_level5' object has no attribute 'flag'
. So payload is list(getattr(my_flag,'flag_level5'))
Another way to solve this problem(though quite similar, the latter gets its shell)
LAK3
Same as before, we can use the excate same payload. Though the official payload provides by crazyman is
__import__('sys')._getframe(1).f_locals['right_guesser_question_answer']
tyPe Ch@nnEl
I haven't quite understand yet. So I will put the payload beforehand:
One possible:
↑ Can took some time(when I tried)
Officail:
LEVEL 4
level 4 again
Quite similar as before, just use
bytes().decode()
to pass the black list.payload:
#####
().class.base.subclasses()[-4].init.globalsbytes([115, 121, 115, 116, 101, 109]).decode()
There is another solution to this problem: I am not sure I fully understand it, so I put a link here beforehand.
payload:
LEVEL 4.0.5
Same payload as last one.
LEVEL 4.1
Quite same as before.
Ps, the
bytes
is now banned, but still you can use show subclassed with tuples
to replace, like this:LEVEL 4.2
Quite same as before..
Or rather use
join
:LEVEL 4.3
Quite same as before...
The next few levels are become harder and harder.
LEVEL 6
repetition:
The basic idea is to RCE with
_posixsubprocess.fork_exec
. If we import it directly, it will trigger the audit hook. But we can pass it by using __builtins__['__loader__'].load_module('_posixsubprocess')
or __loader__.load_module('_posixsubprocess')
. Also, due to its repeatedly exct, we just shell like this:LEVEL 6.1
This time, we only got one time to excute our payload. Though, we our learning above, we know that walrus operator can help us. Also, the shell will shut immediately, the blogger think of a interesting way to overcome this, by brute force, getting shell over and over again and try to input command. That works.
payload:
or
SAFEEVAL
Use lambda to wrap up RCE
payload:
LEVEL7
Come back later to try to figure it out...
payload:
@exec @input class X: pass
import('os').system('sh')
blog
Ok, so that's the end of the hnctf. There are some thing that may help you get further about pyjail:
上一篇
hnctf
下一篇
windows 反调试记录
Loading...