前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python eval安全案例

Python eval安全案例

作者头像
用户1416054
发布2018-08-02 11:43:49
1.1K0
发布2018-08-02 11:43:49
举报
文章被收录于专栏:JackeyGao的博客

Python eval安全案例

Posted June 13, 2017

关于Python的eval函数, 大家一致的避免使用。 但有时候必须使用, 怎么保证安全呢? 下面我用一个案例来避免eval潜在的风险。 当然这只是其中的一种。

我的使用场景是这样的, 要把mongodb中的输出bson类型转换成JSON。 我需要转换的JSON是这样的, 看样子是个map类型, 但不是JSON类型, 确切的说他是bson类型。

bson

代码语言:javascript
复制
{
  "_id" : ObjectId("58e4506f0b14fcb6cb4ecf76"),
  "database" : "test",
  "collection" : "users",
  "command" : "count",
  "params" : {
    "count" : "users"
  },
  "start_time" : ISODate("2017-04-05T10:03:27.777Z"),
  "end_time" : ISODate("2017-04-05T10:03:27.780Z")
}

以上我们需要在作用域中有ObjectId对象, 和ISODate对象, 来分别做两个类型的实例化。 实例化后再通过json.dumps转换为JSON字符串. 所以我想到了eval, 把ObjectId和ISODate分别创建对应的函数.

为了安全考虑,对eval的globals参数中的__builtins__设置为空, 避免掉使用所有内置函数, 然后通过eval第三个参数locals进行实现白名单的机制(safe_map安全映射)。

Python

代码语言:javascript
复制
#! -*- coding: utf-8 -*-
import arrow, re
from bson.son import SON
from bson.binary import Binary, UUIDLegacy, STANDARD
from bson import ObjectId as objectid

ReplaceStrings = (
    ('new.*.Date', 'Date'),
    ('new.*.String', 'String'),
    ('new.*.ObjectId', 'ObjectId')
)


def ObjectId(_id):
    return objectid(_id)


def Date(string=''):
    if string:
        return arrow.get(string).datetime
    else:
        return arrow.get().datetime

def ISODate(string=''):
    return Date(string)


null = None
true = True
false = False


# 定义安全函数列表
SAFES = ('ObjectId', 'Date', 'null', 'true', 'false', 'SON', 'True', 'False', 'ISODate')
SAFE_MAPS = dict(
    [ (k, locals().get(k, None)) for k in SAFES ]
)


def to_python(string):
    """
    把Python代码转换为BSON代码

    目前支持的BSON类型有
        - ObjectId
        - Date
    """
    _string = '''x = %s''' % string

    # 批量替换区
    for _from, _to in ReplaceStrings:
        _string = re.sub(_from, _to, _string)

    x = {
        "error": "E10051",
        "message": "转换BSON失败"
    }

    # 开始转换
    try:
        exec(
            _string,
            {'__builtins__': None},
           SAFE_MAPS
        )

        x = SAFE_MAPS.get('x', x)
    except NameError as e:
        return {
            "error": "E10050",
            "message": str(e)
        }
    except Exception as e:
        return {
            "error": "E10055",
            "message": str(e)
        }

    return x

通过以上的to_python函数转换字符串到python实例. 在通过json.dumps转换json字符串, 然后就可以得到以下结果.

JSON

代码语言:javascript
复制
{
  "_id": "58e4506f0b14fcb6cb4ecf76",
  "collection": "users",
  "command": "count",
  "database": "test",
  "end_time": "2017-04-05T10:03:27.777Z",
  "params": {
    "count": "users"
  },
  "start_time": "2017-04-05T10:03:27.780Z"
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Python eval安全案例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档