注册
登录
新闻动态
python
返回
永远不要在您的下载文件夹中运行“ python”
作者:
凯撒
发布时间:
2024-04-07 04:42:35 (18天前)
来源:
glyph.twistedmatrix.com
Python可以执行代码。确保它仅执行您想要的代码。 蟒蛇程式设计安全2020年8月22日星期六 关于Python的一件奇妙的事情是,您可以轻松开始编写脚本-只需将一些代码放入.py文件中并运行即可python my_file.py。同样很容易上手模块:拆分 my_file.py成my_app.py和my_lib.py,你可以import my_lib从 my_app.py开始整理你的代码模块。 但是,完成这项工作的机制的细节会带来一些令人惊讶的,有时甚至是对安全性至关重要的后果:您从不同位置执行代码越方便,攻击者也就越有机会执行它。 。 Python需要一个安全的空间来从中加载代码 以下是Python安全模型中嵌入的三个关键假设: sys.path假定上面的每个条目都是安全的位置,可以从该位置安全地执行任意代码。 “主脚本”所在的目录始终位于 sys.path。 python直接调用时,即使传递或选项,当前目录也被视为“主脚本”位置。-c-m 如果您运行的是已正确安装在计算机上的Python应用程序,则Python安装或virtualenv之外唯一会自动添加到您sys.path的位置(默认情况下)的位置是主可执行文件或脚本的安装位置。 。 例如,如果您已pip在中安装/usr/bin并运行 /usr/bin/pip,则此功能仅/usr/bin将添加到中sys.path。任何可以写入文件的东西都/usr/bin可以使您或您的系统运行,因此这是一个非常安全的地方。(考虑如果将ls可执行文件替换为讨厌的文件会发生什么情况。) 但是,一种新兴的惯例是更喜欢进行调用/path/to/python -m pip,以避免$PATH正确设置的复杂性,并避免处理有关如何在Windows上安装脚本的各种文档(通常是如今的.exe文件,而不是.py文件)。 很好-只要您相信自己是将文件放入可以从中导入的位置的唯一文件-包括您的工作目录。 您的“下载”文件夹不安全 正如名称为“ DLL Planting”的攻击类别所 表明的,可以通过多种方式欺骗浏览器(有时甚至是其他软件),而无需用户干预即可将具有任意文件名的文件放入Downloads文件夹。 浏览器开始更加认真地对待此类漏洞,并添加了各种缓解措施,以避免网站在访问它们时将其秘密地拖放到下载文件夹中。1个 即使采用缓解措施,也很难将其完全消除:例如,Content-DispositionHTTP标头的filename* 参数 完全存在,以允许站点选择下载到的文件名。 构成攻击 您已经习惯了python -m pip安装东西。您可以从完全值得信赖的网站上下载Python软件包,无论出于何种原因,都可以直接下载而不是在PyPI上安装Python滚轮。也许是内部的,也许是预发行的;随你。因此,您下载了totally-legit-package.whl,然后: 1个 2 ~$ cd Downloads ~/Downloads$ python -m pip install ./totally-legit-package.whl 这似乎是一件很合理的事情,但是对您而言,两周前您所不知道的是,您访问的一个完全不同的站点上有一些XSS JavaScript,该站点中已下载了pip.py带有恶意软件的XSS JavaScript 。 繁荣。 展示它 这是攻击的快速演示: 1个 2 3 4 5 ~$ 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 惊喜 就在几段前,我说过: 如果您运行的是已正确安装在计算机上的Python应用程序,则Python安装或virtualenv之外唯一会自动添加到您sys.path的位置(默认情况下)的位置是主可执行文件或脚本的安装位置。 。 那么,括号内的“默认情况”在做什么?还可以添加其他目录吗? 您的$PYTHONPATH 环境变量上的所有条目 。您不会将当前目录放在上 $PYTHONPATH,对吗? 不幸的是,您可能有一种偶然的常见方式。 让我们模拟一个“脆弱的” Python应用程序: 1个 2 3 4 5 # tool.py try: import optional_extra except ImportError: print("extra not found, that's fine") 制作2个目录:install_dir和attacker_dir。放进去 install_dir。然后,cd attacker_dir以我们使用的名称将我们复杂的恶意软件放在此处tool.py: 1个 2 # optional_extra.py print("lol ur pwnt") 最后,让我们运行它: 1个 2 ~/attacker_dir$ python ../install_dir/tool.py extra not found, that's fine 到目前为止,一切都很好。 但是,这是常见的错误。大多数仍然建议PYTHONPATH 您添加内容的地方,例如: 1个 export PYTHONPATH="/new/useful/stuff:$PYTHONPATH"; 从直觉上讲,这是有道理的。如果要在项目X中添加项目X $PYTHONPATH,也许项目Y已经添加了某些内容,也许没有;您永远都不想丢掉它,并替换掉您的shell启动其他功能可能要做的事情,特别是如果您正在编写许多人会使用的文档。 但是这个习惯用法有一个严重的缺陷:第一次调用它时,如果 $PYTHONPATH以前是空的或未设置的,则它包含一个空字符串,该字符串将解析为当前目录。让我们尝试一下: 1个 2 3 ~/attacker_dir$ export PYTHONPATH="/a/perfectly/safe/place:$PYTHONPATH"; ~/attacker_dir$ python ../install_dir/tool.py lol ur pwnt 不好了!好吧,为了安全起见,让我们清空$PYTHONPATH并再次尝试: 1个 2 3 ~/attacker_dir$ export PYTHONPATH=""; ~/attacker_dir$ python ../install_dir/tool.py lol ur pwnt 还是不安全! 这里发生的事情是,如果PYTHONPATH是空的,这是不一样的东西,因为它是未设置。从Python的范围内,这之间的区别 os.environ.get("PYTHONPATH") == ""和os.environ.get("PYTHONPATH") == None。 如果要确保$PYTHONPATH已从shell(或shell启动中的某处)清除,则需要使用以下unset命令: 1个 2 ~/attacker_dir$ python ../install_dir/tool.py extra not found, that's fine 设置PYTHONPATH曾经是设置Python开发环境的最常用方法;希望它在很大程度上不再受欢迎,而virtualenvs可以更好地满足这一需求。如果您有一个旧的Shell配置,但仍设置了$PYTHONPATH您不再需要的配置,那么这是一个很好的机会,可以继续删除它。 但是,如果您确实需要PYTHONPATH在shell启动中“附加到”成语,请使用以下技术: 1个 2 export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}new_entry_1" export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}new_entry_2" 在bash和zsh中,这都会导致 1个 2 $ echo "${PYTHONPATH}" new_entry_1:new_entry_2 $PYTHONPATH现在您的变量上没有多余的冒号或空白条目。 最后:如果您仍在使用$PYTHONPATH,请务必始终使用绝对路径! 相关风险 Downloads通过与Python进行交互,有很多与检查文件夹中文件有关的不安全行为。其他危险活动: 从任何地方运行python ~/Downloads/anything.py(即使anything.py它本身是安全的)-因为它将借助的位置将您的下载文件夹添加到。sys.pathanything.py Jupyter Notebook将笔记本所在的目录放在其中sys.path,就像Python在其中放置脚本目录一样。所以jupyter notebook ~/Downloads/anything.ipynb是一样危险python ~/Downloads/anything.py。 在运行它们之前,请从下载文件夹中获取这些脚本和笔记本! 但是cd Downloads,然后进行任何交互式的操作仍然是一个问题: 在文件夹中运行python -c包含import语句的命令~/Downloads python交互式运行并在~/Downloads文件夹中导入任何内容 请记住,这~/Downloads/并不特殊;这只是带有攻击者选择的文件名的意外文件可能潜入的地方。请注意其他确实存在的地方。例如,如果您管理的服务器可以让公众上传文件,请特别确保您的应用程序或任何可能运行的管理员都不python会这样做cd public_uploads。 也许考虑将处理上载的代码更改为文件名放在.uploaded末尾,以避免.py文件意外上载和执行的风险。 缓解措施 如果要在下载文件夹中使用Python编写的工具,请养成习惯,/path/to/venv/bin/pip而不是键入模块(/path/to/venv/bin/python -m pip),而是键入脚本的路径()。 通常,只需避免将其~/Downloads作为当前工作目录,并在启动它之前将要使用的所有软件移至更合适的位置。 了解Python从何处获取将要执行的代码非常重要。赋予某人执行任意一行Python的能力等同于赋予他们对您的计算机的完全控制权! 为什么我写这篇文章 在写有关安全性的“技巧”文章时,很容易暗示我(作者)非常聪明,因为他们知道这堆奇怪的琐事,并且是您(读者)保持安全的唯一方法,是为了记住一大堆同样深奥的东西,并不断地思考它。确实,该职位的先前草案无意间做到了这一点。但这是一个非常糟糕的想法,而不是我想参与其中的任何一个。 所以,如果我不想这么说,那为什么要发布它呢?我会解释。 在使用Python多年的过程中,我很少(但经常)看到用户对Python从中加载代码的位置感到困惑。这种混乱的一种形式是人们将使用Twisted的第一个程序放入名为的文件中twisted.py。这掩盖了库的导入,破坏了一切。这种混乱的另一种表现是缓慢的一堆混乱的安全报告,其中研究人员将模块放到有文档记录的位置,以便从Python加载代码(例如上述场景中的当前目录),然后加载该代码,并认为这反映了漏洞,因为它正在执行任意代码。 像这样的任何混乱-即使所讨论的系统“行为如预期”,并且无法轻易更改-都是攻击者可以利用的漏洞。 系统管理员和开发人员是网络犯罪世界中的高价值目标。如果您入侵某个用户,则会获得该用户的数据。但是,如果您黑掉了管理员或开发人员,并且操作正确,则可以访问数以千计的系统受管理员控制的用户,甚至数百万使用开发人员软件的用户。 因此,尽管“时刻保持谨慎” 并非可持续的安全方法,但在一定程度上,我们这些代表用户的用户确实有更大的义务要更加谨慎。至少,应该告知我们工具的行为。像Python这样的开发人员工具不可避免地是功能强大的工具,与一般应用程序相比,它们可能需要更多的关注和更高的准确性。 我上面所描述的完全不是“ bug”或“ exploit”。我不认为Python或Jupyter的开发商都做了什么错 ; 该系统按照设计的方式运作,并且其设计方式合理。我个人对如何在不删除Python大量功能的情况下可以进行更改没有任何好主意。 我最喜欢的安全发明之一是SawStop。发明之前,台锯的工作方式没有 错。它们是执行重要工业功能的极其危险的工具。用台锯做了很多非常有用和重要的事情。然而,也确实是因为台式锯造成了过多的木工事故,尤其是手指丢失。尽管有经验和安全意识强的木匠采取了很多措施,但SawStop仍然每年节省许多手指。 因此,通过强调这种潜在的危险,我也希望引起一些积极进取的安全工程师的思考。对于交互式解释器,任意代码执行的SawStop可能是什么?在不显着降低Python之类的工具功能的情况下,什么发明可以防止我在下面描述的某些情况? 朋友们,请确保在那里安全。 致谢 非常感谢保罗Ganssle,纳撒尼尔·史密斯,埃文·特纳,Trauring 和尼尔森Elhage为实质性的这篇文章上的前几稿的反馈。 任何错误仍然是我自己的。 限制哪些站点可以将文件偷渡到您的下载文件夹中是一项很好的安全功能,除了添加它的主要结果是,每个人似乎都对它感到烦恼,不了解它,并希望将其关闭。 ↩
收藏
举报
1 条回复
动动手指,沙发就是你的了!
登录
后才能参与评论