在 Python 中根据不安全的用户输入评估数学方程

2024-02-24

我有一个网站,用户在其中输入数学方程(表达式),然后根据网站提供的数据(常数)评估这些方程。需要的数学运算包括符号、算术运算、min(), max()以及其他一些基本功能。示例方程可以是:

max(a * b + 100, a / b - 200)

人们可以简单地eval()这是使用 Python 进行的,但众所周知,这会导致网站受到损害。进行数学方程评估的安全方法是什么?

如果选择使用Python本身来计算表达式,是否有任何Python沙箱会限制Python,以便只有用户提供的运算符和函数可用。成熟的 Python,比如定义函数,应该完全禁用。子进程没问题(参见PyPy沙箱 http://pypy.readthedocs.org/en/latest/sandbox.html)。特别是,应该关闭 for 循环和其他利用内存和 CPU 使用的漏洞。


免责声明:我是另一个答案中代码中提到的 Alexer。老实说,我只是半开玩笑地建议了字节码解析方法,因为我碰巧有 99% 的代码都在一个不相关的项目中,所以可以在几分钟内快速组合出一个 POC。也就是说,它本身不应该有任何问题;只是这项任务需要更复杂的机器。事实上,你should只需反汇编代码[根据白名单检查操作码],检查常量和名称是否有效,然后用简单的、邪恶的 eval 执行它就可以逃脱惩罚。您应该失去在整个执行过程中插入偏执的额外检查的能力。 (另一个免责声明:我仍然觉得用 eval 来做这件事还不够舒服)

不管怎样,我有一个无聊的时刻,所以我写了一些代码来以聪明的方式做到这一点;使用 AST 而不是字节码。这只是一个额外的标志compile()。 (要不就ast.parse(),因为无论如何你都需要模块中的类型)

import ast
import operator

_operations = {
        ast.Add: operator.add,
        ast.Sub: operator.sub,
        ast.Mult: operator.mul,
        ast.Div: operator.div,
        ast.Pow: operator.pow,
}

def _safe_eval(node, variables, functions):
        if isinstance(node, ast.Num):
                return node.n
        elif isinstance(node, ast.Name):
                return variables[node.id] # KeyError -> Unsafe variable
        elif isinstance(node, ast.BinOp):
                op = _operations[node.op.__class__] # KeyError -> Unsafe operation
                left = _safe_eval(node.left, variables, functions)
                right = _safe_eval(node.right, variables, functions)
                if isinstance(node.op, ast.Pow):
                        assert right < 100
                return op(left, right)
        elif isinstance(node, ast.Call):
                assert not node.keywords and not node.starargs and not node.kwargs
                assert isinstance(node.func, ast.Name), 'Unsafe function derivation'
                func = functions[node.func.id] # KeyError -> Unsafe function
                args = [_safe_eval(arg, variables, functions) for arg in node.args]
                return func(*args)

        assert False, 'Unsafe operation'

def safe_eval(expr, variables={}, functions={}):
        node = ast.parse(expr, '<string>', 'eval').body
        return _safe_eval(node, variables, functions)

if __name__ == '__main__':
        import math

        print safe_eval('sin(a*pi/b)', dict(a=1, b=2, pi=math.pi), dict(sin=math.sin))

这与字节码版本同样适用;如果您根据白名单检查操作并检查名称和值是否有效,那么您应该能够在 AST 上调用 eval 。 (但是,我还是不会这样做。因为偏执。当涉及评估时,偏执是好的)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Python 中根据不安全的用户输入评估数学方程 的相关文章

随机推荐

  • Drools 知识库 已弃用

    我正在将 Drools 规则引擎集成到我的应用程序中 我发现的 99 的入门示例如下 KnowledgeBuilder kbuilder KnowledgeBuilderFactory newKnowledgeBuilder kbuilde
  • 如何验证 WTForms 中的日期字段

    在我的 Flask 应用程序中 我有一个 WTForm 其中有两个日期选择器 分别用于 开始日期 和 结束日期 验证 结束日期 不早于 开始日期 的最佳方法是什么 from flask wtf import FlaskForm from w
  • .NET 自定义事件组织帮助

    作为 C 的新手 我最近一直在研究自定义事件 虽然我认为我现在了解设置自定义事件所需的基本部分 但我无法确定where每件作品都属于 具体来说 这就是我正在尝试做的事情 我有一个表示内部数据结构布局的树控件 当数据在树中重新排列 通过拖放
  • 傅立叶级数数据与 numpy 的拟合:fft 与编码

    假设我有一些数据 y 我想对其进行傅立叶级数拟合 对此post https stackoverflow com questions 4258106 how to calculate a fourier series in numpy 解决方
  • HttpClient 不从 CookieContainer 发送 cookie

    我正在使用 Visual Studio 2012 开发带有 WPF NET 4 0 客户端的 ASP WebAPI ASP MVC 4 应用程序 客户端需要登录到服务器 我使用带有身份验证 cookie 的 FormsAuthenticat
  • MS Access 子表单在表单视图中带有#Error 字段

    微软访问 2003 我在子表单后面有一个查询 其中有如下 sql 语句 SELECT ClientTotalInvoiceLineItems CDate GetWeekEnding WeekEnding1 WeekEnding2 WeekE
  • 使用内容配置作为文件名下载 Node.js 文件

    我正在使用 Request 模块下载文件 但是当文件名必须来自 Content Disposition 标头时 我不太确定如何将响应传输到输出流 所以基本上 我需要读取响应直到找到标头 然后将其余部分通过管道传输到该文件名 这些示例显示如下
  • 检查残差并可视化零膨胀泊松 r

    我正在为 CPUE 数据运行零膨胀模型 该数据有零通货膨胀的证据 我已通过 Vuong 测试 在下面的代码中 确认了这一点 根据 AIC 的说法 完整模型 zint 优于零模型 我现在想要 检查完整模型的残差以确定模型拟合 由于缺乏来自同事
  • Javascript 设置按钮处于活动状态

    我有一个按钮表 一旦填充完毕 我就会使用 document getElementById btn0 click 单击第一个按钮 该按钮正在执行其应该执行的操作 但是按钮的背景颜色并没有像我手动单击它时那样改变 正如您所看到的 当它运行时 d
  • Rails 这个查询是否对 sql 注入开放?

    我仍在学习如何使用 ActiveRecord 编写良好的查询 我很好奇这个查询是否会受到 sql 注入的影响 因为我在查询中使用日期字段的方式 有人可以指出任何明显的错误或任何更好的方法来编写这个查询吗 arrangements for m
  • MEAN.js 社交共享?

    因此 我使用 MEAN js 构建了一个应用程序 并对文章 博客 部分进行了一些更新 以实现更好的 SEO 可读性 设计等 不过 我似乎无法弄清楚的一个问题是如何共享使用 Facebook Google Twitter 等的文章 并让它们使
  • (#5) Heroku Rails APP 上出现未经授权的源 IP 地址错误

    当有人尝试通过 Facebook 登录时 我的 Heroku 应用程序 FoR 开始抛出此错误 5 Unauthorized source IP address 发生这种情况是因为我的 Heroku 机器 与其他应用程序共享 的 IP 地址
  • Silverlight 4.0 + MVC 2.0 + WCF RIA 服务 + EF 4.0 = 加载错误

    我正在尝试建立一个具有以下内容的网站 VS 2010 用于更新的 WCF RIA 服务 Silverlight 4 0 与 WCF RIA 服务打包在一起 MVC 2 EF 4 0 我将其设置为面向公众的页面将是来自 MVC 的 html
  • 配置 Microsoft Azure Web App 的远程 IIS 管理后找不到 Microsoft.Web.Configuration.AppHostFileProvider

    几个月前 我可以成功地为我的 Azure Web 应用程序配置远程 IIS 管理 更换办公室后 我发现在新计算机上配置远程 IIS 管理后 当我尝试单击我的网站时遇到以下错误 我使用 Internet 信息服务 版本 10 0 16299
  • 写入终端和文件 C++

    我发现这个问题适用于 Python Java Linux 脚本 但不适用于 C 我想将 C 程序的所有输出写入终端和输出文件 使用这样的东西 int main freopen myfile txt w stdout cout lt lt L
  • 如何在 HTML 中的 Image-Click 上播放声音?

    当我单击或将鼠标悬停在播放按钮上时 我尝试播放声音吗 这是我到目前为止所拥有的 我有一个按钮 如果我将鼠标悬停在它上面 它会更改图像 现在我还希望它播放 mp3 play a position relative float left wid
  • 请求遵循重定向而不发送数据

    我在用着请求 js https github com request request用于 Node js 中的 http 请求 request method POST uri http www example com getData fol
  • 通过 Kotlin Coroutine Flow 压缩网络请求

    我有一个通过 RxJava 压缩两个网络请求的代码 Single zip repository requestDate repository requestTime date time gt Result date time 代表着repo
  • 如何在 systemd 控制组之外启动进程

    我有一个服务器进程 从 systemd 启动 可以启动更新进程 更新过程自行守护进程 然后 理论上 使用 SIGTERM 终止服务器 我的问题是 SIGTERM 传播到更新过程这是孩子们 出于调试目的 更新进程只是休眠 然后我手动发送终止命
  • 在 Python 中根据不安全的用户输入评估数学方程

    我有一个网站 用户在其中输入数学方程 表达式 然后根据网站提供的数据 常数 评估这些方程 需要的数学运算包括符号 算术运算 min max 以及其他一些基本功能 示例方程可以是 max a b 100 a b 200 人们可以简单地eval