چالش 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}نویسنده