切勿在下载文件夹中运行‘Python’

2020-08-23 20:13:23

Python的奇妙之处之一是您可以轻松地开始编写脚本-只需将一些代码放入一个.py文件,然后运行pythonmy_file.py即可。同样,开始模块化也很容易:将my_file.py拆分为my_app.py和my_lib.py,您可以从my_app.py导入my_lib并开始将代码组织到模块中。

然而,使此工作的机制的细节有一些令人吃惊的,有时非常关键的安全后果:对您来说,从不同位置执行代码越方便,攻击者执行代码的机会也就越大。

假设sys.path上的每个条目都是一个安全位置,可以从该位置安全地执行任意代码。

当直接调用python时,即使在传递-c或-m选项时,当前目录也被视为“主脚本”位置。

如果您运行的是已在计算机上正确安装的Python应用程序,则Python安装或viralenv之外唯一会自动添加到sys.path(默认情况下)的位置是主可执行文件或脚本的安装位置。

例如,如果您在/usr/bin中安装了pip,并且运行了/usr/bin/pip,则此功能只会将/usr/bin添加到sys.path。任何可以将文件写入/usr/bin的内容都可以让您或您的系统运行程序,因此它是一个相当安全的地方。(考虑一下,如果您的ls可执行文件被替换为令人讨厌的内容,会发生什么情况。)。

然而,一个新兴的惯例是参考调用/path/to/python-m pip,以避免正确设置$PATH的复杂性,并避免处理有关如何在Windows上安装脚本的不同文档(目前通常是.exe文件,而不是.py文件)。

只要您相信您是唯一一个将文件放入您可以从中导入的位置(包括您的工作目录)的人,就可以这样做。

正如名为“DLLPlanting”的攻击类别所示,浏览器(有时还有其他软件)可以通过多种方式被诱骗,在没有用户交互的情况下将具有任意文件名的文件放入Downloads文件夹。

浏览器开始更认真地对待这类漏洞,并添加了各种缓解措施,以避免网站在您访问时偷偷将文件放入下载文件夹中。1个。

不过,即使进行了减轻,也很难完全消除这一点:例如,Content-Disposition HTTP头的filename*参数的存在完全是为了允许站点选择它下载到的文件名。(=。

您已经习惯了使用python-m pip来安装东西。您可以从完全值得信任的网站下载PythonPackage,无论出于何种原因,该网站都会通过直接下载而不是通过PyPI下载Python轮。可能是内部的,也可能是预发行的;随便了。因此,您下载完全合法的Package.whl,然后:

这似乎是合理的做法,但您不知道,两周前,您访问的另一个完全不同的站点上有一些XSS JavaScript,它将一个包含恶意软件的pi.py文件下载到您的下载文件夹中。

~$mkdir攻击者目录~$cd攻击者目录~/攻击者目录$ECHO';打印(";lol ur pwnt";)';>;Pip.py~/攻击者_dir$python-m pip安装请求lol ur pwnt。

如果您运行的是已在计算机上正确安装的Python应用程序,则Python安装或viralenv之外唯一会自动添加到sys.path(默认情况下)的位置是主可执行文件或脚本的安装位置。

那么“默认情况下”是什么意思呢?可能会添加哪些其他目录?

$PYTHONPATH环境变量上的任何条目。您不会将当前目录放在$PYTHONPATH上,是吗?

不幸的是,有一种常见的方式可能是您无意中这样做的。

创建两个目录:install_dir和Attack_dir。将其放在install_dir中。然后,cd攻击者_dir,并将我们复杂的恶意软件放在那里,其名称由tool.py使用:

但是,这里有一个常见的错误。大多数仍然推荐PYTHONPATH的地方建议添加如下内容:

直观地说,这是有道理的;如果您要将项目X添加到$PYTHONPATH中,可能项目Y已经添加了一些东西,也许没有;年轻人是否想要把它去掉,替换掉shell初创公司的其他部分可能用它做过的事情,特别是如果您正在编写许多不同人都会使用的文档。

但是这个习惯用法有一个严重的缺陷:第一次调用它时,如果$PYTHONPATH以前为空或未设置,则会包含一个解析为当前目录的空字符串。我们来试试吧:

哦不!好吧,为了安全起见,让我们清空$PYTHONPATH,然后再试一次:

这里发生的情况是,如果PYTHONPATH是空的,这与它被取消设置不是一回事。在Python中,这是os.Environmental.get(";PYTHONPATH";)==";";和os.Environmental.get(";PYTHONPATH";)==NONE之间的差异。

如果要确保已从shell(或某个shell启动)中清除$PYTHONPATH,则需要使用unset命令:

设置PYTHONPATH曾经是设置Python开发环境的最常见方式;希望它已经基本失宠,而Virtualenvs更好地满足了这一需求。如果您有一个旧的shell配置,仍然设置了一个不再需要的$PYTHONPATH,这是一个删除它的好机会。

但是,如果您确实需要在shell启动中“附加到”PYTHONPATH的习惯用法,请使用以下技术:

通过与Python交互来检查Downloads文件夹中的文件有很多不同的不安全行为。其他高风险活动:

从任何地方运行python~/downloads/anything.py(即使anything.py本身是安全的)-因为它会根据anything.py的位置将您的下载文件夹添加到sys.path。

Jupyter Notebook将笔记本所在的目录放到sys.path上,就像Python将脚本目录放在那里一样。所以jupyter笔记本~/downloads/anything.ipynb和python~/downloads/anything.py一样危险。

在运行脚本和笔记本之前,请将它们从下载文件夹中取出!

在~/downloads文件夹中运行包含import语句的python-c命令

请记住,~/downloads/并不特殊;它只是一个位置,攻击者选择的文件名可能会潜入意外的文件。请留意其他确实存在这种情况的地方。例如,如果您正在重新管理公众可以上传文件的服务器,请特别确保您的应用程序或任何可能运行python的管理员都不会经常使用cd public_ploads。

也许可以考虑更改处理上传的代码,使文件名变得杂乱无章,这样可以避免意外上传和执行.py文件的风险。

如果您的Downloads文件夹中有用Python编写的工具,请养成更喜欢键入脚本路径(/path/to/venv/bin/pip)而不是模块(/path/to/venv/bin/python-mpip)的习惯。

一般来说,只要避免将~/downloads作为当前的工作目录,并在启动之前将您想要使用的任何软件移动到一个更合适的位置即可。

了解Python将执行的代码是从哪里获得的,这一点很重要。即使给某人执行一行任意Python的能力,也等同于让他们完全控制您的计算机!

在写这样一篇关于安全的“小窍门和诀窍”的文章时,很容易暗示我作为作者非常聪明,知道这一堆奇怪的琐事,而对于你作为读者来说,保持安全的唯一方法就是记住一大堆同样深奥的东西,并不断地思考它。事实上,这篇文章的前一稿无意中做到了这一点。但这真的是个糟糕的主意,我也不想参与宣传。

所以如果我不是想这么说,那为什么要发帖呢?我会解释的。

在使用Python的多年中,我很少但经常看到用户对Python加载代码的位置感到困惑。这种混淆的一种形式是,当人们将他们的第一个使用Twisted的程序放入一个文件名为twisted.py的文件中时。这给图书馆的进口蒙上了阴影,破坏了一切。这种混乱的另一个表现是安全报告混乱的缓慢流动,研究人员将一个模块放到记录Python加载代码的位置-就像上面描述的场景中的当前目录-然后加载它,认为这反映了攻击,因为它正在执行任意代码。在这种情况下,研究人员将模块放到记录Python加载代码的位置-就像上面描述的场景中的当前目录-然后加载它,因为它正在执行任意代码。

任何这样的混乱--即使所讨论的系统“行为符合预期”,并且不能轻易改变--都是攻击者可以利用的漏洞。

系统管理员和开发人员是网络犯罪世界中的高价值目标。如果你黑了一个用户,你就会得到那个用户的数据;但是如果你黑了一个管理员或一个开发人员,如果你做得对,你可以访问数千个系统在管理员控制之下的用户,甚至数百万使用开发人员软件的用户。

因此,虽然“时时刻刻多加小心”并不是一个可持续的安全保障,但在某种程度上,我们这些代表用户行事的人确实有更大的义务要更加谨慎。至少,我们应该了解我们的工具的行为。开发人员的工具,如Python,不可避免地是强大的工具,可能比一般的应用程序需要更多的关注和更高的精确度。

确切地说,我上面描述的一切都不是“错误”或“利用”;我不认为Python或Jupyter的开发人员做错了什么;系统按照它的设计方式工作,它的设计方式是有意义的。我个人对于如何在不从Python中转移大量功能的情况下可以改变事情没有什么好的想法。

我最喜欢的安全发明之一是SawStop。在台锯发明之前,它的工作方式没有任何问题;它们是执行重要工业功能的极其危险的工具。许多非常有用和重要的东西都是用台锯做的。然而,桌锯在木工事故中占了不成比例的比例,尤其是失去了手指,这也是事实。尽管有经验丰富、有安全意识的木匠悉心照料,SAWStop每年仍能保住许多手指。

因此,通过强调这一潜在的危险,我也希望在一些有进取心的安全工程师中引发一些思考。交互式解释器的任意代码执行的停止可能是什么?有什么发明可以在不显著削弱Python等工具的能力的情况下阻止我下面描述的一些场景?

非常感谢保罗·甘塞尔,纳撒尼尔·J。Smith,Itamar Turner-Trauring和Nelson Elhage对这篇文章早期草稿的实质性反馈。

限制哪些站点可以驾车将文件放到您的下载文件夹中是一个很好的安全功能,除了添加它的主要后果是每个人似乎都被它惹恼了,不理解它,并且想要关闭它。-↩