我有一个Pyramid web应用程序,它设置了fail2ban,可以监禁连续十个404状态(即探测漏洞的机器人),Sentry错误日志,据我所知,不存在安全漏洞。然而,每隔几天我就会收到一个由空字节攻击引起的502通知。这是无害的,但它已经变得非常令人厌倦,我忽略了一个奇怪但合法的人类用户——结果产生了502状态。
在我的设置中,Pyramid中的一个空字节攻击在url调度级别引发了URLDecodeError('utf-8' codec can't decode byte 0xc0 in position 16: invalid start byte
),因此不会路由到notfound_view_config
装饰视图。
是否有任何方法可以在Pyramid中捕获请求中的%EF
/%BF
,或者我应该在Apache中阻止它们?
Steve Piercy的评论转换为答案:在Pyramid问题跟踪器中搜索会产生几个相关结果。第一次命中提供了一种处理方法。
简而言之,视图构造函数类exception_view_config(ExceptionClass, renderer)
捕获它的行为类似于notfound_view_config
或forbidden_view_config
(与view_config
相比,它们不是传递声明的路由)。
因此404视图可能看起来像:
from pyramid.view import notfound_view_config
from pyramid.exceptions import URLDecodeError
from pyramid.view import exception_view_config
@exception_view_config(context=URLDecodeError, renderer='json')
@notfound_view_config(renderer='json')
def notfound_view(request):
request.response.status = 404
return {"status": "error"}
这可以通过访问浏览器http://0.0.0.0: /%EF%BF
(服务端口在哪里)进行测试。
然而,还有两个额外的考虑因素。
- 它与调试工具栏(本地配置ini文件中的
pyramid.includes = pyramid_debugtoolbar
)配合不好 - 此外,如果访问任何像
request.path_info
这样的动态属性,就会引发错误。因此,要么对响应进行最小格式化,要么在视图中的任何操作(例如使用数据等)之前为request.environ['PATH_INFO']
分配一个新值。然而,视图调用发生在debugtoolbar错误引发之后,因此即使使用request.environ['PATH_INFO'] = 'hacked'
,第一点仍然有效
奖金
由于这无疑是一种攻击,因此可以对其进行定制,以便在第一次发生时使用唯一的状态代码(如418),很好地利用fail2ban来阻止黑客IP。