Merge pull request #4453 from yoff/python-port-unsafe-deserialization

Python: port unsafe deserialization
This commit is contained in:
Rasmus Wriedt Larsen
2020-10-15 17:26:31 +02:00
committed by GitHub
18 changed files with 449 additions and 2 deletions

View File

@@ -0,0 +1,2 @@
import python
import experimental.meta.ConceptsTest

View File

@@ -0,0 +1,3 @@
import dill
dill.loads(payload) # $decodeInput=payload $decodeOutput=Attribute() $decodeFormat=dill $decodeMayExecuteInput

View File

@@ -0,0 +1,5 @@
import pickle
import marshal
pickle.loads(payload) # $decodeInput=payload $decodeOutput=Attribute() $decodeFormat=pickle $decodeMayExecuteInput
marshal.loads(payload) # $decodeInput=payload $decodeOutput=Attribute() $decodeFormat=marshal $decodeMayExecuteInput

View File

@@ -0,0 +1,2 @@
import python
import experimental.meta.ConceptsTest

View File

@@ -0,0 +1,6 @@
import yaml
from yaml import SafeLoader
yaml.load(payload) # $decodeInput=payload $decodeOutput=Attribute() $decodeFormat=YAML $decodeMayExecuteInput
yaml.load(payload, Loader=SafeLoader) # $decodeInput=payload $decodeOutput=Attribute() $decodeFormat=YAML
yaml.load(payload, Loader=yaml.BaseLoader) # $decodeInput=payload $decodeOutput=Attribute() $decodeFormat=YAML

View File

@@ -33,6 +33,46 @@ class SystemCommandExecutionTest extends InlineExpectationsTest {
}
}
class DecodingTest extends InlineExpectationsTest {
DecodingTest() { this = "DecodingTest" }
override string getARelevantTag() {
result in ["decodeInput", "decodeOutput", "decodeFormat", "decodeMayExecuteInput"]
}
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(Decoding d |
exists(DataFlow::Node data |
location = data.getLocation() and
element = data.toString() and
value = value_from_expr(data.asExpr()) and
(
data = d.getAnInput() and
tag = "decodeInput"
or
data = d.getOutput() and
tag = "decodeOutput"
)
)
or
exists(string format |
location = d.getLocation() and
element = format and
value = format and
format = d.getFormat() and
tag = "decodeFormat"
)
or
d.mayExecuteInput() and
location = d.getLocation() and
element = d.toString() and
value = "" and
tag = "decodeMayExecuteInput"
)
}
}
class CodeExecutionTest extends InlineExpectationsTest {
CodeExecutionTest() { this = "CodeExecutionTest" }

View File

@@ -0,0 +1,16 @@
edges
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload |
nodes
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
#select
| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | untrusted input |
| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | untrusted input |
| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | untrusted input |
| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | untrusted input |

View File

@@ -0,0 +1 @@
experimental/Security-new-dataflow/CWE-502/UnsafeDeserialization.ql

View File

@@ -0,0 +1,21 @@
import flask
import pickle
import yaml
import marshal
from yaml import SafeLoader
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def hello():
payload = request.args.get("payload")
pickle.loads(payload) # NOT OK
yaml.load(payload) # NOT OK
yaml.load(payload, Loader=SafeLoader) # OK
marshal.loads(payload) # NOT OK
import dill
dill.loads(payload) # NOT OK