JSP 包含文件的四种方法
- 在不修改配置文件,Tomcat 默认的环境下,主要有以下四种方法包含文件
- 不管何种方法,如果想要包含并执行 jsp/jspx 脚本,那么被包含文件的内容必须是完整的 jsp/jspx 语法的内容
- 总的来说,越靠前介绍的方法用来绕过 webshell 检测的效果越好
- 下面四种方法均不能随意跳目录,想要包含文件并且执行的话,除了文件后缀要注意外,被包含的文件一定要放置在web根及其子目录下
0x01: 四种方法
方法一:include指令标签
<jsp:directive.include file="include.png"/>
- 先包含再编译成
servlet
- 方法二的另一种写法,不太常见
方法二:include指令
<%@ include file="include.png"%>
- 先包含再编译成
servlet
- 不限制被包含文件的文件扩展名
- file 路径可以用
../
跳目录,但不能跳出web根目录
方法三:include动作标签
<jsp:include page="include.jsp"/>
- 先编译成
servlet
再包含 - 限制被包含文件的文件扩展名只能是可执行脚本文件,如
jsp/jspx
- file 路径可以用
../
跳目录,但不能跳出web根目录
方法四:jstl 标签
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:import url="/include.jsp" context="/"></c:import>
- 先编译成
servlet
再包含 - lib 库中必须引入
taglibs-standard-impl-*.jar
和taglibs-standard-spec-*.jar
- 限制被包含文件的文件扩展名只能是可执行脚本文件,如
jsp/jspx
- url 可以是远程文件,如
http://example.com/test.jsp
但引入后会被当成纯文本,同时context属性要去除,否则会报错 - url 被限制只能引入web根目录及子目录下的文件,不能跳出web根目录
0x02: 路径规范化带来的小特性
在动态调试代码,寻找 jstl 标签的 url 的特性和解析原因的时候,偶然发现 url
参数会被 tomcat-coyote.jar!/org/apache/tomcat/util/http/RequestUtil.class
的 public static String normalize(String path, boolean replaceBackSlash)
函数进行规范化处理,完整代码如下:
public static String normalize(String path, boolean replaceBackSlash) {
if (path == null) {
return null;
} else {
String normalized = path;
if (replaceBackSlash && path.indexOf(92) >= 0) {
normalized = path.replace('\\', '/');
}
if (!normalized.startsWith("/")) {
normalized = "/" + normalized;
}
boolean addedTrailingSlash = false;
if (normalized.endsWith("/.") || normalized.endsWith("/..")) {
normalized = normalized + "/";
addedTrailingSlash = true;
}
while(true) {
int index = normalized.indexOf("//");
if (index < 0) {
while(true) {
index = normalized.indexOf("/./");
if (index < 0) {
while(true) {
index = normalized.indexOf("/../");
if (index < 0) {
if (normalized.length() > 1 && addedTrailingSlash) {
normalized = normalized.substring(0, normalized.length() - 1);
}
return normalized;
}
if (index == 0) {
return null;
}
int index2 = normalized.lastIndexOf(47, index - 1);
normalized = normalized.substring(0, index2) + normalized.substring(index + 3);
}
}
normalized = normalized.substring(0, index) + normalized.substring(index + 2);
}
}
normalized = normalized.substring(0, index) + normalized.substring(index + 1);
}
}
}
根据代码和测试发现,tomcat 规范化处理路径带来的关于路径处理方面的小特性:
- 所有四种方法中可以在路径后面添加一个至多个
/.
字符串,被规范化处理后不会对路径寻找产生影响; - 前三种方法可以在路径前面添加一个至多个
./
字符串,被规范化处理后不会对路径寻找产生影响;
对于第一种写法, include.png 文件内容如下:
<% out.print("this is include png"); %>
同目录下, test1.jsp 文件,内容如下:
<jsp:directive.include file="./././include.png/./."/>
浏览器直接访问 http://127.0.0.1/test1.jsp
,include.png
文件中的脚本代码会先被包含进脚本中,然后编译生成/work/Catalina/localhost/_/org/apache/jsp/test1_jsp.java
,执行后网页会输出 this is include png
字符串.
hi :) bross :)