mirror of
https://github.com/github/codeql.git
synced 2026-03-04 14:46:48 +01:00
This query shares implementation with several other queries about cleartext storage, but it's the only one of them that's in the code-scanning suite. The sharing mechanism remains the same as before, but now each query has to override `getASelectedLocation` to become diff-informed. Two other data-flow configurations are used in this query, but they can't easily be made diff-informed.
74 lines
2.2 KiB
Plaintext
74 lines
2.2 KiB
Plaintext
/** Provides classes and predicates to reason about cleartext storage in cookies. */
|
|
|
|
import java
|
|
import semmle.code.java.dataflow.DataFlow
|
|
import semmle.code.java.security.CleartextStorageQuery
|
|
private import semmle.code.java.dataflow.FlowSinks
|
|
private import semmle.code.java.dataflow.FlowSources
|
|
|
|
private class CookieCleartextStorageSink extends CleartextStorageSink {
|
|
Cookie cookie;
|
|
|
|
CookieCleartextStorageSink() { this.asExpr() = cookieInput(cookie) }
|
|
|
|
override Location getASelectedLocation() {
|
|
result = this.getLocation()
|
|
or
|
|
result = cookie.getLocation()
|
|
or
|
|
result = cookie.getAStore().getLocation()
|
|
}
|
|
}
|
|
|
|
/** The instantiation of a cookie, which can act as storage. */
|
|
class Cookie extends Storable, ClassInstanceExpr {
|
|
Cookie() {
|
|
this.getConstructor().getDeclaringType().hasQualifiedName("javax.servlet.http", "Cookie")
|
|
}
|
|
|
|
/** Gets an input, for example `input` in `new Cookie("...", input);`. */
|
|
override Expr getAnInput() { result = cookieInput(this) }
|
|
|
|
/** Gets a store, for example `response.addCookie(cookie);`. */
|
|
override Expr getAStore() {
|
|
exists(DataFlow::Node n |
|
|
cookieStore(n, result) and
|
|
CookieToStoreFlow::flow(DataFlow::exprNode(this), n)
|
|
)
|
|
}
|
|
}
|
|
|
|
private predicate cookieStore(DataFlow::Node cookie, Expr store) {
|
|
exists(MethodCall m, Method def |
|
|
m.getMethod() = def and
|
|
def.getName() = "addCookie" and
|
|
def.getDeclaringType().hasQualifiedName("javax.servlet.http", "HttpServletResponse") and
|
|
store = m and
|
|
cookie.asExpr() = m.getAnArgument()
|
|
)
|
|
}
|
|
|
|
/**
|
|
* A cookie source node.
|
|
*/
|
|
private class CookieSource extends ApiSourceNode {
|
|
CookieSource() { this.asExpr() instanceof Cookie }
|
|
}
|
|
|
|
/**
|
|
* A cookie store sink node.
|
|
*/
|
|
private class CookieStoreSink extends ApiSinkNode {
|
|
CookieStoreSink() { cookieStore(this, _) }
|
|
}
|
|
|
|
private module CookieToStoreFlowConfig implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node src) { src instanceof CookieSource }
|
|
|
|
predicate isSink(DataFlow::Node sink) { sink instanceof CookieStoreSink }
|
|
}
|
|
|
|
private module CookieToStoreFlow = DataFlow::Global<CookieToStoreFlowConfig>;
|
|
|
|
private Expr cookieInput(Cookie c) { result = c.getArgument(1) }
|