mirror of
https://github.com/github/codeql.git
synced 2026-02-24 10:53:49 +01:00
99 lines
3.3 KiB
Plaintext
99 lines
3.3 KiB
Plaintext
/** Provides classes and predicates to reason about cleartext storage in Android's SharedPreferences. */
|
|
|
|
import java
|
|
import semmle.code.java.dataflow.DataFlow
|
|
import semmle.code.java.frameworks.android.SharedPreferences
|
|
import semmle.code.java.security.CleartextStorageQuery
|
|
private import semmle.code.java.dataflow.FlowSinks
|
|
private import semmle.code.java.dataflow.FlowSources
|
|
|
|
private class SharedPrefsCleartextStorageSink extends CleartextStorageSink {
|
|
SharedPrefsCleartextStorageSink() {
|
|
exists(MethodCall m |
|
|
m.getMethod() instanceof PutSharedPreferenceMethod and
|
|
this.asExpr() = m.getArgument(1)
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The call to get a `SharedPreferences.Editor` object, which can set shared preferences and be
|
|
* stored to the device.
|
|
*/
|
|
class SharedPreferencesEditorMethodCall extends Storable, MethodCall {
|
|
SharedPreferencesEditorMethodCall() {
|
|
this.getMethod() instanceof GetSharedPreferencesEditorMethod and
|
|
not DataFlow::localExprFlow(any(MethodCall ma |
|
|
ma.getMethod() instanceof CreateEncryptedSharedPreferencesMethod
|
|
), this.getQualifier())
|
|
}
|
|
|
|
/** Gets an input, for example `password` in `editor.putString("password", password);`. */
|
|
override Expr getAnInput() {
|
|
exists(DataFlow::Node editor |
|
|
sharedPreferencesInput(editor, result) and
|
|
SharedPreferencesFlow::flow(DataFlow::exprNode(this), editor)
|
|
)
|
|
}
|
|
|
|
/** Gets a store, for example `editor.commit();`. */
|
|
override Expr getAStore() {
|
|
exists(DataFlow::Node editor |
|
|
sharedPreferencesStore(editor, result) and
|
|
SharedPreferencesFlow::flow(DataFlow::exprNode(this), editor)
|
|
)
|
|
}
|
|
}
|
|
|
|
/** DEPRECATED: Alias for `SharedPreferencesEditorMethodCall`. */
|
|
deprecated class SharedPreferencesEditorMethodAccess = SharedPreferencesEditorMethodCall;
|
|
|
|
/**
|
|
* Holds if `input` is the second argument of a setter method
|
|
* called on `editor`, which is an instance of `SharedPreferences$Editor`.
|
|
*/
|
|
private predicate sharedPreferencesInput(DataFlow::Node editor, Expr input) {
|
|
exists(MethodCall m |
|
|
m.getMethod() instanceof PutSharedPreferenceMethod and
|
|
input = m.getArgument(1) and
|
|
editor.asExpr() = m.getQualifier().getUnderlyingExpr()
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if `m` is a store method called on `editor`,
|
|
* which is an instance of `SharedPreferences$Editor`.
|
|
*/
|
|
private predicate sharedPreferencesStore(DataFlow::Node editor, MethodCall m) {
|
|
m.getMethod() instanceof StoreSharedPreferenceMethod and
|
|
editor.asExpr() = m.getQualifier().getUnderlyingExpr()
|
|
}
|
|
|
|
/**
|
|
* A shared preferences editor method call source nodes.
|
|
*/
|
|
class SharedPreferencesEditorMethodCallSource extends ApiSourceNode {
|
|
SharedPreferencesEditorMethodCallSource() {
|
|
this.asExpr() instanceof SharedPreferencesEditorMethodCall
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A class of shared preferences sink nodes.
|
|
*/
|
|
class SharedPreferencesSink extends ApiSinkNode {
|
|
SharedPreferencesSink() {
|
|
sharedPreferencesInput(this, _) or
|
|
sharedPreferencesStore(this, _)
|
|
}
|
|
}
|
|
|
|
/** Flow from `SharedPreferences.Editor` to either a setter or a store method. */
|
|
private module SharedPreferencesFlowConfig implements DataFlow::ConfigSig {
|
|
predicate isSource(DataFlow::Node src) { src instanceof SharedPreferencesEditorMethodCallSource }
|
|
|
|
predicate isSink(DataFlow::Node sink) { sink instanceof SharedPreferencesSink }
|
|
}
|
|
|
|
private module SharedPreferencesFlow = DataFlow::Global<SharedPreferencesFlowConfig>;
|