-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16771 from porcupineyhairs/js2py
Python : Arbitrary code execution due to Js2Py
- Loading branch information
Showing
7 changed files
with
93 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<!DOCTYPE qhelp SYSTEM "qhelp.dtd"> | ||
<qhelp> | ||
<overview> | ||
<p> | ||
Passing untrusted inputs to a JavaScript interpreter like `Js2Py` can lead to arbitrary | ||
code execution. | ||
</p> | ||
</overview> | ||
<recommendation> | ||
<p> This vulnerability can be prevented either by preventing an untrusted user input to flow | ||
to an <code>eval_js</code> call. Or, the impact of this vulnerability can be | ||
significantly reduced by disabling imports from the interepreted code (note that in a <a | ||
href="https://github.com/PiotrDabkowski/Js2Py/issues/45#issuecomment-258724406"> | ||
comment</a> the author of the library highlights that Js2Py is still insecure with this | ||
option).</p> | ||
</recommendation> | ||
<example> | ||
<p>In the example below, the Javascript code being evaluated is controlled by the user and | ||
hence leads to arbitrary code execution.</p> | ||
<sample src="Js2pyBad.py" /> | ||
<p>This can be fixed by disabling imports before evaluating the user passed buffer.</p> | ||
<sample src="Js2pyGood.py" /> | ||
</example> | ||
</qhelp> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* @name JavaScript code execution. | ||
* @description Passing user supplied arguments to a Javascript to Python translation engine such as Js2Py can lead to remote code execution. | ||
* @problem.severity error | ||
* @security-severity 9.3 | ||
* @precision high | ||
* @kind path-problem | ||
* @id py/js2py-rce | ||
* @tags security | ||
* experimental | ||
* external/cwe/cwe-94 | ||
*/ | ||
|
||
import python | ||
import semmle.python.ApiGraphs | ||
import semmle.python.dataflow.new.TaintTracking | ||
import semmle.python.dataflow.new.RemoteFlowSources | ||
import semmle.python.Concepts | ||
|
||
module Js2PyFlowConfig implements DataFlow::ConfigSig { | ||
predicate isSource(DataFlow::Node node) { node instanceof RemoteFlowSource } | ||
|
||
predicate isSink(DataFlow::Node node) { | ||
API::moduleImport("js2py").getMember(["eval_js", "eval_js6", "EvalJs"]).getACall().getArg(_) = | ||
node | ||
} | ||
} | ||
|
||
module Js2PyFlow = TaintTracking::Global<Js2PyFlowConfig>; | ||
|
||
import Js2PyFlow::PathGraph | ||
|
||
from Js2PyFlow::PathNode source, Js2PyFlow::PathNode sink | ||
where | ||
Js2PyFlow::flowPath(source, sink) and | ||
not exists(API::moduleImport("js2py").getMember("disable_pyimport").getACall()) | ||
select sink, source, sink, "This input to Js2Py depends on a $@.", source.getNode(), | ||
"user-provided value" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
@bp.route("/bad") | ||
def bad(): | ||
jk = flask.request.form["jk"] | ||
jk = eval_js(f"{jk} f()") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
@bp.route("/good") | ||
def good(): | ||
# disable python imports to prevent execution of malicious code | ||
js2py.disable_pyimport() | ||
jk = flask.request.form["jk"] | ||
jk = eval_js(f"{jk} f()") |
10 changes: 10 additions & 0 deletions
10
python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.expected
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
edges | ||
| Js2PyTest.py:9:5:9:6 | ControlFlowNode for jk | Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | provenance | | | ||
| Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | Js2PyTest.py:9:5:9:6 | ControlFlowNode for jk | provenance | AdditionalTaintStep | | ||
nodes | ||
| Js2PyTest.py:9:5:9:6 | ControlFlowNode for jk | semmle.label | ControlFlowNode for jk | | ||
| Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | ||
| Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring | | ||
subpaths | ||
#select | ||
| Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | Js2PyTest.py:10:18:10:28 | ControlFlowNode for Fstring | This input to Js2Py depends on a $@. | Js2PyTest.py:9:10:9:22 | ControlFlowNode for Attribute | user-provided value | |
1 change: 1 addition & 0 deletions
1
python/ql/test/experimental/query-tests/Security/CWE-094/Js2Py.qlref
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
experimental/Security/CWE-094/Js2Py.ql |
10 changes: 10 additions & 0 deletions
10
python/ql/test/experimental/query-tests/Security/CWE-094/Js2PyTest.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
|
||
import flask | ||
from js2py import eval_js, disable_pyimport | ||
|
||
bp = flask.Blueprint("app", __name__, url_prefix="/") | ||
|
||
@bp.route("/bad") | ||
def bad(): | ||
jk = flask.request.form["jk"] | ||
jk = eval_js(f"{jk} f()") |