Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go: Decompression Bombs #13553

Merged
merged 67 commits into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from 59 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
fbfc959
V1 Bombs
am0o0 May 28, 2023
f1918fb
v1.1
am0o0 Jul 30, 2023
1b598c8
v1.2 make better sinks
am0o0 Jul 31, 2023
260c111
put comment about detecting https://github.com/advisories/GHSA-jpxj-2…
am0o0 Jul 31, 2023
4ee5473
fix a mistake :(
am0o0 Jul 31, 2023
56d0254
fix ReadAll argumrnt number
am0o0 Jul 31, 2023
26f1091
fix a mistake :(
am0o0 Jul 31, 2023
ab7e797
it seems that I must use both isSink and isSource with flow states!
am0o0 Jul 31, 2023
7ce825c
convert to module based dataflow
am0o0 Jul 31, 2023
f79bd2a
added remote flow sources related to multipart upload, added flag pac…
am0o0 Aug 5, 2023
c76d0d3
fix a mistake ioutil => io/ioutil
am0o0 Sep 5, 2023
f6f99fb
remove parameter as source
am0o0 Sep 7, 2023
0f540f4
add sources to detect CVE completely
am0o0 Sep 7, 2023
08f78a2
fix some flowstate bug which Had caused to FP
am0o0 Sep 14, 2023
5a3a8d7
fix some flowstate bug which Had caused to FP
am0o0 Sep 14, 2023
e1d5c9d
fix grammar mistake
am0o0 Sep 14, 2023
2e7529c
remove local sources
am0o0 Sep 29, 2023
2961b79
add multipart sources
am0o0 Sep 29, 2023
9245e1c
remove CLI sources Library file & qldoc warnings
am0o0 Sep 30, 2023
d99c0a2
update tests
am0o0 Sep 30, 2023
00d1b11
chore fix document example
am0o0 Sep 30, 2023
31cae20
make DecompressionBombs module and extention points
am0o0 Oct 6, 2023
d4b2ca5
add vendor for tests, update test results, revert go/vendor/modules.t…
am0o0 Oct 6, 2023
21f477a
revert go/vendor/ :(
am0o0 Oct 6, 2023
13577f7
fix tests, add more comments
am0o0 Oct 6, 2023
14d1e08
reformat
am0o0 Oct 10, 2023
d63b33b
fix a tests
am0o0 Oct 11, 2023
c630300
fix a tests
am0o0 Oct 11, 2023
46616d6
fix a qldoc isuse
am0o0 Oct 11, 2023
8e5be13
fix conflict
am0o0 Oct 11, 2023
7d60f03
fix tests
am0o0 Oct 11, 2023
ac5e9c7
fix a mistake: remove vendor dir from go root directory
am0o0 Oct 12, 2023
761aede
perfomed review suggestions, make Decompression Sink simpler, uncomme…
am0o0 Nov 2, 2023
a1a49bd
Merge branch 'main' into amammad-go-bombs
am0o0 Nov 2, 2023
1fc18be
Merge branch 'main' into amammad-go-bombs
am0o0 Nov 2, 2023
bd1ee9b
fix tests
am0o0 Nov 2, 2023
e421c49
fix multipart mistake :(
am0o0 Nov 6, 2023
7af4b8d
fix isBarrier according to code review
am0o0 Nov 6, 2023
b8c8006
add an extended Class of string for FlowState
am0o0 Nov 6, 2023
75e01d3
Thanks to @owen-mc that provided a good solution of that I couldn't …
am0o0 Nov 21, 2023
fabde6e
fix tests and remove tarfile tar.Reader as sink
am0o0 Nov 21, 2023
1aa4494
stash
am0o0 Nov 24, 2023
2cb0afe
fix some qldocs and some spells
am0o0 Dec 8, 2023
737f3e8
fix stubs
am0o0 Dec 10, 2023
bb50171
Merge branch 'main' into amammad-go-bombs
am0o0 Dec 10, 2023
59195cc
Merge branch 'main' into amammad-go-bombs
am0o0 Dec 10, 2023
572777f
fix a bug in stubs
am0o0 Dec 10, 2023
87b1028
fix pgzip missed sink, apply isBarrier directly to CopyN sink, add ne…
am0o0 Dec 17, 2023
a72bd7e
add GOOD and BAD comment to sinks, some chore improvements on tests
am0o0 Dec 17, 2023
79edc5c
add sanitizer to all Read methods, add Inline tests, improve tests
am0o0 Dec 18, 2023
0efb007
Add hasFlowToComparison to all sinks as a sanitizer
am0o0 Jan 14, 2024
a1c384c
change Decompression bombs Query structure
am0o0 Jan 14, 2024
b2edf6c
add Inline Expectations Test, update tests accordingly
am0o0 Jan 14, 2024
3fcb0ee
move MultipartAndFormRemoteSource to DecompressionBombs.qll
am0o0 Jan 14, 2024
2fe1094
minor change for resolving rebase conflicts
am0o0 Jan 14, 2024
3c79faf
minor change for resolving rebase conflicts
am0o0 Jan 14, 2024
073f65d
Merge branch 'amammad-go-bombs' of https://github.com/amammad/codeql …
am0o0 Jan 14, 2024
65ac943
fix Typo in tests
am0o0 Jan 14, 2024
a47c702
change TN to GOOD instead of using hasValueFlow
am0o0 Jan 15, 2024
9054201
call functions in the same order as the function declarations
am0o0 Feb 20, 2024
13b0a9a
New testcase 's2Reader.ReadByte()'
am0o0 Feb 20, 2024
3307457
use `implements` predicate for `io` interfaces,
am0o0 Feb 20, 2024
4c769f2
update tests
am0o0 Feb 20, 2024
376c6ea
Merge branch 'main' into amammad-go-bombs
am0o0 Feb 21, 2024
1927530
update tests after branch update
am0o0 Feb 21, 2024
66130d2
convert abstract predicate `isAdditionalFlowStep` to non-abstract
am0o0 Mar 8, 2024
43df6a2
add comments for already implemented `io.Read` and `io.WriteTo` Sinks.
am0o0 Mar 8, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!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. Also you can limit the size of reader buffer.</p>

</recommendation>
<example>
<p>
Using "io.LimitReader" and "io.CopyN" are the best option to prevent decompression bomb attacks.
</p>
<sample src="example_good.go"/>

<sample src="example_good_2.go" />
</example>
<references>

<li>
<a href="https://github.com/russellhaering/gosaml2/security/advisories/GHSA-6gc3-crp7-25w5">CVE-2023-26483 </a>
</li>
<li>
<a href="https://www.bamsoftware.com/hacks/zipbomb/">A great research to gain more impact by this kind of attacks</a>
</li>

</references>
</qhelp>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @name Uncontrolled file decompression
* @description Uncontrolled 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 go/uncontrolled-file-decompression
* @tags security
* experimental
* external/cwe/cwe-409
*/

import go
import experimental.frameworks.DecompressionBombs
import DecompressionBomb::Flow::PathGraph

from DecompressionBomb::Flow::PathNode source, DecompressionBomb::Flow::PathNode sink
where DecompressionBomb::Flow::flowPath(source, sink)
select sink.getNode(), source, sink, "This decompression is $@.", source.getNode(),
"decompressing compressed data without managing output size"
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package main

import (
"archive/zip"
"fmt"
"io"
"os"
)

func ZipOpenReader(filename string) {
// Open the zip file
r, _ := zip.OpenReader(filename)
var totalBytes int64
for _, f := range r.File {
rc, _ := f.Open()
totalBytes = 0
for {
result, _ := io.CopyN(os.Stdout, rc, 68)
if result == 0 {
break
}
totalBytes = totalBytes + result
if totalBytes > 1024*1024 {
fmt.Print(totalBytes)
_ = rc.Close()
break
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"compress/gzip"
"io"
"os"
)

func safeReader() {
var src io.Reader
src, _ = os.Open("filename")
gzipR, _ := gzip.NewReader(src)
dstF, _ := os.OpenFile("./test", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
defer dstF.Close()
var newSrc io.Reader
newSrc = io.LimitReader(gzipR, 1024*1024*1024*5)
_, _ = io.Copy(dstF, newSrc)
}
63 changes: 63 additions & 0 deletions go/ql/src/experimental/frameworks/DecompressionBombs.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Provides a taint tracking configuration for reasoning about decompression bomb vulnerabilities.
*/

import go

class MimeMultipartFileHeader extends UntrustedFlowSource::Range {
MimeMultipartFileHeader() {
exists(DataFlow::FieldReadNode frn | this = frn |
frn.getField().hasQualifiedName("mime/multipart", "FileHeader", ["Filename", "Header"])
)
or
exists(DataFlow::Method m |
m.hasQualifiedName("mime/multipart", "FileHeader", "Open") and
this = m.getACall().getResult(0)
)
or
exists(DataFlow::FieldReadNode frn |
frn.getField().hasQualifiedName("mime/multipart", "Form", "Value")
)
}
}

/** Provides a taint tracking configuration for reasoning about decompression bomb vulnerabilities. */
module DecompressionBomb {
import experimental.frameworks.DecompressionBombsCustomizations

module Config implements DataFlow::StateConfigSig {
class FlowState = DecompressionBombs::FlowState;

predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof UntrustedFlowSource and
state = ""
}

predicate isSink(DataFlow::Node sink, FlowState state) {
sink instanceof DecompressionBombs::Sink and
state =
[
"ZstdNewReader", "XzNewReader", "GzipNewReader", "PgzipNewReader", "S2NewReader",
"SnappyNewReader", "ZlibNewReader", "FlateNewReader", "Bzip2NewReader", "ZipOpenReader",
"ZipKlauspost"
]
}

predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
exists(DecompressionBombs::AdditionalTaintStep addStep |
addStep.isAdditionalFlowStep(fromNode, toNode)
)
}

predicate isAdditionalFlowStep(
DataFlow::Node fromNode, FlowState fromState, DataFlow::Node toNode, FlowState toState
) {
exists(DecompressionBombs::AdditionalTaintStep addStep |
addStep.isAdditionalFlowStep(fromNode, fromState, toNode, toState)
)
}
}

/** Tracks taint flow for reasoning about decompression bomb vulnerabilities. */
module Flow = TaintTracking::GlobalWithState<Config>;
}
Loading
Loading