Tomcat 8无法处理带有竖线“|”的查询参数的GET请求?

75

我正在使用Tomcat 8。在某些情况下,我需要处理来自外部源的外部请求,其中请求具有由|分隔的参数。

请求如下:

http://localhost:8080/app/handleResponse?msg=name|id|

在这种情况下,我收到以下错误。

java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:467)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:667)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:789)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

编辑1

它可以在Apache Tomcat 8.0.30上正常工作,但无法在Tomcat 8.5上工作。


5
好的,我猜你需要逃避它。 - Maurice Perry
你看过参考的RFC了吗? - clemens
RFCs旨在不断改进。 - Florian F
7个回答

78

此行为在所有主要Tomcat版本中引入:

  • Tomcat 7.0.738.0.398.5.7

要修复此问题,请执行以下操作之一:


根据更改日志,这些更改可能会影响此行为:

Tomcat 8.5.3:

确保使用不是标记所需的HTTP方法名称的请求会以400响应拒绝

Tomcat 8.5.7:

添加对HTTP请求行解析的有效字符的附加检查,以便更早地拒绝无效的请求行。


最佳选项(遵循标准)- 您希望在客户端对URL进行编码:

encodeURI("http://localhost:8080/app/handleResponse?msg=name|id|")
> http://localhost:8080/app/handleResponse?msg=name%7Cid%7C

或者只是查询字符串:

encodeURIComponent("msg=name|id|")
> msg%3Dname%7Cid%7C

它将保护您免受其他有问题的字符(无效URI字符列表)的影响。


3
谢谢,我刚将“apache-tomcat-8.5.11”降级到“apache-tomcat-8.0.30”,结果非常好。 - Bhuwan Gautam
4
我不建议降级Tomcat,因为最新版本的Tomcat已经包含了所有必要的CVE补丁,这些补丁可能已经影响了您降级的版本。编码URI参数可以解决问题,或者使用“relaxedQueryChars”选项。从长远来看,任何在代码中使用保留的RFC 3986字符的地方都应该重构。 - ha9u63a7
看起来relaxedQueryChars仍然只能被黑客攻击。Apache有没有提供任何合适的解决方案? - Suresh
对我来说,"encodeURIComponent" 的效果非常好!感谢您描述了替代修复方法。 - ljader
在Spring Boot的情况下,是否有任何属性文件更改? - Hafiz Hamza

54
自 Tomcat 7.0.76、8.0.42 和 8.5.12 版本开始,您可以定义属性 requestTargetAllow 来允许禁止的字符。请在您的 catalina.properties 文件中添加以下行:
tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}

1
从tomcat 8.5开始 #警告:使用此选项可能会使服务器暴露于CVE-2016-6816 #tomcat.util.http.parser.HttpParser.requestTargetAllow=| - Bhaskara Arani

18

tomcat.util.http.parser.HttpParser.requestTargetAllow这个参数已经自Tomcat 8.5版本起被废弃,详见Tomcat官方文档

你可以在连接器定义中使用relaxedQueryChars / relaxedPathChars来允许这些字符,详情请参考Tomcat官方文档


在8.5版本中,我尝试了这些方法,但没有任何效果。最好的选择是始终对URL进行编码。 - sproketboy

18

问题: Tomcat (7.0.88) 抛出以下异常,导致400 - 错误请求。

java.lang.IllegalArgumentException: Invalid character found in the request target. 
The valid characters are defined in RFC 7230 and RFC 3986.

这个问题在tomcat 7.0.88版本及以上的大部分版本中出现。

解决方案:(由Apache团队建议)

Tomcat增加了安全性,不再允许在查询字符串中使用未经转义的方括号。我们的请求中有方括号[ ](方括号),因此服务器无法处理该请求。

在server.xml(%TOMCAT_HOME%/conf)下的标签下添加relaxedQueryChars属性:

<Connector port="80" 
           protocol="HTTP/1.1"
           maxThreads="150"
           connectionTimeout="20000"
           redirectPort="443"
           compression="on"
           compressionMinSize="2048"
           noCompressionUserAgents="gozilla, traviata"
           compressableMimeType="text/html,text/xml"
                                     relaxedQueryChars="[,]"
             />

如果应用程序需要更多特殊字符,而这些特殊字符不被Tomcat默认支持,则将那些特殊字符以逗号分隔的形式添加到relaxedQueryChars属性中。


1
最新的Tomcat 8适用于DHIS2,因为这可以帮助某些人!!! - Nickromancer

7

URI被编码为UTF-8,但Tomcat将其解码为ISO-8859-1。您需要在server.xml中编辑连接器设置并添加URIEncoding="UTF-8"属性。

或在您的application.properties文件中编辑此参数

server.tomcat.uri-encoding=utf-8


在 server.xml 文件的 <Connector> 元素上设置 URIEncoding 属性为特定值(例如:URIEncoding="UTF-8"),以解决字符编码问题。更多信息请参考 https://wiki.apache.org/tomcat/FAQ/CharacterEncoding。 - hwak
@hwak,你的链接挂了。 - payne
找到类似的链接 https://cwiki.apache.org/confluence/display/TOMCAT/Character+Encoding - hwak

5

需要转义它。管道符号是一种在不同时间和浏览器之间处理方式不同的符号。例如,在复制/粘贴URL时,Chrome和Firefox会以不同的方式转换带有管道符的URL。然而,最兼容的方式,也是在Tomcat 8.5中必需的方法似乎是对其进行转义:

http://localhost:8080/app/handleResponse?msg=name%7Cid%7C


4
在我的情况下,将"relaxedQueryChars"属性添加到server.xml中起作用了。
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="443" URIEncoding="UTF-8" relaxedQueryChars="[]|{}^&#x5c;&#x60;&quot;&lt;&gt;"/>

如何允许在URL中使用#号? relaxedQueryChars="^{}|[]_#",我正在使用Tomcat 8.5.27。 - Sundar G
尝试:# 因此,可能会像这样: relaxedQueryChars="[]|{}^\`"<>#" - Yasmin AM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接