Drools

Drools is a business-rules engine. Rules are written in DRL (Drools Rule Language), where each rule has a left-hand side of conditions over the working-memory facts and a right-hand side consequence that runs when the rule fires. The expressions in conditions, and the code in consequences, are evaluated by a dialect, and Drools' default expression dialect is MVEL. MVEL is a full JVM expression language with object construction, method invocation, and reflection, so the injection vector here is MVEL under Drools: anything that builds DRL text or an MVEL expression from untrusted input runs attacker MVEL, and MVEL reaches the runtime.

Vulnerable pattern#

The exposure appears wherever rule text is assembled dynamically rather than loaded from fixed resources, for example building DRL from a user-supplied condition or threshold and compiling it:

java
String drl =
  "rule \"dynamic\"\n" +
  "when\n" +
  "  $o : Order( " + userCondition + " )\n" +
  "then\n" +
  "  " + userAction + "\n" +
  "end";
// drl compiled into a KieBase and fired

Both the woven condition and the consequence are MVEL. Applications that let users author rules, or that pass user input into an MVEL eval or a decision-table cell, expose the same dialect.

Reaching the runtime#

MVEL resolves class names and calls methods, so a consequence (or an injected MVEL expression) obtains the runtime and executes a command:

code
Runtime.getRuntime().exec("id");

MVEL also supports explicit construction, so ProcessBuilder works directly:

code
new java.lang.ProcessBuilder("id").start();

To capture output, wrap the process stream in the consequence, constructing a java.util.Scanner over getInputStream() and reading a token, then bind it back to a fact field or an inserted object that the application later reads.

Shell features need an argument vector#

Runtime.exec(String) tokenizes on whitespace and runs with no shell, so $(...), pipes, and redirection stay literal. For shell behavior build the argument vector and let bash interpret it:

code
new java.lang.ProcessBuilder(new String[]{"/bin/bash","-c","id > /tmp/o 2>&1"}).start();

On Windows use new String[]{"cmd.exe","/c","whoami"}. If the application pinned the dialect to java instead of mvel, the consequence is compiled Java rather than MVEL but reaches the same Runtime/ProcessBuilder API, so the command sink is unchanged.

References#

Cookie Consent

We use cookies to enhance your experience. Learn more