【问题标题】:Is it safe to put information from an untrusted source as python exception message?将来自不受信任来源的信息作为 python 异常消息放置是否安全?
【发布时间】:2018-12-01 19:24:33
【问题描述】:

有没有以下危险的方法?如,如果有人将此异常打印到stdout,代码可以执行吗?

def somefunc(val_from_untrusted_source):
    if val_from_untrusted_source == 'something_we_except':
        # do something useful
        pass
    else:
        raise RuntimeException('unknown input: {}'.format(val_from_untrusted_source))

【问题讨论】:

    标签: python security code-injection


    【解决方案1】:

    永远不要那样做!

    日志消息旨在告知处理过程,并且应该安全地传递,以便在出现问题时找到所发生情况的证据。这里没有进行任何控制,所以这里有一些可能的问题:

    • str(val_from_untrusted_source) 本身可能会引发异常,其中 UnicodeEncodeError 用于 Python 2 中包含非 ASCII 字符的 unicode 字符串,或 UnicodeDecodeError 用于 Python 3 中包含非 ASCII 字符的字节字符串。这还包括特制的对象,引发异常__str__方法
    • str(val_from_untrusted_source) 可能是一个很长的字符串。它包括长字节或 unicode 字符串,还包括特制的微小对象:

      class DONT:
          def __init__(self, size, pattern):
              self.pattern = pattern
              self.size = size
          def __str__(self):
              return self.pattern * self.size
      

      它们可能导致日志文件耗尽磁盘空间

    • 可以使用永无止境的__str__ 方法或试图耗尽内存的方法来特制对象。想象一下上面DONT的细微变化...

    所有这些都是在代码不受控制的更糟糕的用例中可能发生的事情。在更实际的使用场景中,val_from_untrusted_source 可能是一个字符串。在那种情况下,限制它的大小并处理UnicodeError异常就足够了:

    if val_from_untrusted_source == 'something_we_except':
        # do something useful
        pass
    else:
        try:
            txt = str(val_from_untrusted_source)
        except UnicodeEncodeError:                # unicode string on Python 2
            txt = val_from_untrusted_source.encode(error = 'replace')
        except UnicodeDecodeError:                # byte string on Python 3
            txt = val_from_untrusted_source.decode(error = 'replace')
        except Exception:                         # quite weird but once we are there...
            txt = "object non convertible to string"
        if len(text) > 47):     # limit length to 50
            txt = txt[:47] + '...'
        raise RuntimeException('unknown input: {}'.format(txt))
    

    【讨论】:

    • 您关于手动制作的对象的最后一点可以用于带有参数的任何函数,无论它对它们做什么:我们可以通过这种方式“破解”min(a, b)。我想问题是关于可以来自应用程序外部的值(如字符串)。
    • @EugenePrimako:你说得对,主要风险在于字符串。我添加了特制对象主要是警告不控制字符串输入是不好的,不控制代码(想想evaling 服务)更糟糕。
    • 是否有任何一般模式反对在异常消息中包含上下文信息?
    • @Thijs:不是这样。您询问了可能存在的危险,我只是尽力做到详尽无遗……但请参阅我的编辑。
    【解决方案2】:

    据我所知,没有什么危险不可能发生。最不愉快的后果:

    1. (如果假定为 Python 2)如果 val_from_untrusted_source 不是 ASCII,则在尝试引发 RuntimeException 时会出现 UnicodeEncodeError
    2. 如果 val_from_untrusted_source 包含 '\r' 并且有人将此异常写入日志 - 当前日志行的开头可能会被覆盖

    【讨论】:

    • '\r' 只不过是一个字节。它仅在显示到终端或打印时返回到行首。但是六边形编辑器会很高兴地显示之前的内容、'\r' iteft(十六进制值 0x0d)和之后的内容。
    猜你喜欢
    • 2013-10-14
    • 2011-05-03
    • 1970-01-01
    • 2011-09-14
    • 2018-05-22
    • 1970-01-01
    • 2012-04-04
    • 2020-07-23
    • 1970-01-01
    相关资源
    最近更新 更多