Java: Checking if map has specific key #160
-
Hello everyone I just got started using CodeQL and currently try to write a query for the following case: Here my bloody beginner attempt:
The local data flow seems to work, however I'm stuck when it comes to do the actual check if the key is set. Is this the right approach or do I need to implement this as a guard? Thank you for your help! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Please ignore this answer, it does not really work. For the next time (not specific to you but in general, when I'm seeing such questions here) it would be great if you could include a sample project that is accessible on lgtm.com. Here is a (untested!) query that should work. /**
* @kind path-problem
* @id foo
*/
import java
import semmle.code.java.Maps
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.DataFlow2
import DataFlow::PathGraph
predicate hasForceAuthentication(Expr e) {
exists(ForceAuthenticationKeyConfig conf | conf.hasFlow(_, DataFlow2::exprNode(e)))
}
class ForceAuthenticationKeyConfig extends DataFlow2::Configuration {
ForceAuthenticationKeyConfig() { this = "ForceAuthenticationKeyConfig" }
override predicate isSource(DataFlow2::Node src) {
src.asExpr().(CompileTimeConstantExpr).getStringValue() = "forceAuthentication"
}
override predicate isSink(DataFlow2::Node srce) { any() }
}
class MapWitForceAuthentication extends Expr {
MapWitForceAuthentication() {
exists(MapPutCall put | hasForceAuthentication(put.getKey()) |
put.getQualifier() = this and
put.getMethod().(MapMethod).getReceiverKeyType().getName() = "String" and
put.getMethod().(MapMethod).getReceiverValueType().getName() = "Object"
)
}
}
class UncheckedMapToSensitiveFunctionConfig extends DataFlow::Configuration {
UncheckedMapToSensitiveFunctionConfig() { this = "UncheckedMapToSensitiveFunctionConfig" }
override predicate isSource(DataFlow::Node src) { src.asExpr().getType() instanceof MapType }
override predicate isSink(DataFlow::Node sink) {
exists(SettingsFactoryMethodAccess ma | ma.getAnArgument() = sink.asExpr())
}
override predicate isBarrier(DataFlow::Node barrier) {
exists(MapWitForceAuthentication map | map = barrier.asExpr())
}
}
class SettingsFactoryMethodAccess extends MethodAccess {
SettingsFactoryMethodAccess() {
getCallee().getDeclaringType().getName() = "SettingsFactory" and
getCallee().getDeclaringType().getPackage().getName() = "my.little.library" and
getMethod().getName() = "newSettings"
}
}
from UncheckedMapToSensitiveFunctionConfig conf, DataFlow::PathNode src, DataFlow::PathNode sink
where conf.hasFlowPath(src, sink)
select sink, src, sink, "Oh no" |
Beta Was this translation helpful? Give feedback.
Please ignore this answer, it does not really work.
Instead look at this improved answer: #235 (comment)
For the next time (not specific to you but in general, when I'm seeing such questions here) it would be great if you could include a sample project that is accessible on lgtm.com.
Otherwise no one can easily test your query.
Here is a (untested!) query that should work.
It looks for flow from any
Map
to your sensitive function.If there is a call that puts something into
forceAuthentication
we consider the flow safe.Note that this is not 100% correct since it would be possible that someone clears the map afterwards.
We would still consider this safe