博客主页:https://tomcat.blog.csdn.net
博主昵称:农民工老王
主要领域:Java、Linux、K8S
期待大家的关注💖点赞👍收藏⭐留言💬
目录
- 故障详情
- 问题原因
- 注意事项
- 两次失败的尝试
- relaxedPathChars & relaxedQueryChars
- error-page
- 解决方案:ErrorReportValve
故障详情
Acunetix是一款网络漏洞扫描软件,它可以检测网络的安全漏洞。在最近的工作中,接到售后同事反馈,用户通过Acunetix扫描我经手开发的java web项目在Acunetix的漏洞扫描过程中,出现大量报错,未能通过检查。
经过了解后得知,Acunetix会自动地在每个接口对应的URL后面,加上各种奇怪的字符串,如:" 12345’“'”);|]*%00{%0d%0a<%00>%bf%27’💩 ",就得到了下面这个奇怪的URL:
https://test.laowang.cn/app/help/12345'"\'\");|]*%00{%0d%0a<%00>%bf%27'💩.htm
Acunetix的漏洞扫描,就是访问这个URL,并查看其返回值是否有问题。而上面这个URL的访问,会导致Tomcat报“java.lang.IllegalArgumentException: 在请求目标中找到无效字符。”
如下图所示:
实际上这个报错是正常的,是没有安全隐患的,但是Acunetix依然认为这些报错所展示的堆栈信息是非常敏感的,可能被不法分子利用。这就是Acunetix扫描到的所谓的“安全漏洞”,如下图所示:
问题原因
面对这个问题,我明确的知道,这不是我开发的war包的问题,而是用户运行war包的Tomcat的配置不对。但作为乙方,我们有必要给甲方提供一个解决方案,让用户的Tomcat不再返回那些堆栈信息。
所以解决这个问题,就是修改Tomcat的配置文件。
注意事项
解决问题的第一步就是在我的开发环境中复现这个报错,我随机复制Acunetix扫描的两个URL,然后尝试访问。
https://test.laowang.cn/app/login?pass=h-5'"/'/");|]*%00{
https://test.laowang.cn/app/help/12345'"\'\");|]*%00{%0d%0a<%00>%bf%27'💩.htm
第一个URL还好,通过浏览器都能访问。但第二个URL,依次通过谷歌浏览器、火狐浏览器、Postman去访问都遇到了问题。谷歌浏览器检测到URL中有异常字符,就会直接跳转到谷歌搜索。火狐浏览器和Postman不能正常识别部分字符,并产生了乱码。
幸好,公司的一位大佬告诉我用Fiddler可以规避这些问题。
访问效果如下:
两次失败的尝试
relaxedPathChars & relaxedQueryChars
最开始,售后同事没有给我提到Acunetix,她只是说有些接口都报同一个错误,并发过来一个示例接口。访问后,我发现这个报错是我遇到过的。在Tomcat的server.xml中的Connector节点内加上 relaxedPathChars="|{}[],%" relaxedQueryChars="|{}[],%
就可以
双引号内的字符可以根据你的实际需求来加,需要通过什么字符都可以加上,我在测试时发现有“\
”,所以我最终改出来的Connector节点如下所示:
<Connector
port="443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https"
secure="true" clientAuth="false" sslProtocol="TLS" URIEncoding="UTF-8"
keystoreFile="conf/tomcat.keystore" keystorePass="024116cb67"
relaxedPathChars="|{}[],%\" relaxedQueryChars="|{}[],%\"
/>
自测示例接口的访问是没问题的,我以为解决问题了,就将这个方案交给了售后同事。一天后,售后同事反馈,并没有解决问题,并远程演示了Acunetix的漏洞扫描。这时我才明白,原来不是某几个固定URL的报错,而是Acunetix会随机生成异常字符,并组装几千个URL进行访问。所以这个解决方案是不对的,毕竟不可能把全部的异常字符写上去,而且通过全部的异常字符也是不安全的。
error-page
既然目标是不显示那些堆栈信息,我第一个想到的是在Tomcat全局设置一个自定义的400的错误页面。
我在Tomcat的webapps\ROOT新增了400.html页面,并在conf/web.xml中的web-app节点的下一层加入了如下内容:
<error-page>
<error-code>400</error-code>
<location>/400.html</location>
</error-page>
但访问后未生效。我又加入了如下内容:
<error-page>
<exception-type>java.lang.IllegalArgumentException</exception-type>
<location>/400.html</location>
</error-page>
依然未生效,为了排查我填写的格式和文件位置是否存在问题,我按照相同的方法,设置了404错误页面,测试是能正常访问的。
原来,高版本的Tomcat改进了错误处理(已验证了Tomcat8,Tomcat9属于这种情况) ,将某些的错误,尤其是发生在请求处理开始之前的错误,传递给标准错误处理机制,而不仅仅是返回错误代码。因此通过设置error-page无法修改400的错误页面。
解决方案:ErrorReportValve
通过查阅资料得知,在server.xml中的Host//Engine/Service/Server节点下添加ErrorReportValve如下配置可以隐藏报错堆栈信息:
<Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" />
我就这样解决了问题。
测试如下:
如果希望能异常Tomcat服务器的详细(上图中的“Apache Tomcat/9.0.36”),还可以加上 showServerInfo="false"
。
如果希望自定义错误页面,还可以加上errorCode.${error-code}="${错误页面路径}l"
。
<Valve className="org.apache.catalina.valves.ErrorReportValve"
errorCode.400="webapps/ROOT/400.html"
showReport="false"
showServerInfo="false"
/>
如需转载,请注明本文的出处:农民工老王的CSDN博客https://blog.csdn.net/monarch91 。