Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,14 @@ private class AspNetCoreRemoteFlowSourceMember extends TaintTracking::TaintedMem
}

/** A data flow source of remote user input (ASP.NET query collection). */
class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode {
class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::Node {
AspNetCoreQueryRemoteFlowSource() {
exists(ValueOrRefType t |
t instanceof MicrosoftAspNetCoreHttpHttpRequest or
t instanceof MicrosoftAspNetCoreHttpQueryCollection or
t instanceof MicrosoftAspNetCoreHttpQueryString
|
this.getExpr().(Call).getTarget().getDeclaringType() = t or
this.asExpr().(Call).getTarget().getDeclaringType() = t or
this.asExpr().(Access).getTarget().getDeclaringType() = t
)
or
Expand All @@ -245,7 +245,7 @@ class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFl
.getDeclaringType()
.hasFullyQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and
c.getTarget().getName() = "TryGetValue" and
this.asExpr() = c.getArgumentForName("value")
this.asDefinition().getTargetAccess() = c.getArgument(1)
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Extracting Compressed files with any compression algorithm like gzip can cause to denial of service attacks.</p>
<p>Attackers can compress a huge file which created by repeated similiar byte and convert it to a small compressed file.</p>

</overview>
<recommendation>

<p>When you want to decompress a user-provided compressed file you must be careful about the decompression ratio or read these files within a loop byte by byte to be able to manage the decompressed size in each cycle of the loop.</p>

</recommendation>
<example>

<p>A good Blog Post about decompression bombs and recommended method is already written by Gérald Barré in <a href="https://www.meziantou.net/prevent-zip-bombs-in-dotnet.htm">this</a> blog post</p>

<references>

<li>
<a href="https://www.bamsoftware.com/hacks/zipbomb/">A great research to gain more impact by this kind of attack</a>
</li>

</references>
</qhelp>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* @name Uncontrolled file decompression
* @description Uncontrolled decompression without checking the compression rate is dangerous
* @kind path-problem
* @problem.severity error
* @security-severity 7.8
* @precision medium
* @id cs/user-controlled-file-decompression
* @tags security
* experimental
* external/cwe/cwe-409
*/

import csharp
import semmle.code.csharp.security.dataflow.flowsources.Remote
import experimental.dataflow.security.DecompressionBomb
import RemoteFlowSource

/**
* A taint tracking configuration for Decompression Bomb.
*/
module DecompressionBombModule implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }

predicate isSink(DataFlow::Node sink) { sink instanceof DecompressionBomb::Sink }

predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
any(DecompressionBomb::AdditionalStep a).isAdditionalFlowStep(node1, node2)
}
}

module DecompressionBombConfig = TaintTracking::Global<DecompressionBombModule>;

import DecompressionBombConfig::PathGraph

from DecompressionBombConfig::PathNode source, DecompressionBombConfig::PathNode sink
where DecompressionBombConfig::flowPath(source, sink)
select sink.getNode(), source, sink, "This uncontrolled depends on a $@.", source.getNode(), "this"
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import csharp
import semmle.code.csharp.security.dataflow.flowsources.Remote

/** A data flow source of remote user input by Form File (ASP.NET core request data). */
class FormFile extends AspNetRemoteFlowSource {
FormFile() {
// openReadStream is already implemented but I'm putting this here because of having a uniform class for FormFile
exists(MethodCall mc |
mc.getTarget().hasFullyQualifiedName("Microsoft.AspNetCore.Http", "IFormFile", "OpenReadStream") and
this.asExpr() = mc
)
or
exists(MethodCall mc |
mc.getTarget()
.hasFullyQualifiedName("Microsoft.AspNetCore.Http", "IFormFile", ["CopyTo", "CopyToAsync"]) and
this.asParameter() = mc.getTarget().getParameter(0)
)
or
exists(Property fa |
fa.getDeclaringType().hasFullyQualifiedName("Microsoft.AspNetCore.Http", "IFormFile") and
fa.hasName(["ContentType", "ContentDisposition", "Name", "FileName"]) and
this.asExpr() = fa.getAnAccess()
)
}

override string getSourceType() { result = "ASP.NET core request data from multipart request" }
}

/** A data flow source of remote user input by Form (ASP.NET core request data). */
class FormCollection extends AspNetRemoteFlowSource {
FormCollection() {
exists(Property fa |
fa.getDeclaringType().hasFullyQualifiedName("Microsoft.AspNetCore.Http", "IFormCollection") and
fa.hasName("Keys") and
this.asExpr() = fa.getAnAccess()
)
or
exists(Call c |
c.getTarget()
.getDeclaringType()
.hasFullyQualifiedName("Microsoft.AspNetCore.Http", "IFormCollection") and
c.getTarget().getName() = "TryGetValue" and
this.asDefinition().getTargetAccess() = c.getArgument(1)
)
}

override string getSourceType() {
result = "ASP.NET core request data from multipart request Form Keys"
}
}

/** A data flow source of remote user input by Headers (ASP.NET core request data). */
class HeaderDictionary extends AspNetRemoteFlowSource {
HeaderDictionary() {
exists(Property fa |
fa.getDeclaringType().hasFullyQualifiedName("Microsoft.AspNetCore.Http", "IHeaderDictionary") and
this.asExpr() = fa.getAnAccess()
)
}

override string getSourceType() { result = "ASP.NET core request data from Headers of request" }
}
Loading