add FlowSources as a common source for all sinks, so we don't need States anymore

This commit is contained in:
am0o0
2024-06-13 03:30:07 +02:00
parent 273848c879
commit 11a416ea7c
2 changed files with 104 additions and 254 deletions

View File

@@ -27,298 +27,156 @@ import ZlibUncompress
import ZlibInflator
import Brotli
module DecompressionTaintConfig implements DataFlow::StateConfigSig {
class FlowState = DataFlow::FlowState;
module DecompressionTaintConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
(
exists(FunctionCall fc | fc.getTarget() instanceof AllocationFunction | fc = source.asExpr())
or
exists(FunctionCall fc | fopenCall(fc) | fc = source.asExpr())
or
source.asExpr() instanceof PointerVar
or
source.asExpr() instanceof Uint8Var
) and
state = "brotli"
or
(
source.asExpr() instanceof BzStreamVar
or
source.asExpr() instanceof BzFileVar
or
exists(FunctionCall fc | fopenCall(fc) | fc = source.asExpr())
) and
state = "bzip2"
or
exists(FunctionCall fc | fc.getTarget() instanceof Archive_read_new |
fc.getArgument(0) = source.asExpr()
) and
state = "libarchive"
or
(
source.asExpr() instanceof UnsignedCharVar
or
source.asExpr() instanceof PointerVar
or
source.asExpr() instanceof CharVar
or
source.asExpr() instanceof MzZipArchiveVar
or
source.asExpr() instanceof MzStreampVar
or
source.asDefiningArgument() =
any(Call call | call.getTarget() instanceof MzInflateInit).getArgument(0)
or
source.asDefiningArgument() =
any(Call call | call.getTarget() instanceof MzZip).getArgument(0)
) and
state = "libminiz"
or
(
exists(FunctionCall fc | fc.getTarget() instanceof AllocationFunction | fc = source.asExpr())
or
exists(FunctionCall fc | fopenCall(fc) | fc = source.asExpr())
or
source.asExpr() instanceof ZSTDinBufferSVar
or
source.asExpr() instanceof ZSTDinBufferVar
) and
state = "zstd"
or
(
exists(FunctionCall fc | fc.getTarget() instanceof UnzOpenFunction |
fc.getArgument(0) = source.asExpr()
)
or
source.asExpr() instanceof UnzFileVar
) and
state = "unzFile"
or
exists(FunctionCall fc | fc.getTarget() instanceof Mz_zip_reader_create |
fc = source.asExpr() and
state = "mz_zip_reader"
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall fc | fc.getTarget() instanceof BrotliDecoderDecompressStreamFunction |
fc.getArgument(2) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof Mz_zip_create |
fc = source.asExpr() and
state = "mz_zip"
exists(FunctionCall fc | fc.getTarget() instanceof BrotliDecoderDecompressFunction |
fc.getArgument(1) = sink.asExpr()
)
or
(
source.asExpr() instanceof LzmaStreamVar
or
source.asExpr() instanceof Uint8Var
) and
state = "xz"
exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzDecompressFunction |
fc.getArgument(0) = sink.asExpr()
)
or
(
exists(FunctionCall fc | fc.getTarget() instanceof GzopenFunction |
fc.getArgument(0) = source.asExpr() and
// arg 0 can be a path string which we must do following check
not fc.getArgument(0).isConstant()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzdopenFunction |
fc.getArgument(0) = source.asExpr()
)
or
source.asExpr() instanceof GzFileVar
) and
state = "zlibgzopen"
exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzReadFunction |
fc.getArgument(1) = sink.asExpr()
)
or
source.asExpr() instanceof ZStreamVar and state = "zlifinflator"
or
source.asExpr() instanceof BytefVar and state = "zlibuncompress"
}
predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
(
exists(FunctionCall fc | fc.getTarget() instanceof BrotliDecoderDecompressStreamFunction |
fc.getArgument(2) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof BrotliDecoderDecompressFunction |
fc.getArgument(1) = sink.asExpr()
)
) and
state = "brotli"
or
(
exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzDecompressFunction |
fc.getArgument(0) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzReadFunction |
fc.getArgument(1) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzBuffToBuffDecompressFunction |
fc.getArgument(2) = sink.asExpr()
)
) and
state = "bzip2"
exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzBuffToBuffDecompressFunction |
fc.getArgument(2) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof Archive_read_data_block |
fc.getArgument(0) = sink.asExpr() and
state = "libarchive"
fc.getArgument(0) = sink.asExpr()
)
or
(
exists(FunctionCall fc | fc.getTarget() instanceof MzUncompress |
fc.getArgument(0) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof MzZipReaderExtract |
fc.getArgument(1) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof MzInflate |
fc.getArgument(0) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof TinflDecompress |
fc.getArgument(1) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof TinflDecompressMem |
fc.getArgument(0) = sink.asExpr()
)
) and
state = "libminiz"
exists(FunctionCall fc | fc.getTarget() instanceof MzUncompress |
fc.getArgument(0) = sink.asExpr()
)
or
(
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressFunction |
fc.getArgument(2) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressDCtxFunction |
fc.getArgument(3) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressStreamFunction |
fc.getArgument(2) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressUsingDictFunction |
fc.getArgument(3) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressUsingDDictFunction |
fc.getArgument(3) = sink.asExpr()
)
) and
state = "zstd"
exists(FunctionCall fc | fc.getTarget() instanceof MzZipReaderExtract |
fc.getArgument(1) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof MzInflate |
fc.getArgument(0) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof TinflDecompress |
fc.getArgument(1) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof TinflDecompressMem |
fc.getArgument(0) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressFunction |
fc.getArgument(2) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressDCtxFunction |
fc.getArgument(3) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressStreamFunction |
fc.getArgument(2) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressUsingDictFunction |
fc.getArgument(3) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressUsingDDictFunction |
fc.getArgument(3) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof UnzReadCurrentFileFunction |
fc.getArgument(0) = sink.asExpr() and
state = "unzFile"
fc.getArgument(0) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof Mz_zip_reader_entry |
fc.getArgument(1) = sink.asExpr() and
state = "mz_zip_reader"
fc.getArgument(1) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof Mz_zip_entry |
fc.getArgument(1) = sink.asExpr() and
state = "mz_zip"
fc.getArgument(1) = sink.asExpr()
)
or
(
exists(FunctionCall fc | fc.getTarget() instanceof LzmaStreamBufferDecodeFunction |
fc.getArgument(1) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof LzmaCodeFunction |
fc.getArgument(0) = sink.asExpr()
)
) and
state = "xz" and
exists(FunctionCall fc2 | fc2.getTarget() instanceof LzmaDecoderFunction)
exists(FunctionCall fc | fc.getTarget() instanceof LzmaStreamBufferDecodeFunction |
fc.getArgument(1) = sink.asExpr()
)
or
(
exists(FunctionCall fc | fc.getTarget() instanceof GzReadFunction |
fc.getArgument(0) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzFreadFunction |
sink.asExpr() = fc.getArgument(3)
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzGetsFunction |
sink.asExpr() = fc.getArgument(0)
)
) and
state = "zlibgzopen"
exists(FunctionCall fc | fc.getTarget() instanceof LzmaCodeFunction |
fc.getArgument(0) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzReadFunction |
fc.getArgument(0) = sink.asExpr()
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzFreadFunction |
sink.asExpr() = fc.getArgument(3)
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzGetsFunction |
sink.asExpr() = fc.getArgument(0)
)
or
exists(FunctionCall fc | fc.getTarget() instanceof InflateFunction |
fc.getArgument(0) = sink.asExpr()
) and
state = "zlifinflator"
)
or
exists(FunctionCall fc | fc.getTarget() instanceof UncompressFunction |
fc.getArgument(0) = sink.asExpr()
) and
state = "zlibuncompress"
)
}
predicate isAdditionalFlowStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(FunctionCall fc | fc.getTarget() instanceof UnzOpenFunction |
node1.asExpr() = fc.getArgument(0) and
node2.asExpr() = fc and
state1 = "" and
state2 = "unzFile"
node2.asExpr() = fc
)
or
exists(FunctionCall fc | fc.getTarget() instanceof Mz_zip_reader_entry |
node1.asExpr() = fc.getArgument(0) and
node2.asExpr() = fc.getArgument(1) and
state1 = "" and
state2 = "mz_zip_reader"
node2.asExpr() = fc.getArgument(1)
)
or
exists(FunctionCall fc | fc.getTarget() instanceof Mz_zip_entry |
node1.asExpr() = fc.getArgument(0) and
node2.asExpr() = fc.getArgument(1) and
state1 = "" and
state2 = "mz_zip"
node2.asExpr() = fc.getArgument(1)
)
or
(
exists(FunctionCall fc |
fc.getTarget() instanceof GzopenFunction or fc.getTarget() instanceof GzdopenFunction
|
node1.asExpr() = fc.getArgument(0) and
node2.asExpr() = fc
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzReadFunction |
node1.asExpr() = fc.getArgument(0) and
node2.asExpr() = fc.getArgument(1)
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzFreadFunction |
node1.asExpr() = fc.getArgument(3) and
node2.asExpr() = fc.getArgument(0)
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzGetsFunction |
node1.asExpr() = fc.getArgument(0) and
node1.asExpr() = fc.getArgument(1)
)
) and
state1 = "" and
state2 = "gzopen"
exists(FunctionCall fc |
fc.getTarget() instanceof GzopenFunction or fc.getTarget() instanceof GzdopenFunction
|
node1.asExpr() = fc.getArgument(0) and
node2.asExpr() = fc
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzReadFunction |
node1.asExpr() = fc.getArgument(0) and
node2.asExpr() = fc.getArgument(1)
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzFreadFunction |
node1.asExpr() = fc.getArgument(3) and
node2.asExpr() = fc.getArgument(0)
)
or
exists(FunctionCall fc | fc.getTarget() instanceof GzGetsFunction |
node1.asExpr() = fc.getArgument(0) and
node1.asExpr() = fc.getArgument(1)
)
}
predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { none() }
}
module DecompressionTaint = TaintTracking::GlobalWithState<DecompressionTaintConfig>;
module DecompressionTaint = TaintTracking::Global<DecompressionTaintConfig>;
import DecompressionTaint::PathGraph

View File

@@ -13,14 +13,6 @@ class LzmaStreamVar extends VariableAccess {
LzmaStreamVar() { this.getType().hasName("lzma_stream") }
}
/**
* The `lzma_*_decoder` function is used as a required condition for decompression
*/
class LzmaDecoderFunction extends Function {
LzmaDecoderFunction() {
this.hasGlobalName(["lzma_stream_decoder", "lzma_auto_decoder", "lzma_alone_decoder"])
}
}
/**
* The `lzma_code` function is used in Flow sink