Skip to content

Commit a29ccd6

Browse files
committed
Initial commit
1 parent 931c0e9 commit a29ccd6

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p> The ScriptEngine api is available since the release of Java 6.
8+
It allows application to interact with script written in language such as JavaScript.</p>
9+
</overview>
10+
11+
<recommendation>
12+
Use "Cloudbees Rhino Sandbox" or sandboxing with SecurityManager or use <a href="https://www.graalvm.org/">graalvm</a> instead
13+
</recommendation>
14+
15+
<example>
16+
The following code could executes random JavaScript code
17+
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
18+
ScriptEngine scriptEngine = scriptEngineManager.getEngineByExtension("js");
19+
Object result = scriptEngine.eval(code);
20+
</example>
21+
22+
<references>
23+
<li>
24+
CERT coding standard: <a href="https://wiki.sei.cmu.edu/confluence/display/java/IDS52-J.+Prevent+code+injection">ScriptEngine code injection</a>
25+
</li>
26+
</references>
27+
</qhelp>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* @name Script engine eval
3+
* @description Malicious javascript code could caused arbitrary command execution on OS level
4+
* @kind path-problem
5+
* @problem.severity error
6+
* @precision high
7+
* @id java/unsafe-eval
8+
* @tags security
9+
* external/cwe/cwe-094
10+
*/
11+
12+
import java
13+
import semmle.code.java.dataflow.FlowSources
14+
import DataFlow::PathGraph
15+
16+
class ScriptEngineMethod extends Method {
17+
ScriptEngineMethod() {
18+
this.getDeclaringType().hasQualifiedName("javax.script", "ScriptEngine") and
19+
this.hasName("eval")
20+
}
21+
}
22+
23+
predicate scriptEngine(MethodAccess ma, Expr sink) {
24+
exists(Method m | m = ma.getMethod() |
25+
m instanceof ScriptEngineMethod and
26+
sink = ma.getArgument(0)
27+
)
28+
}
29+
30+
class ScriptEngineSink extends DataFlow::ExprNode {
31+
ScriptEngineSink() { scriptEngine(_, this.getExpr()) }
32+
33+
MethodAccess getMethodAccess() { scriptEngine(result, this.getExpr()) }
34+
}
35+
36+
class ScriptEngineConfiguration extends TaintTracking::Configuration {
37+
ScriptEngineConfiguration() { this = "ScriptEngineConfiguration" }
38+
39+
override predicate isSource(DataFlow::Node source) {
40+
source instanceof RemoteFlowSource
41+
or
42+
source instanceof LocalUserInput
43+
}
44+
45+
override predicate isSink(DataFlow::Node sink) { sink instanceof ScriptEngineSink }
46+
}
47+
48+
from DataFlow::PathNode source, DataFlow::PathNode sink, ScriptEngineConfiguration conf
49+
where conf.hasFlowPath(source, sink)
50+
select sink.getNode().(ScriptEngineSink).getMethodAccess(), source, sink, "Script engine eval $@.",
51+
source.getNode(), "user input"

0 commit comments

Comments
 (0)