diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBomb.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBomb.qhelp index 44256d36ea9..cdadabbf207 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBomb.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBomb.qhelp @@ -5,7 +5,6 @@ Extracting Compressed files with any compression algorithm like gzip can cause to denial of service attacks. Attackers can compress a huge file which created by repeated similiar byte and convert it to a small compressed file. - @@ -25,8 +24,13 @@ An Unsafe Approach can be this example which we don't check for uncompressed siz + + +Zlib Documentation + + A great research to gain more impact by this kind of attacks diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsBrotli.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsBrotli.ql new file mode 100644 index 00000000000..b09858d6471 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsBrotli.ql @@ -0,0 +1,107 @@ +/** + * @name User-controlled file decompression + * @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous + * @kind path-problem + * @problem.severity error + * @security-severity 7.8 + * @precision high + * @id cpp/user-controlled-file-decompression-brotli + * @tags security + * experimental + * external/cwe/cwe-409 + */ + +// https://github.com/google/brotli +import cpp +import semmle.code.cpp.ir.dataflow.TaintTracking +import semmle.code.cpp.security.FlowSources +import semmle.code.cpp.commons.File + +/** + * A Pointer Variable is used in Flow source + */ +private class PointerVar extends VariableAccess { + PointerVar() { this.getType() instanceof PointerType } +} + +/** + * A Pointer Variable is used in Flow source + */ +private class Uint8Var extends VariableAccess { + Uint8Var() { this.getType() instanceof UInt8_t } +} + +/** + * A ZSTD_inBuffer Variable is used in Flow source + */ +private class ZSTDinBufferVar extends VariableAccess { + ZSTDinBufferVar() { this.getType().hasName("ZSTD_inBuffer") } +} + +/** + * The `ZSTD_decompress_usingDDict` function is used in Flow sink + * Ref: https://www.brotli.org/decode.html#af68 + */ +private class BrotliDecoderDecompressFunction extends Function { + BrotliDecoderDecompressFunction() { this.hasGlobalName(["BrotliDecoderDecompress"]) } +} + +/** + * The `BrotliDecoderDecompressStream` function is used in Flow sink + * Ref: https://www.brotli.org/decode.html#a234 + */ +private class BrotliDecoderDecompressStreamFunction extends Function { + BrotliDecoderDecompressStreamFunction() { this.hasGlobalName(["BrotliDecoderDecompressStream"]) } +} + +module BrotliTaintConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowState; + + predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + exists(FunctionCall fc | fc.getTarget() instanceof AllocationFunction | + fc = source.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fopenCall(fc) | + fc = source.asExpr() and + state = "" + ) + or + source.asExpr() instanceof PointerVar and + state = "" + or + source.asExpr() instanceof Uint8Var and + state = "" + } + + predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + exists(FunctionCall fc | fc.getTarget() instanceof BrotliDecoderDecompressStreamFunction | + fc.getArgument(2) = sink.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fc.getTarget() instanceof BrotliDecoderDecompressFunction | + fc.getArgument(1) = sink.asExpr() and + state = "" + ) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, + DataFlow::FlowState state2 + ) { + none() + } + + predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { none() } +} + +module BrotliTaint = TaintTracking::GlobalWithState; + +import BrotliTaint::PathGraph + +from BrotliTaint::PathNode source, BrotliTaint::PathNode sink +where BrotliTaint::flowPath(source, sink) +select sink.getNode(), source, sink, "This Decompression depends on a $@.", source.getNode(), + "potentially untrusted source" diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsBzip2.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsBzip2.ql new file mode 100644 index 00000000000..e9b7d60715d --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsBzip2.ql @@ -0,0 +1,126 @@ +/** + * @name User-controlled file decompression + * @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous + * @kind path-problem + * @problem.severity error + * @security-severity 7.8 + * @precision high + * @id cpp/user-controlled-file-decompression-bzip2 + * experimental + * external/cwe/cwe-409 + */ + +import cpp +import semmle.code.cpp.ir.dataflow.TaintTracking +import semmle.code.cpp.security.FlowSources +import semmle.code.cpp.commons.File + +/** + * A `bz_stream` Variable as a Flow source + */ +private class BzStreamVar extends VariableAccess { + BzStreamVar() { this.getType().hasName("bz_stream") } +} + +/** + * A `BZFILE` Variable as a Flow source + */ +private class BZFILEVar extends VariableAccess { + BZFILEVar() { this.getType().hasName("BZFILE") } +} + +/** + * The `BZ2_bzopen`,`BZ2_bzdopen` functions as a Flow source + */ +private class BZ2BzopenFunction extends Function { + BZ2BzopenFunction() { this.hasGlobalName(["BZ2_bzopen", "BZ2_bzdopen"]) } +} + +/** + * The `BZ2_bzDecompress` function as a Flow source + */ +private class BZ2BzDecompressFunction extends Function { + BZ2BzDecompressFunction() { this.hasGlobalName(["BZ2_bzDecompress"]) } +} + +/** + * The `BZ2_bzReadOpen` function + */ +private class BZ2BzReadOpenFunction extends Function { + BZ2BzReadOpenFunction() { this.hasGlobalName(["BZ2_bzReadOpen"]) } +} + +/** + * The `BZ2_bzRead` function is used in Flow sink + */ +private class BZ2BzReadFunction extends Function { + BZ2BzReadFunction() { this.hasGlobalName("BZ2_bzRead") } +} + +/** + * The `BZ2_bzRead` function is used in Flow sink + */ +private class BZ2BzBuffToBuffDecompressFunction extends Function { + BZ2BzBuffToBuffDecompressFunction() { this.hasGlobalName("BZ2_bzBuffToBuffDecompress") } +} + +/** + * https://www.sourceware.org/bzip2/manual/manual.html + */ +module Bzip2TaintConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowState; + + predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + source.asExpr() instanceof BzStreamVar and + state = "" + or + source.asExpr() instanceof BZFILEVar and + state = "" + or + // will flow into BZ2BzReadOpenFunction + exists(FunctionCall fc | fopenCall(fc) | + fc = source.asExpr() and + state = "" + ) + } + + predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzDecompressFunction | + fc.getArgument(0) = sink.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzReadFunction | + fc.getArgument(1) = sink.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzBuffToBuffDecompressFunction | + fc.getArgument(2) = sink.asExpr() and + state = "" + ) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, + DataFlow::FlowState state2 + ) { + exists(FunctionCall fc | fc.getTarget() instanceof BZ2BzReadOpenFunction | + node1.asExpr() = fc.getArgument(1) and + node2.asExpr() = fc and + state1 = "" and + state2 = "" + ) + } + + predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { none() } +} + +module Bzip2Taint = TaintTracking::GlobalWithState; + +import Bzip2Taint::PathGraph + +from Bzip2Taint::PathNode source, Bzip2Taint::PathNode sink +where Bzip2Taint::flowPath(source, sink) +select sink.getNode(), source, sink, "This Decompressiondepends on a $@.", source.getNode(), + "potentially untrusted source" diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsMiniZip.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsMiniZip.ql new file mode 100644 index 00000000000..b8cd89fc542 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsMiniZip.ql @@ -0,0 +1,102 @@ +/** + * @name User-controlled file decompression + * @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous + * @kind path-problem + * @problem.severity error + * @security-severity 7.8 + * @precision high + * @id cpp/user-controlled-file-decompression-minizip + * @tags security + * experimental + * external/cwe/cwe-409 + */ + +import cpp +import semmle.code.cpp.ir.dataflow.TaintTracking +import semmle.code.cpp.security.FlowSources + +/** + * A `unzFile` Variable as a Flow source + */ +private class UnzFileVar extends VariableAccess { + UnzFileVar() { this.getType().hasName("unzFile") } +} + +/** + * The `UnzOpen` function as a Flow source + */ +private class UnzOpenFunction extends Function { + UnzOpenFunction() { this.hasGlobalName(["UnzOpen", "unzOpen64", "unzOpen2", "unzOpen2_64"]) } +} + +/** + * The `mz_stream_open` function is used in Flow source + */ +private class MzStreamOpenFunction extends Function { + MzStreamOpenFunction() { this.hasGlobalName("mz_stream_open") } +} + +/** + * The `unzReadCurrentFile` function is used in Flow sink + */ +private class UnzReadCurrentFileFunction extends Function { + UnzReadCurrentFileFunction() { this.hasGlobalName(["unzReadCurrentFile"]) } +} + +module MiniZipTaintConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowState; + + predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + exists(FunctionCall fc | fc.getTarget() instanceof UnzOpenFunction | + fc.getArgument(0) = source.asExpr() and + state = "unzFile" + ) + or + source.asExpr() instanceof UnzFileVar and + state = "unzFile" + or + // TO Check + exists(FunctionCall fc | fc.getTarget() instanceof MzStreamOpenFunction | + fc.getArgument(0).getEnclosingVariable() = source.asVariable() and + state = "MzStream" + ) + or + // TO Check + exists(FunctionCall fc | fc.getTarget() instanceof MzStreamOpenFunction | + fc.getArgument(0).getEnclosingVariable() = source.asVariable() and + state = "MzStream" + ) + } + + predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + exists(FunctionCall fc | fc.getTarget() instanceof UnzReadCurrentFileFunction | + fc.getArgument(0) = sink.asExpr() and + state = "unzFile" + // and not sanitizer(fc) + ) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, + DataFlow::FlowState state2 + ) { + exists(FunctionCall fc | fc.getTarget() instanceof UnzOpenFunction | + node1.asExpr() = fc.getArgument(0) and + node2.asExpr() = fc and + state1 = "" and + state2 = "unzFile" + ) + } + + predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { none() } +} + + +module MiniZipTaint = TaintTracking::GlobalWithState; + +import MiniZipTaint::PathGraph + +from MiniZipTaint::PathNode source, MiniZipTaint::PathNode sink +where MiniZipTaint::flowPath(source, sink) +select sink.getNode(), source, sink, "This Decompressiondepends on a $@.", source.getNode(), + "potentially untrusted source" diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsXZ.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsXZ.ql new file mode 100644 index 00000000000..dadbf7a5a8a --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsXZ.ql @@ -0,0 +1,100 @@ +/** + * @name User-controlled file decompression + * @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous + * @kind path-problem + * @problem.severity error + * @security-severity 7.8 + * @precision high + * @id cpp/user-controlled-file-decompression-xz + * @tags security + * experimental + * external/cwe/cwe-409 + */ + +import cpp +import semmle.code.cpp.ir.dataflow.TaintTracking +import semmle.code.cpp.security.FlowSources + +/** + * A Pointer Variable as a Flow source + */ +private class Uint8Var extends VariableAccess { + Uint8Var() { this.getType() instanceof UInt8_t } +} + +/** + * A `lzma_stream` Variable as a Flow source + */ +private class LzmaStreamVar extends VariableAccess { + LzmaStreamVar() { this.getType().hasName("lzma_stream") } +} + +/** + * The `lzma_*_decoder` function is used as a required condition for decompression + */ +private 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 + */ +private class LzmaCodeFunction extends Function { + LzmaCodeFunction() { this.hasGlobalName(["lzma_code"]) } +} + +/** + * The `lzma_stream_buffer_decode` function is used in Flow sink + */ +private class LzmaStreamBufferDecodeFunction extends Function { + LzmaStreamBufferDecodeFunction() { this.hasGlobalName(["lzma_stream_buffer_decode"]) } +} + +/** + * https://github.com/tukaani-project/xz + */ +module XzTaintConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowState; + + predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + source.asExpr() instanceof LzmaStreamVar and + state = "" + or + source.asExpr() instanceof Uint8Var and + state = "" + // and not exists(FunctionCall fc | fc.getTarget() instanceof LzmaStreamDecoderFunction) + } + + predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + exists(FunctionCall fc | fc.getTarget() instanceof LzmaStreamBufferDecodeFunction | + fc.getArgument(1) = sink.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fc.getTarget() instanceof LzmaCodeFunction | + fc.getArgument(0) = sink.asExpr() and + state = "" + ) and + exists(FunctionCall fc2 | fc2.getTarget() instanceof LzmaDecoderFunction) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, + DataFlow::FlowState state2 + ) { + none() + } + + predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { none() } +} + +module XzTaint = TaintTracking::GlobalWithState; + +import XzTaint::PathGraph + +from XzTaint::PathNode source, XzTaint::PathNode sink +where XzTaint::flowPath(source, sink) +select sink.getNode(), source, sink, "This Decompressiondepends on a $@.", source.getNode(), + "potentially untrusted source" diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZSTD.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZSTD.ql new file mode 100644 index 00000000000..9e984bb89e2 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZSTD.ql @@ -0,0 +1,140 @@ +/** + * @name User-controlled file decompression + * @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous + * @kind path-problem + * @problem.severity error + * @security-severity 7.8 + * @precision high + * @id cpp/user-controlled-file-decompression-zstd + * @tags security + * experimental + * external/cwe/cwe-409 + */ + +// https://github.com/facebook/zstd/blob/dev/examples/streaming_decompression.c +import cpp +import semmle.code.cpp.ir.dataflow.TaintTracking +import semmle.code.cpp.security.FlowSources +import semmle.code.cpp.commons.File + +// /** +// * A Pointer Variable as a Flow source +// */ +// private class PointerVar extends VariableAccess { +// PointerVar() { this.getType() instanceof PointerType } +// } +/** + * A ZSTD_inBuffer Variable as a Flow source + */ +private class ZSTDinBufferVar extends VariableAccess { + ZSTDinBufferVar() { this.getType().hasName("ZSTD_inBuffer") } +} + +/** + * A ZSTD_inBuffer_s Variable as a Flow source + */ +private class ZSTDinBufferSVar extends VariableAccess { + ZSTDinBufferSVar() { this.getType().hasName("ZSTD_inBuffer_s") } +} + +/** + * The `ZSTD_decompress` function is used in Flow sink + */ +private class ZSTDDecompressFunction extends Function { + ZSTDDecompressFunction() { this.hasGlobalName(["ZSTD_decompress"]) } +} + +/** + * The `ZSTD_decompressDCtx` function is used in Flow sink + */ +private class ZSTDDecompressDCtxFunction extends Function { + ZSTDDecompressDCtxFunction() { this.hasGlobalName(["ZSTD_decompressDCtx"]) } +} + +/** + * The `ZSTD_decompressStream` function is used in Flow sink + */ +private class ZSTDDecompressStreamFunction extends Function { + ZSTDDecompressStreamFunction() { this.hasGlobalName(["ZSTD_decompressStream"]) } +} + +/** + * The `ZSTD_decompress_usingDDict` function is used in Flow sink + */ +private class ZSTDDecompressUsingDictFunction extends Function { + ZSTDDecompressUsingDictFunction() { this.hasGlobalName(["ZSTD_decompress_usingDDict"]) } +} + +/** + * The `ZSTD_decompress_usingDDict` function is used in Flow sink + */ +private class ZSTDDecompressUsingDDictFunction extends Function { + ZSTDDecompressUsingDDictFunction() { this.hasGlobalName(["ZSTD_decompress_usingDDict"]) } +} + +module ZstdTaintConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowState; + + predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + exists(FunctionCall fc | fc.getTarget() instanceof AllocationFunction | + fc = source.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fopenCall(fc) | + fc = source.asExpr() and + state = "" + ) + or + source.asExpr() instanceof ZSTDinBufferSVar and + state = "" + or + source.asExpr() instanceof ZSTDinBufferVar and + state = "" + } + + predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressFunction | + fc.getArgument(2) = sink.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressDCtxFunction | + fc.getArgument(3) = sink.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressStreamFunction | + fc.getArgument(2) = sink.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressUsingDictFunction | + fc.getArgument(3) = sink.asExpr() and + state = "" + ) + or + exists(FunctionCall fc | fc.getTarget() instanceof ZSTDDecompressUsingDDictFunction | + fc.getArgument(3) = sink.asExpr() and + state = "" + ) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, + DataFlow::FlowState state2 + ) { + none() + } + + predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { none() } +} + +module ZstdTaint = TaintTracking::GlobalWithState; + +import ZstdTaint::PathGraph + +from ZstdTaint::PathNode source, ZstdTaint::PathNode sink +where ZstdTaint::flowPath(source, sink) +select sink.getNode(), source, sink, "This Decompression depends on a $@.", source.getNode(), + "potentially untrusted source" diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsGzopen.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZlibGzopen.ql similarity index 98% rename from cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsGzopen.ql rename to cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZlibGzopen.ql index 6c0804404cd..ce7324eded0 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsGzopen.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZlibGzopen.ql @@ -5,7 +5,7 @@ * @problem.severity error * @security-severity 7.8 * @precision high - * @id cpp/user-controlled-file-decompression1 + * @id cpp/user-controlled-file-zlibgz * @tags security * experimental * external/cwe/cwe-409 diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsInflator.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZlibInflator.ql similarity index 84% rename from cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsInflator.ql rename to cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZlibInflator.ql index fdd11e1fc16..e526b4d9273 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsInflator.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZlibInflator.ql @@ -5,7 +5,7 @@ * @problem.severity error * @security-severity 7.8 * @precision high - * @id cpp/user-controlled-file-decompression2 + * @id cpp/user-controlled-file-zlibinflator * @tags security * experimental * external/cwe/cwe-409 @@ -41,13 +41,6 @@ module ZlibTaintConfig implements DataFlow::ConfigSig { fc.getArgument(0) = sink.asExpr() ) } - - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - exists(FunctionCall fc | fc.getTarget() instanceof InflateFunction | - node1.asExpr() = fc.getArgument(0) and - node2.asExpr() = fc - ) - } } module ZlibTaint = TaintTracking::Global; diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsUncompress.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZlibUncompress.ql similarity index 83% rename from cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsUncompress.ql rename to cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZlibUncompress.ql index 09327616fd9..b385523f185 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsUncompress.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/DecompressionBombsZlibUncompress.ql @@ -5,7 +5,7 @@ * @problem.severity error * @security-severity 7.8 * @precision high - * @id cpp/user-controlled-file-decompression3 + * @id cpp/user-controlled-file-zlibuncompress * @tags security * experimental * external/cwe/cwe-409 @@ -37,13 +37,6 @@ module ZlibTaintConfig implements DataFlow::ConfigSig { fc.getArgument(0) = sink.asExpr() ) } - - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - exists(FunctionCall fc | fc.getTarget() instanceof UncompressFunction | - node1.asExpr() = fc.getArgument(0) and - node2.asExpr() = fc - ) - } } module ZlibTaint = TaintTracking::Global; diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/example_bad.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/example_bad.cpp index 94e3e969a51..af513817386 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/example_bad.cpp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/example_bad.cpp @@ -1,3 +1,8 @@ +#include +#include +#include "zlib.h" +#include +#include int UnsafeInflate(int argc, char *argv[]) { // original string len = 36 diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/example_good.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/example_good.cpp index e3a2d4b2e50..7ad34658367 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/example_good.cpp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-409-DecompressionBomb/example_good.cpp @@ -1,3 +1,8 @@ +#include +#include +#include "zlib.h" +#include +#include int SafeGzread() { std::cout << "enter compressed file name!\n" << std::endl;
Extracting Compressed files with any compression algorithm like gzip can cause to denial of service attacks.
Attackers can compress a huge file which created by repeated similiar byte and convert it to a small compressed file.