应用程序希望解析并“执行”一个文件,并且为了安全起见,希望断言该文件是可执行的。
稍作思考,您就会意识到这个初始代码有一个使安全方案无效的竞争条件:
import os
class ExecutionError (Exception):
pass
def execute_file(filepath):
"""Execute serialized command inside @filepath
The file must be executable (comparable to a shell script)
>>> execute_file(__file__) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
ExecutionError: ... (not executable)
"""
if not os.path.exists(filepath):
raise IOError('"%s" does not exist' % (filepath, ))
if not os.access(filepath, os.X_OK):
raise ExecutionError('No permission to run "%s" (not executable)' %
filepath)
data = open(filepath).read()
print '"Dummy execute"'
print data
竞争条件存在于
os.access(filepath, os.X_OK)
和
data = open(filepath).read()
因为在这两个系统调用之间,文件可能被具有不同内容的不可执行文件覆盖。
我拥有的第一个解决方案是更改关键调用的顺序(并跳过现在的冗余存在检查):
fobj = open(filepath, "rb")
if not os.access(filepath, os.X_OK):
raise ExecutionError('No permission to run "%s" (not executable)' %
filepath)
data = fobj.read()
这能解决比赛条件吗?我怎样才能正确地解决它?
安全方案的基本原理(我想)
该文件将能够在其内部执行任意命令。
环境,因此可以与shell脚本进行比较。
在带有.desktop文件的免费桌面上有一个安全漏洞
应用程序:该文件可以使用参数指定任何可执行文件,以及
它可以选择自己的图标和名称。所以随机下载的文件可以隐藏
在任何名字或图标后面,做任何事情。那太糟糕了。
这是通过要求.desktop文件具有可执行位来解决的。
设置,否则将不使用名称/图标和自由桌面呈现它们
将在开始前询问用户是否要启动程序。
与MacOSX的设计相比:“这个程序是从网上下载的,
你确定要打开它吗?”.
所以在寓言中,你必须
chmod +x
壳
你下载的脚本,我在上面的问题中考虑了设计。
结束语
最后,也许我们应该保持简单:如果文件必须是可执行的,那么让它成为可执行的,并让内核在用户调用时执行它。将任务委派到它所属的位置。