Refactor CleartextStorage libraries

This commit is contained in:
Ed Minnix
2023-03-19 23:24:35 -04:00
parent b4130e650d
commit aa7934161a
7 changed files with 71 additions and 77 deletions

View File

@@ -29,16 +29,16 @@ class LocalDatabaseOpenMethodAccess extends Storable, Call {
} }
override Expr getAnInput() { override Expr getAnInput() {
exists(LocalDatabaseFlowConfig config, DataFlow::Node database | exists(DataFlow::Node database |
localDatabaseInput(database, result) and localDatabaseInput(database, result) and
config.hasFlow(DataFlow::exprNode(this), database) LocalDatabaseFlow::flow(DataFlow::exprNode(this), database)
) )
} }
override Expr getAStore() { override Expr getAStore() {
exists(LocalDatabaseFlowConfig config, DataFlow::Node database | exists(DataFlow::Node database |
localDatabaseStore(database, result) and localDatabaseStore(database, result) and
config.hasFlow(DataFlow::exprNode(this), database) LocalDatabaseFlow::flow(DataFlow::exprNode(this), database)
) )
} }
} }
@@ -93,19 +93,17 @@ private predicate localDatabaseStore(DataFlow::Node database, MethodAccess store
) )
} }
private class LocalDatabaseFlowConfig extends DataFlow::Configuration { private module LocalDatabaseFlowConfig implements DataFlow::ConfigSig {
LocalDatabaseFlowConfig() { this = "LocalDatabaseFlowConfig" } predicate isSource(DataFlow::Node source) {
override predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof LocalDatabaseOpenMethodAccess source.asExpr() instanceof LocalDatabaseOpenMethodAccess
} }
override predicate isSink(DataFlow::Node sink) { predicate isSink(DataFlow::Node sink) {
localDatabaseInput(sink, _) or localDatabaseInput(sink, _) or
localDatabaseStore(sink, _) localDatabaseStore(sink, _)
} }
override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
// Adds a step for tracking databases through field flow, that is, a database is opened and // Adds a step for tracking databases through field flow, that is, a database is opened and
// assigned to a field, and then an input or store method is called on that field elsewhere. // assigned to a field, and then an input or store method is called on that field elsewhere.
exists(Field f | exists(Field f |
@@ -115,3 +113,5 @@ private class LocalDatabaseFlowConfig extends DataFlow::Configuration {
) )
} }
} }
private module LocalDatabaseFlow = DataFlow::Global<LocalDatabaseFlowConfig>;

View File

@@ -24,16 +24,16 @@ class LocalFileOpenCall extends Storable {
} }
override Expr getAnInput() { override Expr getAnInput() {
exists(FilesystemFlowConfig conf, DataFlow::Node n | exists(DataFlow::Node n |
filesystemInput(n, result) and filesystemInput(n, result) and
conf.hasFlow(DataFlow::exprNode(this), n) FilesystemFlow::flow(DataFlow::exprNode(this), n)
) )
} }
override Expr getAStore() { override Expr getAStore() {
exists(FilesystemFlowConfig conf, DataFlow::Node n | exists(DataFlow::Node n |
closesFile(n, result) and closesFile(n, result) and
conf.hasFlow(DataFlow::exprNode(this), n) FilesystemFlow::flow(DataFlow::exprNode(this), n)
) )
} }
} }
@@ -79,17 +79,15 @@ private class CloseFileMethod extends Method {
} }
} }
private class FilesystemFlowConfig extends DataFlow::Configuration { private module FilesystemFlowConfig implements DataFlow::ConfigSig {
FilesystemFlowConfig() { this = "FilesystemFlowConfig" } predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LocalFileOpenCall }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LocalFileOpenCall } predicate isSink(DataFlow::Node sink) {
override predicate isSink(DataFlow::Node sink) {
filesystemInput(sink, _) or filesystemInput(sink, _) or
closesFile(sink, _) closesFile(sink, _)
} }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
// Add nested Writer constructors as extra data flow steps // Add nested Writer constructors as extra data flow steps
exists(ClassInstanceExpr cie | exists(ClassInstanceExpr cie |
cie.getConstructedType().getAnAncestor().hasQualifiedName("java.io", "Writer") and cie.getConstructedType().getAnAncestor().hasQualifiedName("java.io", "Writer") and
@@ -98,3 +96,5 @@ private class FilesystemFlowConfig extends DataFlow::Configuration {
) )
} }
} }
private module FilesystemFlow = DataFlow::Global<FilesystemFlowConfig>;

View File

@@ -14,8 +14,8 @@ private class ClassCleartextStorageSink extends CleartextStorageSink {
abstract class ClassStore extends Storable, ClassInstanceExpr { abstract class ClassStore extends Storable, ClassInstanceExpr {
/** Gets an input, for example `input` in `instance.password = input`. */ /** Gets an input, for example `input` in `instance.password = input`. */
override Expr getAnInput() { override Expr getAnInput() {
exists(ClassStoreFlowConfig conf, DataFlow::Node instance | exists(DataFlow::Node instance |
conf.hasFlow(DataFlow::exprNode(this), instance) and ClassStoreFlow::flow(DataFlow::exprNode(this), instance) and
result = getInstanceInput(instance, this.getConstructor().getDeclaringType()) result = getInstanceInput(instance, this.getConstructor().getDeclaringType())
) )
} }
@@ -40,9 +40,9 @@ private class Serializable extends ClassStore {
/** Gets a store, for example `outputStream.writeObject(instance)`. */ /** Gets a store, for example `outputStream.writeObject(instance)`. */
override Expr getAStore() { override Expr getAStore() {
exists(ClassStoreFlowConfig conf, DataFlow::Node n | exists(DataFlow::Node n |
serializableStore(n, result) and serializableStore(n, result) and
conf.hasFlow(DataFlow::exprNode(this), n) ClassStoreFlow::flow(DataFlow::exprNode(this), n)
) )
} }
} }
@@ -53,9 +53,9 @@ private class Marshallable extends ClassStore {
/** Gets a store, for example `marshaller.marshal(instance)`. */ /** Gets a store, for example `marshaller.marshal(instance)`. */
override Expr getAStore() { override Expr getAStore() {
exists(ClassStoreFlowConfig conf, DataFlow::Node n | exists(DataFlow::Node n |
marshallableStore(n, result) and marshallableStore(n, result) and
conf.hasFlow(DataFlow::exprNode(this), n) ClassStoreFlow::flow(DataFlow::exprNode(this), n)
) )
} }
} }
@@ -73,20 +73,20 @@ private Expr getInstanceInput(DataFlow::Node instance, RefType t) {
) )
} }
private class ClassStoreFlowConfig extends DataFlow::Configuration { private module ClassStoreFlowConfig implements DataFlow::ConfigSig {
ClassStoreFlowConfig() { this = "ClassStoreFlowConfig" } predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ClassStore }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ClassStore } predicate isSink(DataFlow::Node sink) {
override predicate isSink(DataFlow::Node sink) {
exists(getInstanceInput(sink, _)) or exists(getInstanceInput(sink, _)) or
serializableStore(sink, _) or serializableStore(sink, _) or
marshallableStore(sink, _) marshallableStore(sink, _)
} }
override int fieldFlowBranchLimit() { result = 1 } int fieldFlowBranchLimit() { result = 1 }
} }
private module ClassStoreFlow = DataFlow::Global<ClassStoreFlowConfig>;
private predicate serializableStore(DataFlow::Node instance, Expr store) { private predicate serializableStore(DataFlow::Node instance, Expr store) {
exists(MethodAccess m | exists(MethodAccess m |
store = m and store = m and

View File

@@ -20,9 +20,9 @@ class Cookie extends Storable, ClassInstanceExpr {
/** Gets a store, for example `response.addCookie(cookie);`. */ /** Gets a store, for example `response.addCookie(cookie);`. */
override Expr getAStore() { override Expr getAStore() {
exists(CookieToStoreFlowConfig conf, DataFlow::Node n | exists(DataFlow::Node n |
cookieStore(n, result) and cookieStore(n, result) and
conf.hasFlow(DataFlow::exprNode(this), n) CookieToStoreFlow::flow(DataFlow::exprNode(this), n)
) )
} }
} }
@@ -37,12 +37,12 @@ private predicate cookieStore(DataFlow::Node cookie, Expr store) {
) )
} }
private class CookieToStoreFlowConfig extends DataFlow3::Configuration { private module CookieToStoreFlowConfig implements DataFlow::ConfigSig {
CookieToStoreFlowConfig() { this = "CookieToStoreFlowConfig" } predicate isSource(DataFlow::Node src) { src.asExpr() instanceof Cookie }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof Cookie } predicate isSink(DataFlow::Node sink) { cookieStore(sink, _) }
override predicate isSink(DataFlow::Node sink) { cookieStore(sink, _) }
} }
private module CookieToStoreFlow = DataFlow::Global<CookieToStoreFlowConfig>;
private Expr cookieInput(Cookie c) { result = c.getArgument(1) } private Expr cookieInput(Cookie c) { result = c.getArgument(1) }

View File

@@ -19,17 +19,17 @@ class Properties extends Storable, ClassInstanceExpr {
/** Gets an input, for example `input` in `props.setProperty("password", input);`. */ /** Gets an input, for example `input` in `props.setProperty("password", input);`. */
override Expr getAnInput() { override Expr getAnInput() {
exists(PropertiesFlowConfig conf, DataFlow::Node n | exists(DataFlow::Node n |
propertiesInput(n, result) and propertiesInput(n, result) and
conf.hasFlow(DataFlow::exprNode(this), n) PropertiesFlow::flow(DataFlow::exprNode(this), n)
) )
} }
/** Gets a store, for example `props.store(outputStream, "...")`. */ /** Gets a store, for example `props.store(outputStream, "...")`. */
override Expr getAStore() { override Expr getAStore() {
exists(PropertiesFlowConfig conf, DataFlow::Node n | exists(DataFlow::Node n |
propertiesStore(n, result) and propertiesStore(n, result) and
conf.hasFlow(DataFlow::exprNode(this), n) PropertiesFlow::flow(DataFlow::exprNode(this), n)
) )
} }
} }
@@ -50,13 +50,13 @@ private predicate propertiesStore(DataFlow::Node prop, Expr store) {
) )
} }
private class PropertiesFlowConfig extends DataFlow::Configuration { private module PropertiesFlowConfig implements DataFlow::ConfigSig {
PropertiesFlowConfig() { this = "PropertiesFlowConfig" } predicate isSource(DataFlow::Node src) { src.asExpr() instanceof Properties }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof Properties } predicate isSink(DataFlow::Node sink) {
override predicate isSink(DataFlow::Node sink) {
propertiesInput(sink, _) or propertiesInput(sink, _) or
propertiesStore(sink, _) propertiesStore(sink, _)
} }
} }
private module PropertiesFlow = DataFlow::Global<PropertiesFlowConfig>;

View File

@@ -21,9 +21,7 @@ class CleartextStorageAdditionalTaintStep extends Unit {
class SensitiveSource extends Expr instanceof SensitiveExpr { class SensitiveSource extends Expr instanceof SensitiveExpr {
/** Holds if this source flows to the `sink`. */ /** Holds if this source flows to the `sink`. */
predicate flowsTo(Expr sink) { predicate flowsTo(Expr sink) {
exists(SensitiveSourceFlowConfig conf | SensitiveSourceFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(sink))
conf.hasFlow(DataFlow::exprNode(this), DataFlow::exprNode(sink))
)
} }
} }
@@ -40,27 +38,25 @@ abstract class Storable extends Call {
abstract Expr getAStore(); abstract Expr getAStore();
} }
private class SensitiveSourceFlowConfig extends TaintTracking2::Configuration { private module SensitiveSourceFlowConfig implements DataFlow::ConfigSig {
SensitiveSourceFlowConfig() { this = "SensitiveSourceFlowConfig" } predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr } predicate isSink(DataFlow::Node sink) { sink instanceof CleartextStorageSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof CleartextStorageSink } predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof CleartextStorageSanitizer }
override predicate isSanitizer(DataFlow::Node sanitizer) { predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
sanitizer instanceof CleartextStorageSanitizer
}
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
any(CleartextStorageAdditionalTaintStep c).step(n1, n2) any(CleartextStorageAdditionalTaintStep c).step(n1, n2)
} }
} }
private module SensitiveSourceFlow = TaintTracking::Global<SensitiveSourceFlowConfig>;
private class DefaultCleartextStorageSanitizer extends CleartextStorageSanitizer { private class DefaultCleartextStorageSanitizer extends CleartextStorageSanitizer {
DefaultCleartextStorageSanitizer() { DefaultCleartextStorageSanitizer() {
this.getType() instanceof NumericType or this.getType() instanceof NumericType or
this.getType() instanceof BooleanType or this.getType() instanceof BooleanType or
exists(EncryptedValueFlowConfig conf | conf.hasFlow(_, this)) EncryptedValueFlow::flow(_, this)
} }
} }
@@ -76,12 +72,10 @@ private class EncryptedSensitiveMethodAccess extends MethodAccess {
} }
/** Flow configuration for encryption methods flowing to inputs of persistent storage. */ /** Flow configuration for encryption methods flowing to inputs of persistent storage. */
private class EncryptedValueFlowConfig extends DataFlow4::Configuration { private module EncryptedValueFlowConfig implements DataFlow::ConfigSig {
EncryptedValueFlowConfig() { this = "EncryptedValueFlowConfig" } predicate isSource(DataFlow::Node src) { src.asExpr() instanceof EncryptedSensitiveMethodAccess }
override predicate isSource(DataFlow::Node src) { predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SensitiveExpr }
src.asExpr() instanceof EncryptedSensitiveMethodAccess
}
override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SensitiveExpr }
} }
private module EncryptedValueFlow = DataFlow::Global<EncryptedValueFlowConfig>;

View File

@@ -28,17 +28,17 @@ class SharedPreferencesEditorMethodAccess extends Storable, MethodAccess {
/** Gets an input, for example `password` in `editor.putString("password", password);`. */ /** Gets an input, for example `password` in `editor.putString("password", password);`. */
override Expr getAnInput() { override Expr getAnInput() {
exists(SharedPreferencesFlowConfig conf, DataFlow::Node editor | exists(DataFlow::Node editor |
sharedPreferencesInput(editor, result) and sharedPreferencesInput(editor, result) and
conf.hasFlow(DataFlow::exprNode(this), editor) SharedPreferencesFlow::flow(DataFlow::exprNode(this), editor)
) )
} }
/** Gets a store, for example `editor.commit();`. */ /** Gets a store, for example `editor.commit();`. */
override Expr getAStore() { override Expr getAStore() {
exists(SharedPreferencesFlowConfig conf, DataFlow::Node editor | exists(DataFlow::Node editor |
sharedPreferencesStore(editor, result) and sharedPreferencesStore(editor, result) and
conf.hasFlow(DataFlow::exprNode(this), editor) SharedPreferencesFlow::flow(DataFlow::exprNode(this), editor)
) )
} }
} }
@@ -65,15 +65,15 @@ private predicate sharedPreferencesStore(DataFlow::Node editor, MethodAccess m)
} }
/** Flow from `SharedPreferences.Editor` to either a setter or a store method. */ /** Flow from `SharedPreferences.Editor` to either a setter or a store method. */
private class SharedPreferencesFlowConfig extends DataFlow::Configuration { private module SharedPreferencesFlowConfig implements DataFlow::ConfigSig {
SharedPreferencesFlowConfig() { this = "SharedPreferencesFlowConfig" } predicate isSource(DataFlow::Node src) {
override predicate isSource(DataFlow::Node src) {
src.asExpr() instanceof SharedPreferencesEditorMethodAccess src.asExpr() instanceof SharedPreferencesEditorMethodAccess
} }
override predicate isSink(DataFlow::Node sink) { predicate isSink(DataFlow::Node sink) {
sharedPreferencesInput(sink, _) or sharedPreferencesInput(sink, _) or
sharedPreferencesStore(sink, _) sharedPreferencesStore(sink, _)
} }
} }
private module SharedPreferencesFlow = DataFlow::Global<SharedPreferencesFlowConfig>;