项目下载地址
spider-flow: 新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。https://gitee.com/ssssssss-team/spider-flow
在平台spiderflow的页面中有一个自定义函数,看到函数应是非常的敏感了。
?
可以做一些猜想与尝试,定义的函数在什么时候可以调用?让定义的脚本执行系统命令?基于java的机制写一段静态代码段尝试一下!?
然而这些尝试都没有达到预期目的,现在我们尝试进入后端代码,调试调试看一看底层的调用机制。
输入一些参数开始进行抓包,抓包的目的是想看它调用了谁的接口
很明显,我们重点找/function/save
springboot项目 我们重点关注Controller的名称 注解RequestMapping 以寻求调用的方法
好的,我们成功找到了,接口的入口,而且注意到输入的数据都在function里
?
打上断点开始进入调式
追进savaFunction
继续追进validScript,注意参数的传递,
看看参数变成什么样了 ,concatScript函数把我们怎么处理了,直接看看它把参数处理的结果
?
它最终把输入的参数变成了字符串,而且可以确定的是ming can xxxx 这三个位置是我们可控的,且之前没有什么相关的参数过滤(这里先不考虑过滤器什么的机制 先这样认为)
再追进
停..... 这里我就要喊停了,因为再调就跳出三界之外了!这之前都是项目文件包中的代码逻辑,而这段eval 是jdk的。所以要停 即使我们不知道那个engine也要有这样的意识。作为一名代码审计员 任重而道远 要分析中重点的内容.....
重点分析这个eval 调用的时候是否有漏洞。 别忘了执行条命令的时候有些参数我们可以控制的。
我们把这个包名与这段代码,丢给GPT 看看它给我们的示例!
jdk.nashorn.api.scripting
是Java 8中引入的一个包,它提供了与Nashorn JavaScript引擎交互的API。Nashorn是Java 8中默认的JavaScript引擎,为Java开发人员提供了在Java虚拟机上运行JavaScript代码的能力。
jdk.nashorn.api.scripting
包中的类和接口提供了一系列方法,可以在Java和JavaScript之间进行数据交换、函数调用和脚本执行等操作。以下是一些常用的类和接口:
ScriptEngineManager
:用于获取和管理不同脚本引擎的工厂类。
ScriptEngine
:表示一个脚本引擎,可以在其中执行JavaScript脚本。
Bindings
:一个键-值集合,用于在Java和JavaScript之间传递数据。
Invocable
:表示一个可调用的JavaScript对象,可以在其中调用JavaScript函数。
ScriptContext
:表示一个JavaScript脚本的执行环境,包括全局变量、输出流和错误流等。使用这些类和接口,可以编写Java代码来执行JavaScript脚本、调用JavaScript函数、获取JavaScript对象等等,实现Java和JavaScript之间的无缝交互。
需要注意的是,虽然Nashorn是Java 8中默认的JavaScript引擎,但在Java 11中已经被弃用,建议使用其他JavaScript引擎库来代替。
?随后可以要求GPT给出示例代码
以下是一个使用
jdk.nashorn.api.scripting
包的简单示例,展示了如何在Java中执行JavaScript脚本和调用JavaScript函数:
javaCopy Codeimport javax.script.*;
?
public class NashornExample {
? public static void main(String[] args) throws ScriptException, NoSuchMethodException {
? ? ? // 创建一个ScriptEngineManager对象
? ? ? ScriptEngineManager manager = new ScriptEngineManager();
? ? ? ?
? ? ? // 获取Nashorn脚本引擎
? ? ? ScriptEngine engine = manager.getEngineByName("nashorn");
? ? ? ?
? ? ? // 定义JavaScript脚本
? ? ? String script = "function greet(name) { return 'Hello, ' + name; }";
? ? ? ?
? ? ? // 执行JavaScript脚本
? ? ? engine.eval(script);
? ? ? ?
? ? ? // 调用JavaScript函数
? ? ? Invocable invocable = (Invocable) engine;
? ? ? String result = (String) invocable.invokeFunction("greet", "John");
? ? ? ?
? ? ? System.out.println(result); // 输出:Hello, John
? }
}
在上述示例中,我们首先创建一个
ScriptEngineManager
对象,然后通过它获取一个Nashorn脚本引擎。接下来,我们定义了一个JavaScript脚本,其中包含一个名为greet
的函数,该函数接受一个参数并返回一个拼接的字符串。然后,我们使用
engine.eval(script)
方法执行JavaScript脚本。这将使脚本中的函数在脚本引擎中可用。最后,我们使用
Invocable
接口将脚本引擎转换为可调用对象,并使用invokeFunction
方法调用JavaScript函数。在这个例子中,我们调用greet
函数并传递一个参数"John",并将返回的结果保存在一个字符串变量中。最后,我们输出结果,将会打印出"Hello, John"。
请注意,在实际应用中,还需要处理异常情况和错误处理,以确保脚本的安全性和稳定性。同时,由于Nashorn已经被弃用,建议使用其他更先进的JavaScript引擎库,如GraalVM的JavaScript引擎。
这段脚本的确可以执行,不过可不是在这行代码engine.eval(script);中执行,而是在随后的反射调用中执行。
上网查查engine.eval 能否直接执行系统函数
看看网上结果不少,似乎思路是可行的。点开第一个
先在本地测试一下,没问题可以弹出计算机。
把这段代码到spider项目中 测试一下 。中间出了小插曲,这里报错了
看到报错有一个},立马意识到 我们在构造这个payload的时候,里面有一个{ 和前面闭合了 所以之后的} 也要闭合。
仔细一点,即使没有有报错信息我们也可以分析出,这也给代码审计人员提了个醒,payload测试不要急躁。
修正后的代码(在后面加{就行了)
保存, 成功弹出计算机
附赠poc
POST /function/save HTTP/1.1
Host: 127.0.0.1:8088
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
id=446b686c047b28bc30583782ea9088aa&name=test¶meter=can&script=return+java.lang.%2F****%2FRuntime%7D%3Br%3Dtest()%3Br.getRuntime().exec(%22calc%22)%3B%7B
?