Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions java/lib/ResearchMode.qll
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class FieldTaintStep extends TaintTracking::AdditionalTaintStep {
class NotifyWaitTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(
MethodAccess notify, RefType t, MethodAccess wait, SynchronizedStmt notifySync,
MethodCall notify, RefType t, MethodCall wait, SynchronizedStmt notifySync,
SynchronizedStmt waitSync
|
notify.getMethod().getName() = ["notify", "notifyAll"] and
Expand All @@ -65,7 +65,7 @@ class NotifyWaitTaintStep extends TaintTracking::AdditionalTaintStep {
*/
class ExceptionTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(Call call, TryStmt t, CatchClause c, MethodAccess gm |
exists(Call call, TryStmt t, CatchClause c, MethodCall gm |
call.getEnclosingStmt().getEnclosingStmt*() = t.getBlock() and
t.getACatchClause() = c and
(
Expand All @@ -85,7 +85,7 @@ class ExceptionTaintStep extends TaintTracking::AdditionalTaintStep {
*/
private class GetterTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma, Method m |
exists(MethodCall ma, Method m |
ma.getMethod() = m and
m.getName().matches("get%") and
m.getNumberOfParameters() = 0 and
Expand All @@ -97,7 +97,7 @@ private class GetterTaintStep extends TaintTracking::AdditionalTaintStep {
/*
* private class SetterTaintStep extends TaintTracking::AdditionalTaintStep {
* override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
* exists(MethodAccess ma, Method m |
* exists(MethodCall ma, Method m |
* ma.getMethod() = m and
* m.getName().matches("set%") and
* m.getNumberOfParameters() = 1 and
Expand All @@ -110,8 +110,8 @@ private class GetterTaintStep extends TaintTracking::AdditionalTaintStep {
*
* class GlobalSanitizer extends TaintTracking::Sanitizer {
* override predicate sanitize(DataFlow::Node node) {
* node.asExpr().(MethodAccess).getMethod().hasName("getInputStream") or
* node.asExpr().(MethodAccess).getMethod().hasName("getHostName")
* node.asExpr().(MethodCall).getMethod().hasName("getInputStream") or
* node.asExpr().(MethodCall).getMethod().hasName("getHostName")
* }
* }
*/
Expand Down
14 changes: 7 additions & 7 deletions java/lib/applications/Dubbo.qll
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module Dubbo {

class CodecSupportGetPayload extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod()
.getDeclaringType()
.hasQualifiedName("org.apache.dubbo.remoting.transport", "CodecSupport") and
Expand All @@ -34,7 +34,7 @@ module Dubbo {

class CodecSupportDeserialize extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod()
.getDeclaringType()
.hasQualifiedName("org.apache.dubbo.remoting.transport", "CodecSupport") and
Expand All @@ -58,7 +58,7 @@ module Dubbo {

class ChannelBuffer_ThisReturn_TaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod()
.getDeclaringType()
.getASourceSupertype*()
Expand All @@ -72,7 +72,7 @@ module Dubbo {

class ChannelBuffer_ThisArg1_TaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod()
.getDeclaringType()
.getASourceSupertype*()
Expand All @@ -86,7 +86,7 @@ module Dubbo {

class ChannelBuffer_ThisArg0_TaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod()
.getDeclaringType()
.getASourceSupertype*()
Expand All @@ -100,7 +100,7 @@ module Dubbo {

class ChannelBuffer_ArgThis1_TaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod()
.getDeclaringType()
.getASourceSupertype*()
Expand All @@ -114,7 +114,7 @@ module Dubbo {

class ChannelBuffer_ArgThis0_TaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod()
.getDeclaringType()
.getASourceSupertype*()
Expand Down
24 changes: 16 additions & 8 deletions java/lib/codeql-pack.lock.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@
lockVersion: 1.0.0
dependencies:
codeql/dataflow:
version: 0.0.3
version: 1.0.0
codeql/java-all:
version: 0.7.4
version: 1.0.0
codeql/mad:
version: 0.1.4
version: 1.0.0
codeql/rangeanalysis:
version: 1.0.0
codeql/regex:
version: 0.1.4
version: 1.0.0
codeql/ssa:
version: 0.1.4
version: 1.0.0
codeql/threat-models:
version: 1.0.0
codeql/tutorial:
version: 0.1.4
version: 1.0.0
codeql/typeflow:
version: 1.0.0
codeql/typetracking:
version: 0.1.4
version: 1.0.0
codeql/util:
version: 0.1.4
version: 1.0.0
codeql/xml:
version: 1.0.0
compiled: false
2 changes: 1 addition & 1 deletion java/lib/frameworks/GoogleGuavaCache.qll
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ module GuavaCache {
*/
class LoadCacheItemTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma1, MethodAccess ma2, VarAccess va |
exists(MethodCall ma1, MethodCall ma2, VarAccess va |
ma1.getMethod() instanceof GetFromCacheMethod and
ma2.getMethod() instanceof BuildCacheLoaderMethod and
exists(Method m |
Expand Down
8 changes: 4 additions & 4 deletions java/lib/frameworks/Protobuf.qll
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import semmle.code.java.dataflow.FlowSources
module Protobuf {
class ProtoToCoreTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod().getName().matches("toCore%") and
n2.asExpr() = ma and
n1.asExpr() = ma.getArgument(0)
Expand All @@ -13,7 +13,7 @@ module Protobuf {

class ByteStringThisReturnTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
//ma.getMethod().getName().matches(["toByteArray", "toString", "toStringUtf8", "substring", "concat", "asReadOnlyByteBuffer", "asReadOnlyByteBufferList"]) and
ma.getMethod().getName().matches("toByteArray") and
ma.getMethod()
Expand All @@ -29,7 +29,7 @@ module Protobuf {

class ByteStringArgReturnTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod().getName().matches(["readFrom", "copyFrom", "concat"]) and
ma.getMethod()
.getDeclaringType()
Expand All @@ -44,7 +44,7 @@ module Protobuf {

class RemoteSource extends RemoteFlowSource {
RemoteSource() {
exists(MethodAccess ma, Method m |
exists(MethodCall ma, Method m |
ma.getMethod() = m and
m.getName().matches("get%") and
m.getDeclaringType()
Expand Down
2 changes: 1 addition & 1 deletion java/lib/ghsl/BeanManipulation.qll
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SetPropertyMethod extends Method {

class BeanManipulationSink extends DataFlow::ExprNode {
BeanManipulationSink() {
exists(MethodAccess ma |
exists(MethodCall ma |
ma.getMethod() instanceof SetPropertyMethod and
this.getExpr() = ma.getAnArgument()
)
Expand Down
163 changes: 75 additions & 88 deletions java/lib/ghsl/CommandInjectionRuntimeExec.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,124 +4,111 @@ import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources

abstract class Source extends DataFlow::Node {
Source() { this = this }
}

// a static string of an unsafe executable tainting arg 0 of Runtime.exec()
class ExecTaintConfiguration extends TaintTracking::Configuration {
ExecTaintConfiguration() { this = "ExecTaintConfiguration" }

override
predicate
isSource(DataFlow::Node source) {
source.asExpr() instanceof StringLiteral
and source.asExpr().(StringLiteral).getValue() instanceof UnSafeExecutable
module RuntimeExec {
// a static string of an unsafe executable tainting arg 0 of Runtime.exec()
module RuntimeExecConfiguration implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof StringLiteral and
source.asExpr().(StringLiteral).getValue() instanceof UnSafeExecutable
}

override
predicate
isSink(DataFlow::Node sink) {
exists(RuntimeExecMethod method, MethodAccess call |
call.getMethod() = method
and sink.asExpr() = call.getArgument(0)
and sink.asExpr().getType() instanceof Array
)
predicate isSink(DataFlow::Node sink) {
exists(RuntimeExecMethod method, MethodCall call |
call.getMethod() = method and
sink.asExpr() = call.getArgument(0) and
sink.asExpr().getType() instanceof Array
)
}

override
predicate
isSanitizer(DataFlow::Node node) {
node.asExpr().getFile().isSourceFile() and
(
node instanceof AssignToNonZeroIndex
or node instanceof ArrayInitAtNonZeroIndex
or node instanceof StreamConcatAtNonZeroIndex
or node.getType() instanceof PrimitiveType
or node.getType() instanceof BoxedType
)
predicate isBarrier(DataFlow::Node node) {
node.asExpr().getFile().isSourceFile() and
(
node instanceof AssignToNonZeroIndex or
node instanceof ArrayInitAtNonZeroIndex or
node instanceof StreamConcatAtNonZeroIndex or
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType
)
}
}
}

abstract class Source extends DataFlow::Node {
Source() {
this = this
}
}
module RuntimeExecFlow = TaintTracking::Global<RuntimeExecConfiguration>;

import RuntimeExecFlow::PathGraph
}

// taint flow from user data to args of the command
class ExecTaintConfiguration2 extends TaintTracking::Configuration {
ExecTaintConfiguration2() { this = "ExecTaintConfiguration2" }

override
predicate
isSource(DataFlow::Node source) {
source instanceof Source
module ExecTaint {
module ExecTaintConfiguration implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }

predicate isSink(DataFlow::Node sink) {
exists(RuntimeExecMethod method, MethodCall call, int index |
call.getMethod() = method and
sink.asExpr() = call.getArgument(index) and
sink.asExpr().getType() instanceof Array
)
}

override
predicate
isSink(DataFlow::Node sink) {
exists(RuntimeExecMethod method, MethodAccess call, int index |
call.getMethod() = method
and sink.asExpr() = call.getArgument(index)
and sink.asExpr().getType() instanceof Array
)
predicate isBarrier(DataFlow::Node node) {
node.asExpr().getFile().isSourceFile() and
(
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType
)
}
}

override
predicate
isSanitizer(DataFlow::Node node) {
node.asExpr().getFile().isSourceFile() and
(
node.getType() instanceof PrimitiveType
or node.getType() instanceof BoxedType
)
}
}
module ExecTaintFlow = TaintTracking::Global<ExecTaintConfiguration>;

import ExecTaintFlow::PathGraph
}

// array[3] = node
class AssignToNonZeroIndex extends DataFlow::Node {
AssignExpr assign;
ArrayAccess access;

AssignToNonZeroIndex() {
assign.getDest() = access
and access.getIndexExpr().(IntegerLiteral).getValue() != "0"
and assign.getSource() = this.asExpr()
}
AssignExpr assign;
ArrayAccess access;

AssignToNonZeroIndex() {
assign.getDest() = access and
access.getIndexExpr().(IntegerLiteral).getValue() != "0" and
assign.getSource() = this.asExpr()
}
}


// String[] array = {"a", "b, "c"};
class ArrayInitAtNonZeroIndex extends DataFlow::Node {
ArrayInit init;
int index;
ArrayInit init;
int index;

ArrayInitAtNonZeroIndex() {
init.getInit(index) = this.asExpr()
and index != 0
}
ArrayInitAtNonZeroIndex() {
init.getInit(index) = this.asExpr() and
index != 0
}
}

// Stream.concat(Arrays.stream(array_1), Arrays.stream(array_2))
class StreamConcatAtNonZeroIndex extends DataFlow::Node {
MethodAccess call;
int index;

StreamConcatAtNonZeroIndex() {
call.getMethod().getQualifiedName() = "java.util.stream.Stream.concat"
and call.getArgument(index) = this.asExpr()
and index != 0
}
MethodCall call;
int index;

StreamConcatAtNonZeroIndex() {
call.getMethod().getQualifiedName() = "java.util.stream.Stream.concat" and
call.getArgument(index) = this.asExpr() and
index != 0
}
}


// allow list of executables that execute their arguments
// TODO: extend with data extensions
class UnSafeExecutable extends string {
bindingset[this]
UnSafeExecutable() {
this.regexpMatch("^(|.*/)([a-z]*sh|javac?|python[23]?|perl|[Pp]ower[Ss]hell|php|node|deno|bun|ruby|osascript|cmd|Rscript|groovy)(\\.exe)?$")
and not this.matches("netsh.exe")
}
bindingset[this]
UnSafeExecutable() {
this.regexpMatch("^(|.*/)([a-z]*sh|javac?|python[23]?|perl|[Pp]ower[Ss]hell|php|node|deno|bun|ruby|osascript|cmd|Rscript|groovy)(\\.exe)?$") and
not this.matches("netsh.exe")
}
}
Loading