mirror of
https://github.com/github/codeql.git
synced 2026-01-15 15:34:49 +01:00
88 lines
3.2 KiB
Plaintext
88 lines
3.2 KiB
Plaintext
/** Provides classes to reason about vulnerabilites related to content URIs. */
|
|
|
|
import java
|
|
private import semmle.code.java.dataflow.TaintTracking
|
|
private import semmle.code.java.frameworks.android.Android
|
|
private import semmle.code.java.security.PathSanitizer
|
|
|
|
/** A URI that gets resolved by a `ContentResolver`. */
|
|
abstract class ContentUriResolutionSink extends DataFlow::Node { }
|
|
|
|
/** A sanitizer for content URIs. */
|
|
abstract class ContentUriResolutionSanitizer extends DataFlow::Node { }
|
|
|
|
/**
|
|
* A unit class for adding additional taint steps to configurations related to
|
|
* content URI resolution vulnerabilities.
|
|
*/
|
|
class ContentUriResolutionAdditionalTaintStep extends Unit {
|
|
/** Holds if the step from `node1` to `node2` should be considered an additional taint step. */
|
|
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
|
|
}
|
|
|
|
/** The URI argument of a call to a `ContentResolver` URI-opening method. */
|
|
private class DefaultContentUriResolutionSink extends ContentUriResolutionSink {
|
|
DefaultContentUriResolutionSink() {
|
|
exists(MethodAccess ma |
|
|
ma.getMethod() instanceof UriOpeningContentResolverMethod and
|
|
this.asExpr() = ma.getAnArgument() and
|
|
this.getType().(RefType).hasQualifiedName("android.net", "Uri")
|
|
)
|
|
}
|
|
}
|
|
|
|
/** A `ContentResolver` method that resolves a URI. */
|
|
private class UriOpeningContentResolverMethod extends Method {
|
|
UriOpeningContentResolverMethod() {
|
|
this.hasName([
|
|
"openInputStream", "openOutputStream", "openAssetFile", "openAssetFileDescriptor",
|
|
"openFile", "openFileDescriptor", "openTypedAssetFile", "openTypedAssetFileDescriptor",
|
|
]) and
|
|
this.getDeclaringType() instanceof AndroidContentResolver
|
|
}
|
|
}
|
|
|
|
private class UninterestingTypeSanitizer extends ContentUriResolutionSanitizer {
|
|
UninterestingTypeSanitizer() {
|
|
this.getType() instanceof BoxedType or
|
|
this.getType() instanceof PrimitiveType or
|
|
this.getType() instanceof NumberType
|
|
}
|
|
}
|
|
|
|
private class PathSanitizer extends ContentUriResolutionSanitizer instanceof PathInjectionSanitizer {
|
|
}
|
|
|
|
private class FilenameOnlySanitizer extends ContentUriResolutionSanitizer {
|
|
FilenameOnlySanitizer() {
|
|
exists(Method m | this.asExpr().(MethodAccess).getMethod() = m |
|
|
m.hasQualifiedName("java.io", "File", "getName") or
|
|
m.hasQualifiedName("kotlin.io", "FilesKt", ["getNameWithoutExtension", "getExtension"]) or
|
|
m.hasQualifiedName("org.apache.commons.io", "FilenameUtils", "getName")
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A `ContentUriResolutionSink` that flows to an image-decoding function.
|
|
* Such functions raise exceptions when the input is not a valid image,
|
|
* which prevents accessing arbitrary non-image files.
|
|
*/
|
|
private class DecodedAsAnImageSanitizer extends ContentUriResolutionSanitizer {
|
|
DecodedAsAnImageSanitizer() {
|
|
exists(Argument decodeArg, MethodAccess decode |
|
|
decode.getArgument(0) = decodeArg and
|
|
decode
|
|
.getMethod()
|
|
.hasQualifiedName("android.graphics", "BitmapFactory",
|
|
[
|
|
"decodeByteArray", "decodeFile", "decodeFileDescriptor", "decodeResource",
|
|
"decodeStream"
|
|
])
|
|
|
|
|
TaintTracking::localExprTaint(this.(ContentUriResolutionSink).asExpr().(Argument).getCall(),
|
|
decodeArg)
|
|
)
|
|
}
|
|
}
|