CherryPy 隐藏版本信息
CherryPy 默认会在响应的头部带上服务器的版本号,但一些安全扫描软件会认为这是一个漏洞:
# https://github.com/cherrypy/cherrypy/blob/v18.1.1/cherrypy/_cprequest.py#L839
class Response(object):
def __init__(self):
dict.update(self.headers, {
'Content-Type': 'text/html',
'Server': 'CherryPy/' + cherrypy.__version__,
'Date': httputil.HTTPDate(self.time),
})
针对每个请求的处理修改返回的服务器信息字段,有如下两种方式:
@cherrypy.expose
@cherrypy.tools.response_headers(headers=[("Server", "wtf")])
def index(self):
return self.health()
@cherrypy.expose
def index(self):
cherrypy.serving.response.headers['Server'] = "wtf"
return self.health()
但比较坑爹的是,favicon 使用了 staticfile 进行处理,同样会返回版本信息:
# https://github.com/cherrypy/cherrypy/blob/v18.1.1/cherrypy/_cptree.py#L234
def mount(self, root, script_name='', config=None):
# If mounted at "", add favicon.ico
needs_favicon = (
script_name == ''
and root is not None
and not hasattr(root, 'favicon_ico')
)
if needs_favicon:
favicon = os.path.join(
os.getcwd(),
os.path.dirname(__file__),
'favicon.ico',
)
root.favicon_ico = tools.staticfile.handler(favicon)
此外,404 之类的错误也会返回版本信息。
显然,上面提到的通过给每个请求单独修改响应的方式行不通,不过 CherryPy 的 hook 机制比较强大,可以通过配置的方式给所有的响应都添加处理:
cherrypy.config.update({
'tools.response_headers.on': True,
'tools.response_headers.headers': [("Server", "wtf")]
})
但是,还一个更坑爹的是 CherryPy 直接在错误页面返回了版本信息:
https://github.com/cherrypy/cherrypy/blob/v18.1.1/cherrypy/_cperror.py#L467
<body>
<h2>%(status)s</h2>
<p>%(message)s</p>
<pre id="traceback">%(traceback)s</pre>
<div id="powered_by">
<span>
Powered by <a href="http://www.cherrypy.org">CherryPy %(version)s</a>
</span>
</div>
</body>
可以通过如下的方式进行修改:
from cherrypy import _cperror as cperror
cperror._HTTPErrorTemplate = "wtf"
参考资料
CherryPy — A Minimalist Python Web Framework
https://docs.cherrypy.org/en/latest/index.html
CherryPy Extend
https://docs.cherrypy.org/en/latest/extend.html
Hook into Cherry Pys Core Engine
https://www.pythonstudio.us/cherrypy-guide/hook-into-cherrypys-core-engine.html
最后修改于 2019-05-30