Python学习中你不可不知的Python陷阱二.docx
- 文档编号:25854275
- 上传时间:2023-06-16
- 格式:DOCX
- 页数:10
- 大小:63.63KB
Python学习中你不可不知的Python陷阱二.docx
《Python学习中你不可不知的Python陷阱二.docx》由会员分享,可在线阅读,更多相关《Python学习中你不可不知的Python陷阱二.docx(10页珍藏版)》请在冰豆网上搜索。
Python学习中你不可不知的Python陷阱二
Python学习中你不可不知的Python陷阱
(二)
本篇文章主要是对上篇文章Python学习中的出现的安全隐患问题的一个补充,安全隐患不可小看,一不注意就可能造成很大的错误。
模块注入
Python的模块导入系统功能强大而复杂。
模块和包可以通过定义在sys.path列表中的搜索路径找到的文件或目录名导入。
搜索路径初始化是一个复杂的过程,它也依赖于Python版本,平台和本地配置。
要对一个Python应用程序进行成功攻击,攻击者需要找到一种方法来将恶意Python模块揉入进Python在尝试导入模块时会考虑的一个目录或可导入包文件。
处理措施是维护搜索路径中的所有目录和包文件的安全访问权限,以确保XX的用户无法对其进行写访问。
请记住,调用Python解释器的初始脚本所在的目录会自动插入到搜索路径中。
像这样运行脚本显示实际的搜索路径:
root@iZ2854ev03bZ:
~#catmyapp.py
#!
/usr/bin/envpython
#-*-coding:
utf-8-*-
importsys
importpprint
pprint.pprint(sys.path)
在Windows平台,Python进程的当前工作目录,而不是脚本所在位置,会被注入到搜索路径中。
在UNIX平台,无论何时从标准输入或者命令行\("-"或者"-c"或者"-m"选项\)读入程序代码,当前工作目录都会自动插入到 sys.path 中:
root@iZ2854ev03bZ:
~#echo"importsys;importpprint;pprint.pprint(sys.path)"|python-
['',
'/usr/local/lib/python2.7/dist-packages/gensim-0.12.3-py2.7-linux-x86_64.egg',
'/usr/local/lib/python2.7/dist-packages/smart_open-1.3.2-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/requests-2.8.1-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/bz2',
'/usr/local/lib/python2.7/dist-packages/httpretty-0.8.10-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/boto-2.38.0-py2.7.egg',
'/usr/lib/python2.7/dist-packages',
'/usr/local/lib/python2.7/dist-packages/tornado-4.3-py2.7-linux-x86_64.egg',
'/usr/local/lib/python2.7/dist-packages/singledispatch-3.4.0.3-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/Project_RNN_Enhancement-0.0.1-py2.7.egg',
'/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/PILcompat',
'/usr/lib/python2.7/dist-packages/gtk-2.0',
'/usr/lib/pymodules/python2.7']
root@iZ2854ev03bZ:
~#python-c"importsys;importpprint;pprint.pprint(sys.path)"
['',
'/usr/local/lib/python2.7/dist-packages/gensim-0.12.3-py2.7-linux-x86_64.egg',
'/usr/local/lib/python2.7/dist-packages/smart_open-1.3.2-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/requests-2.8.1-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/bz2',
'/usr/local/lib/python2.7/dist-packages/httpretty-0.8.10-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/boto-2.38.0-py2.7.egg',
'/usr/lib/python2.7/dist-packages',
'/usr/local/lib/python2.7/dist-packages/tornado-4.3-py2.7-linux-x86_64.egg',
'/usr/local/lib/python2.7/dist-packages/singledispatch-3.4.0.3-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/Project_RNN_Enhancement-0.0.1-py2.7.egg',
'/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/PILcompat',
'/usr/lib/python2.7/dist-packages/gtk-2.0',
'/usr/lib/pymodules/python2.7']
root@iZ2854ev03bZ:
~#python-mmyapp
['',
'/usr/local/lib/python2.7/dist-packages/gensim-0.12.3-py2.7-linux-x86_64.egg',
'/usr/local/lib/python2.7/dist-packages/smart_open-1.3.2-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/requests-2.8.1-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/bz2',
'/usr/local/lib/python2.7/dist-packages/httpretty-0.8.10-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/boto-2.38.0-py2.7.egg',
'/usr/lib/python2.7/dist-packages',
'/usr/local/lib/python2.7/dist-packages/tornado-4.3-py2.7-linux-x86_64.egg',
'/usr/local/lib/python2.7/dist-packages/singledispatch-3.4.0.3-py2.7.egg',
'/usr/local/lib/python2.7/dist-packages/Project_RNN_Enhancement-0.0.1-py2.7.egg',
'/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/PILcompat',
'/usr/lib/python2.7/dist-packages/gtk-2.0',
'/usr/lib/pymodules/python2.7']
要处理从当前工作路径注入模块的风险,推荐在Windows运行Python或者通过命令行传递代码之前,显式地修改目录到一个安全的目录。
另一个搜索路径可能的来源是 $PYTHONPATH 环境变量的内容。
抵御 sys.path 不被进程环境污染的简单方法是传递 -E 选项给Python解释器,这会让它忽略 $PYTHONPATH 变量。
导入时的代码执行
语句实际上会导致导入的模块中的代码的执行,这一事实并不明显。
这就是为什么甚至导入不可信模块或包是有风险的。
导入像这样的简单模块可能会导致不愉快的结果:
$catmalicious.py
importos
importsys
os.system('cat/etc/passwd|mail')
delsys.modules['malicious']#pretendit'snotimported
$python
>>>importmalicious
>>>dir(malicious)
Traceback(mostrecentcalllast):
NameError:
name'malicious'isnotdefined
与 sys.path 入口注入攻击相结合,它可能为进一步的系统漏洞利用铺平道路。
猴子补丁(monkeypatching)
运行时修改Python对象属性的过程称之为猴子补丁(monkeypatching)。
作为动态语言,Python完全支持运行时程序自省和代码突变。
一旦以某种方式导入了一个恶意模块,那么任何现有的可变对象可被不知不觉地在没有程序员同意的情况下被打猴子补丁。
考虑以下情况:
$catnowrite.py
importbuiltins
defmalicious_open(*args,**kwargs):
iflen(args)>1andargs[1]=='w':
args=('/dev/null',)+args[1:
]
returnoriginal_open(*args,**kwargs)
original_open,builtins.open=builtins.open,malicious_open
如果Python解释器执行了上面的代码,那么任何写到文件的东西都不会存储在文件系统中:
>>>importnowrite
>>>open('data.txt','w').write('datatostore')
5
>>>open('data.txt','r')
Traceback(mostrecentcalllast):
...
:
[Errno2]Nosuchdirectory:
'data.txt'
攻击者可以利用Python垃圾回收器( gc.get_objects() )来掌握现有的所有对象,并黑进它们中任意一个。
在Python2中,内置的对象可以通过魔法 __builtins__ 模块访问。
一个已知的技巧,利用 __builtins__ 可变性,可以让整个世界崩溃:
>>>__builtins__.False,__builtins__.True=True,False
>>>True
False
>>>int(True)
0
在Python3中,对 True 和 False 的赋值不起作用,因此不能那样操作。
在Python中,函数时第一类对象,它们维护了到函数的许多属性的引用。
特别是,可执行字节码被 __code__ 属性引用,当然,这是可以被修改的:
>>>importshutil
>>>
>>>shutil.copy
>>>shutil.copy.__code__=(lambdasrc,dst:
dst).__code__
>>>
>>>shutil.copy('my_','/tmp')
'/tmp'
>>>shutil.copy
>>>
一旦应用了上面的猴子补丁,尽管 shutil.copy 函数看起来仍然理智,但由于误操作的lambda函数代码的设置,它默默地停止了工作。
Python对象的类型是由 __class__ 属性决定的。
邪恶的攻击者可以通过依靠改变活动对象的类型来令人绝望地把事情搞砸:
>>>classX(object):
pass
...
>>>classY(object):
pass
...
>>>x_obj=X()
>>>x_obj
<__main__.Xobjectat0x7f62dbe5e010>
>>>isinstance(x_obj,X)
True
>>>x_obj.__class__=Y
>>>x_obj
<__main__.Yobjectat0x7f62dbe5d350>
>>>isinstance(x_obj,X)
False
>>>isinstance(x_obj,Y)
True
>>>
对抗恶意猴子补丁的唯一处理措施是保证导入的Python模块的真实性和完整性。
通过subprocess进行shell注入
以胶水语言著称,对Python脚本来说,通过让操作系统来执行它们,可能还提供额外的参数,来委派系统管理任务给其他程序,是非常常见的。
subprocess模块为这样的任务提供了易于使用和相当高层次的服务。
>>>fromsubprocessimportcall
>>>unvalidated_input='/bin/true'
>>>call(unvalidated_input)
0
>>>
但有一个陷阱!
要利用UNIXshell服务,例如命令行参数扩展, call 函数的 shell 关键字参数应该设置为 True 。
然后原样传递 call 函数的第一个参数给系统 shell ,用以进一步的解析。
一旦无效的用户输入到达 call 函数(或者其他在 subprocess 模块中实现的函数),那么就会开放一个口给底层系统资源。
>>>fromsubprocessimportcall
>>>
>>>unvalidated_input='/bin/true'
>>>unvalidated_input+=';cut-d:
-f1/etc/passwd'
>>>call(unvalidated_input,shell=True)
root
bin
daemon
adm
lp
0
显然,将 shell 关键字保持默认值 False ,并且提供命令及其参数的数组给 subprocess 函数,不要为外部命令执行调用UNIXshell,这样会安全得多。
在这第二次调用格式,命令或者它的参数都不会被shell解析或展开。
>>>fromsubprocessimportcall
>>>call(['/bin/ls','/tmp'])
如果应用的本质决定了使用UNIXshell服务,那么清理一切到 subprocess 的参数,确保没有不想要的shell功能可以被恶意用户利用,这完全是重要的。
在更新的Python版本中,可以用标准库的 shlex.quote 函数来进行shell转义。
Python学习中还有许多要注意的问题,更多深入的学习还需要你自己去探索,学习的过程可能是艰难地,但是发现的过程却是快乐的,加油!
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Python 学习 不可 不知 陷阱
![提示](https://static.bdocx.com/images/bang_tan.gif)