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-*.jartaglibs-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.classpublic 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 规范化处理路径带来的关于路径处理方面的小特性:

  1. 所有四种方法中可以在路径后面添加一个至多个 /. 字符串,被规范化处理后不会对路径寻找产生影响;
  2. 前三种方法可以在路径前面添加一个至多个 ./ 字符串,被规范化处理后不会对路径寻找产生影响;

对于第一种写法, include.png 文件内容如下:

<% out.print("this is include png"); %>

同目录下, test1.jsp 文件,内容如下:

<jsp:directive.include file="./././include.png/./."/>

浏览器直接访问 http://127.0.0.1/test1.jspinclude.png 文件中的脚本代码会先被包含进脚本中,然后编译生成/work/Catalina/localhost/_/org/apache/jsp/test1_jsp.java,执行后网页会输出 this is include png 字符串.

标签   

1 评论

  1. rardPurce
    /回复

    hi :) bross :)

评论