【安全问题】Python 的 Bug?

起因是前几天写一个 Python 项目的时候发现 elpy-format-code 提示找不到 yapf,可能和同目录下一个名为 types.py 的文件有关,最近深入研究了以下发现是 elpy 在 venv 环境下用 python -c "import yapf" 判断 yapf 是否存在时引发异常。

然后神奇的事情来了,我发现 venv 环境下的 Python 引入 types 时会优先引入工作目录下的 types.py,而且 Python shell 和 yapf 都会引入 types,如图。

这意味这如果攻击者在代码库的 types.py 中放些恶意代码,任何激活了 venv 的用户在该目录下运行 Python shell 或 yapf 都会执行恶意代码,例如 elpy。

这是不是要给 Python 报个 Bug? :thinking:

1 个赞

参考 Python 官方手册:6. Modules — Python 3.12.2 documentation

When a module named spam is imported, the interpreter first searches for a built-in module with that name. These module names are listed in sys.builtin_module_names. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path. sys.path is initialized from these locations:

  • The directory containing the input script (or the current directory when no file is specified).
  • PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
  • The installation-dependent default (by convention including a site-packages directory, handled by the site module).

看上去,优先引入工作目录下文件的行为是符合预期的

尝试在types.py文件中添加读/写文件的代码试试,或其他能够肯定该文件被执行了的代码,若达到预期效果,是有被利用的可能的。但条件依旧十分苛刻,对方需要有读写types.py文件的权限,或通过其他漏洞达到这个效果。

当然,它也可以在他人入侵后,被对方用于持久性后门,如果这个文件会被频繁使用的话。这类文件不少,攻击者有其他更保险的选择。

我比较菜,个人猜测,有误轻喷。

linux系统存在大量类似的机制,例如根据环境变量加载某些外部模块。如果系统已经被入侵,那跟python也没有啥关系了。

这个路径查找机制是合理的。

P.S. 只要你使用外部代码库,就会有被攻击的可能,有无数种注入恶意代码的方式,所以应该避免在不做防护的情况下使用来路不明或未经验证的代码

个人认为这是合理的,优先从项目目录加载代码, 可以自己改动模块代码. 实际上是开发者的疏忽,不属于攻击范围.

types 是内置模块,而且是否使用 venv 的行为并不一致,只有使用 venv 时才会优先加载 types.py。

可能 clone 个仓库下来仅浏览代码都不安全了。

可以的。条件并不苛刻,在开源的 Python 项目里创建 types.py 即可,可以是流行的项目,也可以是钓鱼的项目。只要用户在项目目录内在 vnev 环境下用 Python shell 或其它 Python 工具就能执行恶意代码。

钓鱼,投毒的话确实可行。

types 是内置模块

其实并不是。内置模块是 sys.builtin_module_names 里面列举的那些。

是否使用 venv 的行为并不一致,只有使用 venv 时才会优先加载 types.py

你可以试着加一下 -S 参数,看看行为是否一致。site module 的行为有可能影响其他模块的引入

2 个赞

我用pylsp遇到过一样的问题。后来发现只要装pylsp或yapf时所对应的python和执行自己代码的python不是同一个就好了。比如用conda把pylsp装进python3.11里。然后自己代码用python3.6之类的。其实跟版本无关,主要是得不同的python。

如: pkexec 的 GCONV_PATH

你是对的,venv 环境默认配置带 -S 参数,所以这不是 venv 的问题而是 -S 的问题。