Model python_jwt.process_jwt

This commit is contained in:
jorgectf
2021-12-19 18:32:14 +01:00
parent 8fabbd697e
commit f82ed8573e
4 changed files with 72 additions and 0 deletions

View File

@@ -11,5 +11,6 @@ private import experimental.semmle.python.frameworks.NoSQL
private import experimental.semmle.python.frameworks.Log
private import experimental.semmle.python.frameworks.JWT
private import experimental.semmle.python.libraries.PyJWT
private import experimental.semmle.python.libraries.Python_JWT
private import experimental.semmle.python.libraries.Authlib
private import experimental.semmle.python.libraries.PythonJose

View File

@@ -0,0 +1,56 @@
private import python
private import experimental.semmle.python.Concepts
private import semmle.python.ApiGraphs
private module Python_JWT {
/**
* Gets a call to `python_jwt.process_jwt`.
*
* Given the following example:
*
* ```py
* python_jwt.process_jwt(token)
* python_jwt.verify_jwt(token, "key", "HS256")
* ```
*
* * `this` would be `jwt.process_jwt(token)`.
* * `getPayload()`'s result would be `token`.
* * `getKey()`'s result would be `"key"`.
* * `getAlgorithm()`'s result would be `"HS256"`.
* * `getAlgorithmstring()`'s result would be `HS256`.
* * `getOptions()`'s result would be `none()`.
* * `verifiesSignature()` predicate would succeed.
*/
private class Python_JWTProcessCall extends DataFlow::CallCfgNode, JWTDecoding::Range {
DataFlow::CallCfgNode verifyCall;
boolean verifiesSignature;
Python_JWTProcessCall() {
this = API::moduleImport("python_jwt").getMember("process_jwt").getACall() and
(
verifyCall = API::moduleImport("python_jwt").getMember("verify_jwt").getACall() and
this.getArg(0).getALocalSource().flowsTo(verifyCall.getArg(0)) and
verifiesSignature = true
or
verifiesSignature = false
)
}
override DataFlow::Node getPayload() { result = this.getArg(0) }
override DataFlow::Node getKey() { result = verifyCall.getArg(1) }
override DataFlow::Node getAlgorithm() { result = verifyCall.getArg(2) }
override string getAlgorithmString() {
exists(StrConst str |
DataFlow::exprNode(str).(DataFlow::LocalSourceNode).flowsTo(this.getAlgorithm()) and
result = str.getText()
)
}
override DataFlow::Node getOptions() { none() }
override predicate verifiesSignature() { exists( | verifiesSignature = true) }
}
}

View File

@@ -1,3 +1,4 @@
| pyjwt.py:22:12:22:16 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
| pyjwt.py:23:12:23:16 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
| python_jose.py:19:12:19:16 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
| python_jwt.py:14:24:14:29 | ControlFlowNode for token3 | is not verified with a cryptographic secret or public key. |

View File

@@ -0,0 +1,14 @@
import python_jwt
# GOOD
token1 = "1"
python_jwt.process_jwt(token1)
python_jwt.verify_jwt(token1, "key", "HS256")
# BAD
# no call to verify_jwt
token3 = "123"
python_jwt.process_jwt(token3)