چالش ok-nice ¶
آشنایی با مساله¶
تو این سوال به ما فایل jail.py
داده شده است. بیایید نگاهی به محتویاتش بیندازیم
jail.py | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
تو این سوال با یک سوال از دسته pyjail
روبرو هستیم.
این دسته از سوالات معمولا یک اسکریپت پایتونی داریم که ورودی از کاربر میگیره و در صورتیکه شرط های مساله رو نقض نکرده باشه، ورودی کاربر به exec
یا eval
داده میشه و اجرا میشه. و به این طریق فرد میتواند به فلگ برسد.

مساله ما بطور خلاصه سه شرط زیر را دارد:
- رشته ورودی ما نباید از
blacklist
ها استفاده کرده باشد - حرفهای رشته ورودی ما باید کد اسکی بین
40
تا125
داشته باشند (نمیتونیم ازItalic Text
جهت دور زدن شرط ها استفاده کرد) - نباید بیش از
17
حرف متفاوت تو رشته ورودیمون استفاده کرده باشیم
در گام نخست میایم لیستی از چیزهایی که میتونیم استفاده کنیم رو بدست میاریم
import builtins, keyword, string
blacklist=['0','1','2','3','4','5','6','7','8','9','_','.','=','>','<','{','}','class','global','var','local','import','exec','eval','t','set','blacklist']
def check(inp):
for bad in blacklist:
if bad in inp:
return False
for ch in inp:
if (ord(ch) > 125) or (ord(ch) < 40):
return False
if (len(set(inp))>17):
return False
return True
print("\n========= Allowed globals =========")
for w in list(globals()):
if check(w):
print(w)
print("\n========= Allowed builtins =========")
for w in list(builtins.__dict__):
if check(w):
print(w)
print("\n========= Allowed keywords =========")
for w in list(keyword.kwlist):
if check(w):
print(w)
print("\n========= Allowed special chars =========")
for w in string.punctuation:
if check(w):
print(w)
========= Allowed globals =========
In
open
keyword
check
========= Allowed builtins =========
abs
all
any
ascii
bin
callable
chr
compile
dir
divmod
hash
hex
id
len
max
min
ord
pow
repr
round
sum
None
Ellipsis
False
True
bool
memoryview
complex
map
range
reversed
slice
super
zip
BufferError
EOFError
LookupError
MemoryError
NameError
OSError
ReferenceError
TypeError
ValueError
Warning
OverflowError
ZeroDivisionError
EncodingWarning
ResourceWarning
UnicodeWarning
UserWarning
BlockingIOError
ChildProcessError
PermissionError
ProcessLookupError
IndexError
KeyError
RecursionError
UnboundLocalError
UnicodeError
BrokenPipeError
TabError
UnicodeDecodeError
UnicodeEncodeError
IOError
WindowsError
open
license
help
runfile
display
========= Allowed keywords =========
False
None
True
and
as
async
break
def
del
elif
else
finally
for
from
if
in
is
lambda
or
pass
raise
while
yield
========= Allowed special chars =========
(
)
*
+
,
-
/
:
;
?
@
[
\
]
^
`
|
راه حل¶
ورودی ما به تابع eval
داده میشه و دستور eval
به خودی خود چیزی نمایش نمیده.
درنتیجه دستور ما، باید شامل توابعی نظیر print
باشد تا خروجی را نمایش دهد، اما متاسفانه با توجه به اینکه ما نمیتونیم از فاصله و نقطه و حرف t
استفاده کنیم، پس استفاده از تابع print
و نظیرهم کنسل میشه 😕
بعد کلی آزمون و خطا، ایده ZeroDivisionError
به ذهنم اومد، چون سوال وقتی تابع eval
به ارور بخوره error
چاپ میشه و از این طریق میتونیم حروف فلگ رو بدست بیاوریم. چطور؟
میدونیم تو پایتون اگر عددی تقسیم بر صفر شه، به ارور برمیخوریم. پس داریم:
1/0 => ZeroDivisionError
همچنین میدونیم تو پایتون True
میتواند بعنوان عدد 1
نیز لحاظ شود و داریم:
flag[1] == flag[True]
flag[2] == flag[True+True]
در نتیجه خواهیم داشت:
True / ( ord('t') - 116 ) => ZeroDivisionError
True / ( ord(flag[True+True]) - 116 ) => ZeroDivisionError
در ادامه کافیست یک اسکریپت بنویسیم و اینکار رو اتومیت کنیم و فلگ را بدست بیاریم
solve.py | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
FLAG 
ictf{0k_n1c3_7f4d3e5a6b}
نویسنده