[Java] - Limiting Flows Based on Patterns
- Lenguaje dominante
- CodeQL
- Estrellas
- 10.1k
- Forks
- 2.1k
- Merge medio
- 2 d 15 h
- PR fusionados (30 d)
- 141
Descripción
Hello, I am trying to restrict flows to only include those that have a source flow that is used as a query parameter.
For example, say authToken is a source,
```
String urlString = "http://auth.companyportal.com/auth?userId=" + userId + "&token=" + authToken;
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
```
However, my current query is picking up false positives where the source isn't used as a query parameter but somehow reaches the sink. Such as a dummy example like this
```
URL url = new URL(authToken);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
```
To address this I added a `isValidQueryParamFlow` predicate to my query that matches based on `".*\\?.*=.*"` however, this causes all of the expected detections to be removed. Even if I remove the regex, or relax the restrictions there still aren't any results. I know the rest of the query is operating as it should since I am getting the expected results without this check. So, I believe it is an issue with how I am performing this filtering.
Here is my full query
```
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
import SensitiveInfo.SensitiveInfo
import Barrier.Barrier
module Flow = TaintTracking::Global;
import Flow::PathGraph
/** A configuration for finding flows from sensitive information sources to URL constructions. */
module SensitiveInfoToUrlConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(SensitiveVariableExpr sve |
source.asExpr() = sve and
not sve.toString().toLowerCase().matches("%url%"))
}
predicate isSink(DataFlow::Node sink) {
// Direct use of URL with openConnection followed by setRequestMethod("GET")
exists(ConstructorCall urlConstructor, MethodCall openConnectionCall, MethodCall setRequestMethod |
urlConstructor.getConstructedType().hasQualifiedName("java.net", "URL") and
urlConstructor.getAnArgument() = sink.asExpr() and
openConnectionCall.getMethod().hasName("openConnection") and
openConnectionCall.getMethod().getDeclaringType().hasQualifiedName("java.net", "URL") and
DataFlow::localExprFlow(urlConstructor, openConnectionCall.getQualifier()) and
setRequestMethod.getMethod().hasName("setRequestMethod") and
((StringLiteral)setRequestMethod.getArgument(0)).getValue() = "GET" and
DataFlow::localExprFlow(openConnectionCall, setRequestMethod.getQualifier())
)
}
predicate isBarrier(DataFlow::Node node) {
Barrier::barrier(node)
}
}
predicate isValidQueryParamFlow(Flow::PathNode source, Flow::PathNode sink) {
exists(BinaryExpr be |
be.getOp() = "+" and
be.getLeftOperand().toString().matches(".*\\?.*=.*") and // Ensure there is a `=` after `?`
source.getNode().asExpr() = be.getRightOperand() and
sink.getNode().asExpr() = be
)
}
from Flow::PathNode source, Flow::PathNode sink
where Flow::flowPath(source, sink) and
isValidQueryParamFlow(source, sink)
select sink.getNode(), source, sink, "Sensitive information used in a URL constructed for a GET request."
```
Any help is appreciated, thank you,
Guía de contribución
Evaluación
Este issue todavía no se ha evaluado.