From b0d9c80ccc5deea8fa31ea19ae09e6a56423aeda Mon Sep 17 00:00:00 2001 From: yh-semmle Date: Mon, 11 Feb 2019 20:09:09 -0500 Subject: [PATCH] Java: add taint steps for Protobuf framework --- .../code/java/dataflow/TaintTracking.qll | 9 +++ .../semmle/code/java/frameworks/Protobuf.qll | 56 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 java/ql/src/semmle/code/java/frameworks/Protobuf.qll diff --git a/java/ql/src/semmle/code/java/dataflow/TaintTracking.qll b/java/ql/src/semmle/code/java/dataflow/TaintTracking.qll index 6b96b4b029b..3df7bee8401 100644 --- a/java/ql/src/semmle/code/java/dataflow/TaintTracking.qll +++ b/java/ql/src/semmle/code/java/dataflow/TaintTracking.qll @@ -13,6 +13,7 @@ private import semmle.code.java.security.SecurityTests private import semmle.code.java.security.Validation private import semmle.code.java.frameworks.android.Intent private import semmle.code.java.frameworks.Guice +private import semmle.code.java.frameworks.Protobuf private import semmle.code.java.Maps module TaintTracking { @@ -474,6 +475,8 @@ module TaintTracking { m.hasName("get") or m = any(GuiceProvider gp).getAnOverridingGetMethod() + or + m = any(ProtobufMessageLite p).getAGetterMethod() } private class StringReplaceMethod extends Method { @@ -578,6 +581,12 @@ module TaintTracking { method.getDeclaringType().hasQualifiedName("javax.xml.transform.sax", "SAXSource") and method.hasName("sourceToInputSource") and arg = 0 + or + exists(ProtobufParser p | method = p.getAParseFromMethod()) and + arg = 0 + or + exists(ProtobufMessageLite m | method = m.getAParseFromMethod()) and + arg = 0 } /** diff --git a/java/ql/src/semmle/code/java/frameworks/Protobuf.qll b/java/ql/src/semmle/code/java/frameworks/Protobuf.qll new file mode 100644 index 00000000000..8af99d7f608 --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/Protobuf.qll @@ -0,0 +1,56 @@ +/** + * Provides classes and predicates for working with the Protobuf framework. + */ + +import java + +/** + * The interface `com.google.protobuf.Parser`. + */ +class ProtobufParser extends Interface { + ProtobufParser() { this.hasQualifiedName("com.google.protobuf", "Parser") } + + /** + * Gets a method named `parseFrom` (or similar) declared on a subtype of `com.google.protobuf.Parser`. + */ + Method getAParseFromMethod() { + result.getDeclaringType().getASupertype*().getSourceDeclaration() = this and + result.getName().matches("parse%From") + } +} + +/** + * The interface `com.google.protobuf.MessageLite`. + */ +class ProtobufMessageLite extends Interface { + ProtobufMessageLite() { this.hasQualifiedName("com.google.protobuf", "MessageLite") } + + /** + * Gets a static method named `parseFrom` (or similar) declared on a subtype of the `MessageLite` interface. + */ + Method getAParseFromMethod() { + result = getASubtype+().getAMethod() and + result.getName().matches("parse%From") and + result.isStatic() + } + + /** + * Gets a getter method declared on a subtype of the `MessageLite` interface. + */ + Method getAGetterMethod() { + exists(RefType decl | decl = result.getDeclaringType() and decl = this.getASubtype+() | + exists(string name, string suffix | + suffix = "" or + suffix = "list" or + suffix = "map" or + suffix = "ordefault" or + suffix = "orthrow" + | + exists(Field f | f.getDeclaringType() = decl | + f.getName().toLowerCase().replaceAll("_", "") = name + ) and + result.getName().toLowerCase() = "get" + name + suffix + ) + ) + } +}