tomcat对URL合法字符的判断(RFC 7230 and RFC 3986 异常排查)
為什么80%的碼農都做不了架構師?>>> ??
- 起因
有一個數據上報接口,之前在物理機上部署,數據上報正常。
最近將項目遷移到 docker 中,結果出現了異常如下:
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level. java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986at org.apache.coyote.http11.InternalInputBuffer.parseRequestLine(InternalInputBuffer.java:192)at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1028)at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)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)- 問題原因
問題排查過程:略
原因:請求中出現了字符"{"(示例請求)
https://127.0.0.1:8080/metric?data=[{%22app在不更改接口數據的前提下,解決方案為:在tomcat的cataline.properties追加配置
tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}官方文檔鏈接:http://tomcat.apache.org/tomcat-8.0-doc/config/systemprops.html#Other
| tomcat.util.http.parser.HttpParser. requestTargetAllow | A string comprised of characters the server should allow even when they are not encoded. These characters would normally result in a 400 status. The acceptable characters for this property are:?|,?{?, and?} WARNING: Use of this option will expose the server to CVE-2016-6816. If not specified, the default value of?null?will be used. |
- 問題來源
那么為什么之前接口不會出現異常呢?是tomcat版本不同導致的。
查看源碼后發現:org.apache.tomcat.util.http.parser.HttpParser
tomcat 8.2.3 版本及 tomcat 7.0.82 ,都有如下代碼,讀取配置
String prop = System.getProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow"); if (prop != null) {for (int i = 0; i < prop.length(); i++) {char c = prop.charAt(i);if (c == '{' || c == '}' || c == '|') {REQUEST_TARGET_ALLOW[c] = true;} else {log.warn(sm.getString("httpparser.invalidRequestTargetCharacter",Character.valueOf(c)));}} }而tomcat 8.0.14 版本中并沒有讀取配置,對 |?{?}?的處理,而是默認為合法字符。
static {// Setup the flag arraysfor (int i = 0; i < 128; i++) {if (i < 32) {isToken[i] = false;} else if (i == '(' || i == ')' || i == '<' || i == '>' || i == '@' ||i == ',' || i == ';' || i == ':' || i == '\\' || i == '\"' ||i == '/' || i == '[' || i == ']' || i == '?' || i == '=' ||i == '{' || i == '}' || i == ' ' || i == '\t') {isToken[i] = false;} else {isToken[i] = true;}if (i >= '0' && i <= '9' || i >= 'A' && i <= 'F' ||i >= 'a' && i <= 'f') {isHex[i] = true;} else {isHex[i] = false;}} }雖然沒有進行全面的比對,但可以看出在 8.0.x 左右的一些版本中,tomcat.util.http.parser.HttpParser. requestTargetAllow?這個配置是沒有生效的,即? |?{?}?這3個符號認為是合法的。
- 結論:
?
?
?
?
?
轉載于:https://my.oschina.net/pding/blog/1794176
總結
以上是生活随笔為你收集整理的tomcat对URL合法字符的判断(RFC 7230 and RFC 3986 异常排查)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 总结了一下Ubuntu常用命令
- 下一篇: 聊聊JvmGcMetrics的manag