如何保护Python应用程序免受恶意脚本注入





Python应用程序使用许多脚本。这就是网络罪犯用来在我们身上放“猪”的地方-我们最不希望看到它的地方。



Python的优点之一是易于使用:要运行脚本,只需将其保存在.py文件中并执行命令python (, python my_file.py)破坏我们的文件(例如模块)my_app.pymy_lib.py继续连接模块以使用design也是很容易的import...from: import my_lib from my_app.py



但是,这种简单明了的缺点是:您从不同位置执行代码越容易,攻击者就越有机会进行干预。



将Python代码放在​​安全的地方



Python安全模型基于以下三个原则:



  1. , sys.path , .
  2. , (main), sys.path.
  3. python , -c -m.


假设您要运行已“正确”安装在计算机上的Python应用程序。在这种情况下,默认情况下唯一会自动添加到sys.path的位置(安装了Python的文件夹除外)是带有主脚本或可执行文件的文件夹。



例如,如果pip在中/usr/bin,并且您运行/usr/bin/pip,则sys.path只会添加/usr/bin。只有root可以将文件写入/ usr / bin,因此该位置被认为是安全的。



然而,协议要求我们这样做:/path/to/python -m pip。这样可以避免$PATHWindows文档的问题和冲突。



通常,如果只有您一个人有权在Python导入模块的目录中添加和编辑文件,那么一切都会好起来的。



下载文件夹-易受攻击的位置



有很多方法可以迫使浏览器(有时甚至是其他软件)在用户不知情的情况下将任意命名的文件放置在Downloads文件夹中。此漏洞被称为DLL欺骗的攻击所利用。在我们的案例中,我们将讨论Python脚本,但是想法是相同的。



浏览器对此已经变得越来越认真,并正在逐步尝试确保用户访问的站点不能将文件秘密地放入其“下载”文件夹中。



但是,要完全解决此问题将非常困难:例如,仍然有一个选项可供Content-Disposition HTTP header’s filename*站点选择放置上载文件的目录。



攻击如何进行



您运行安装:python -m pip您正在从一个完全值得信赖的网站上下载Python软件包,但是出于某些原因,该网站提供的是直接下载而不是PyPI。也许它是某种内部版本,也许是初步版本-没什么不同。所以这取决于你totally-legit-package.whl



~$ cd Downloads
~/Downloads$ python -m pip install ./totally-legit-package.whl


似乎还可以,但是事实证明,两个星期前,在您访问的一个完全不同的站点上,一些XSS JavaScript在不知情的情况下将带有恶意软件的pip.py下载到了Downloads文件夹中。



繁荣!



崩溃!



~$ mkdir attacker_dir
~$ cd attacker_dir
~/attacker_dir$ echo 'print("lol ur pwnt")' > pip.py
~/attacker_dir$ python -m pip install requests
lol ur pwnt


奇怪的行为 PYTHONPATH



我在上面的几段中写道:



默认情况下,唯一会自动添加到sys.path的位置(Python安装文件夹除外)是主脚本或可执行文件文件夹。


那么“默认”在这里做什么?您还可以添加其他哪些位置?



基本上,$PYTHONPATH您可以将任何内容写入环境变量但是您不会在中写下您的当前位置$PYTHONPATH,对吗?



不幸的是,在某些情况下,您可能会意外地这样做。

让我们来画一个“脆弱的” Python应用程序来进行说明:



# tool.py
try:
    import optional_extra
except ImportError:
    print("extra not found, that's fine")


让我们创建2个目录:install_dirattacker_dir让我们陷入install_dir,然后执行cd attacker_dir恶意代码并将其放置在此处tool.py



# optional_extra.py
print("lol ur pwnt")


剩下的就是运行它:



~/attacker_dir$ python ../install_dir/tool.py
extra not found, that's fine


到目前为止,一切进展顺利。



但是现在我们将看到一个常见的错误。许多建议增加一个$PYTHONPATH更多的事情



export PYTHONPATH="/new/useful/stuff:$PYTHONPATH";


乍一看,这是有道理的:如果将项目X添加到中$PYTHONPATH,也许根据项目Y,是否也添加了某些内容;无论如何,您都不想覆盖与其他项目关联的更改。当您编写许多人会使用的文档时,这一点尤其重要。



现在,我们面临着“奇怪”的行为$PYTHONPATH如果它$PYTHONPATH是空的或在第一次启动之前未安装,则其中将出现一个空行,它将被识别为当前目录。让我们检查一下:



~/attacker_dir$ export PYTHONPATH="/a/perfectly/safe/place:$PYTHONPATH";
~/attacker_dir$ python ../install_dir/tool.py
lol ur pwnt


为了增强安全性,让我们将其设置为$PYTHONPATH空,然后重试:



~/attacker_dir$ export PYTHONPATH="";
~/attacker_dir$ python ../install_dir/tool.py
lol ur pwnt


确实,这根本不安全!



还有一件事情:事实证明,变量为$PYTHONPATH空和$PYTHONPATH未设置变量的情况有两种不同的情况:



os.environ.get("PYTHONPATH") == ""</code>  <code>os.environ.get("PYTHONPATH") == None.


如果要确保清理$PYTHONPATH,请使用以下命令unset



~/attacker_dir$ python ../install_dir/tool.py
extra not found, that's fine


通常,写入变量$PYTHONPATH是设置环境以运行Python应用程序的最常见方法。幸运的是,随着虚拟环境和virtualenv的出现,它已经过时了。如果您有一个向写入内容的旧配置$PYTHONPATH,但是您可以不用它,那么现在是时候删除它了。



如果由于某种原因您不能执行此操作,请使用生活技巧



export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}new_entry_1"
export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}new_entry_2"


在bash和zsh中,这将给出以下输出:



$ echo "${PYTHONPATH}"
new_entry_1:new_entry_2


好了,现在没有多余的冒号和空条目。



最后,如果您仍在使用$PYTHONPATH,请使用绝对路径。总是!



问题更加严重



与从Downloads文件夹启动Python文件相关的事件的危险开发有多种选择:



  • 运行python ~/Downloads/anything.py(即使它本身anything.py是安全的)。您的下载文件夹将添加到中sys.path
  • 启动后,“jupyter notebook ~/Downloads/anything.ipynb下载”文件夹也将添加到中sys.path


因此,最好在运行之前从此文件夹中删除.py和.ipynb文件。如果导入的文件位于Downloads文件夹中,则



执行cd Downloads内部启动python -c并附带说明启动import或交互式启动python并随后导入均不能完全解决问题。



不幸的是,这~/Downloads/不是可能包含恶意文件的唯一位置。例如,如果要管理用户可以向其上载文件的服务器,请cd public_uploads在运行命令之前确保没有人可以启动python



在这种情况下,可能值得考虑的是,用于处理文件上传的代码将附加到其名称之后.uploaded这将有助于避免计划外的脚本执行.py



注意事项



如果您要在“下载”文件夹中使用Python应用程序,则将输入脚本(/ path / to / venv / bin / pip)而不是模块(/ path / to / venv / bin / python -m pip的路径作为规则



通常,只需避免将“下载”用作当前工作目录,并在开始之前将要使用的所有脚本移动到更合适的位置。



了解Python从何处获取将要执行的代码非常重要。让某人执行左手Python脚本的哪一行,都等于完全控制了您的计算机!



根据需要



阅读有关安全性的“技巧和生活技巧”的文章,可以很容易地认为作者非常聪明,知道其他人应该知道的一堆小事情,并不断思考。但是实际上,这并非完全正确。我会解释。



多年来,我以令人羡慕的频率观察到用户如何不理解Python从何处下载代码。例如,人们将使用Twisted的第一个程序放置在名为twisted.py的文件中。但是在这种情况下,根本不可能导入该库!



如果网络罪犯能够成功地攻击系统管理员或开发人员,他们会感到非常高兴。如果您入侵某个用户,您将获得该用户的数据。但是,如果您黑掉了管理员或开发人员并正确执行了操作,则可以访问系统受管理员控制的数千名用户,甚至使用开发人员软件的数百万用户。



因此,“始终保持谨慎”并不是一个可靠的方法。那些负责大量用户产品的IT专业人员确实需要格外小心。至少,应该告知他们某些开发工具的工作特性。



错误或功能...



我上面描述的内容实际上都不是真正的“错误”或“漏洞”。我认为Python或Jupyter开发人员不会错误地做任何事情。该系统按照其设计方式工作,并且可能可以解释。就我个人而言,我不知道如何在不减少Python功能的情况下对其进行更改,而我们对此非常重视。



我最喜欢的发明之一是SawStop,这是用于台锯的独特安全系统。与人体接触后,您可以在5毫秒内停止锯片的旋转。在该系统发明之前,台锯是非常危险的工具,但它们起着重要的生产功能。在台锯上已经完成了许多非常有用和重要的事情。但是,在木工车间中,台锯在事故中所占的比例也确实很高。现在,SawStop每年可以节省很多手指。



因此,通过详细介绍Python脚本编写的复杂性,我也希望对一些安全工程师有所考虑。可以使SawStop执行用于交互式解释程序的任意代码吗?哪种解决方案可以防止上述某些问题?



保持安全的朋友。






广告



VDSina在Linux或Windows上提供安全的服务器-选择预安装的操作系统之一,或从映像中安装。






All Articles