环境搭建:
1、下载 9.0.108 漏洞版本并解压:
https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.108/bin/apache-tomcat-9.0.108-windows-x64.zip
2、在 conf/server.xml 中添加如下开启 RewriteValve 配置:
1 | <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" /> |

3、创建 conf/Catalina/localhost/rewrite.config 并配置 RewriteValve 规则:
1 | RewriteCond %{QUERY_STRING} (^|&)path=([^&]+) |

漏洞分析:
根据漏洞描述可知:关键点在 RewriteValve 重写,其作用类似于Apache HTTP 服务器的 mod_rewrite 实现了 URL 重写功能。
https://tomcat.apache.org/tomcat-9.0-doc/rewrite.html

比如存在以下规则:/download?path=/WEB-INF/web.xml 会通过 RewriteValve 处理后变为 //WEB-INF/web.xml, 然后归一化(normalize)后变为 /WEB-INF/web.xml
1 | RewriteCond %{QUERY_STRING} (^|&)path=([^&]+) |
继续查看漏洞补丁:根源在于 RewriteValve 处理URL重写时,归一化步骤在URL解码之前执行,导致 %2f 无法被正确识别和归一化。
https://github.com/apache/tomcat/commit/b5042622b8b78340ae65403c55dcb9c7416924df?diff=split

补丁前:
1 | // 步骤1: 对重写后的URL进行编码 |
补丁后:
1 | // 步骤1: 先对编码的URL进行解码 |
比如以下请求 /download?path=%2FWEB-INF/web.xml,由于先归一化无法处理%2F,导致变成/%2FWEB-INF/web.xml,然后在URL解码变成//WEB-INF/web.xml。
org.apache.catalina.valves.rewrite.RewriteValve#invoke

而 tomcat 中的 StandardContextValve 会检查以 /WEB-INF/或 /META-INF/ 为开头的敏感路径,并且是在 RewriteValve 后才检查从而导致绕过。
org.apache.catalina.core.StandardContextValve#invoke

漏洞复现:
curl -i “http://localhost:8080/download?path=%2FWEB-INF/web.xml“
