Python的cgi.FieldStorage有一些问题

173 阅读3分钟

在我关于我们对cgi 模块的有限使用的文章中,我赞扬了 [cgi](https://docs.python.org/3/library/cgi.html).FieldStorage 是编写处理参数的 Python CGI 的一种很好的简单方法,特别是对于POST 表格。不幸的是,cgi.FieldStorage 也有一些阴暗面(除了它可能存在的任何错误),为了公平起见,我应该讨论一下。总的来说,cgi.FieldStorage 对于内部使用来说可能是安全的,但我对在不友好的情况下将其暴露在互联网上还是有点担心的。最终的问题是,在方便和工作的名义下,cgi.FieldStorage 对其输入相当信任,而在一般的网络上,安全的大规则之一是你的输入完全在攻击者的控制之下。

因此,这里有一些问题,cgi.FieldStorage ,如果你把它暴露给敌对的一方。第一个广泛的问题是,FieldStorage没有任何限制:

  • 它允许人们向你上传文件,不管你是否期望如此;文件被写入本地文件系统。现代版本的FieldStorage 至少在 Python 垃圾收集器销毁 FieldStorage 对象时删除文件。

  • 它对接受多大的POST 体或等待多长时间读入POST 体没有限制(或等待多长时间上传文件)。一些网络服务器CGI环境可能会对这些施加自己的限制,特别是时间,但攻击者可能至少可以淹没你的内存。

    (FieldStorage的init函数确实有一些参数,可以用来设计一些限制,额外的工作是将标准输入包裹在一个类似文件的东西中,施加大小和时间限制。对于大小限制,你也可以预先检查内容长度)。

然后还有一个普遍的问题,即GETPOST 参数实际上并不真正像 Python 的 dict (或任何语言的形式)。所有类似字典的东西都需要唯一的键,但攻击者可以自由地在他们的请求中提供重复的键。FieldStorage在这里的行为没有得到很好的定义,但它可能把任何给定参数的最后一个版本作为真正的参数。如果你的软件栈中的其他东西对重复的参数有不同的解释,你的CGI和其他组件实际上是看到了两个不同的请求。这是一个典型的获得安全漏洞的方法。

(FieldStorage也有默认的自由解析,尽管你可以用一个初始函数参数来改变它。顺便说一句,初始函数的参数都没有在 cgi文档中没有涉及,你必须阅读help() 或cgi.py的源代码)。

广义上讲,cgi.FieldStorage感觉像是一个早期网络编程时代的产物,在那个时代,CGI是非常重要的东西,网络是一个更小的、表面上更友好的地方。对于一个或多或少只需要处理来自正确编程的浏览器的友好输入的内部网应用程序来说,它仍然是完美的,不太可能爆炸。对于一般的现代互联网使用来说,就不是那么回事了,即使你还在使用CGI。