Module: PWN::Plugins::Fuzz
- Defined in:
- lib/pwn/plugins/fuzz.rb
Overview
This plugin was created to support fuzzing various networking protocols
Class Method Summary collapse
-
.authors ⇒ Object
- Author(s)
-
0day Inc.
-
.help ⇒ Object
Display Usage for this Module.
-
.socket(opts = {}) ⇒ Object
- Supported Method Parameters
-
socket_fuzz_results_arr = PWN::Plugins::Fuzz.socket( target: ‘required - target host or ip’, port: ‘required - target port’, protocol: ‘optional - :tcp || :udp (defaults to tcp)’, tls: ‘optional - boolean connect to target socket using TLS (defaults to false)’, fuzz_delimeter: ‘optional - fuzz delimeter used in request to specify where payloads should reside (defaults to u2665)’, request: ‘required - String object of socket request w/ u001A as fuzz delimeter (e.g. “GET /u001Au001A HTTP/1.1rnHost: u001A127..0.0.1u001Arnrn”)’, payload: ‘required - payload string’, encoding: ‘optional - :base64 || :hex || :html_entity || :url (Defaults to nil)’, encoding_depth: ‘optional - number of times to encode payload (defaults to 1)’, char_encoding: ‘optional - character encoding returned by PWN::Plugins::Char.list_encoders (defaults to UTF-8)’, response_timeout: ‘optional - float (defaults to 0.9)’, request_rate_limit: ‘optional - float (defaults to 0.3)’ ).
Class Method Details
.authors ⇒ Object
- Author(s)
-
0day Inc. <[email protected]>
174 175 176 177 178 |
# File 'lib/pwn/plugins/fuzz.rb', line 174 public_class_method def self. "AUTHOR(S): 0day Inc. <[email protected]> " end |
.help ⇒ Object
Display Usage for this Module
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/pwn/plugins/fuzz.rb', line 182 public_class_method def self.help puts "USAGE: socket_fuzz_results_arr = #{self}.socket( target: 'required = target host or ip', port: 'required => target port', protocol: 'optional => :tcp || :udp (defaults to tcp)', tls: 'optional - boolean connect to target socket using TLS (defaults to false)', fuzz_delimeter: \"optional - fuzz delimeter used in request to specify where payloads should reside (defaults to \u2665)\", request: \"required - String object of socket request w/ \u2665 as fuzz delimeter (e.g. '\"GET /\u2665\u2665 HTTP/1.1\\r\\nHost: \u2665127.0.0.1\u2665\\r\\n\\r\\n\"')\", payload: 'required - payload string', encoding: 'optional - :base64 || :hex || :html_entity || :url (Defaults to nil)', encoding_depth: 'optional - number of times to encode payload (defaults to 1)', char_encoding: 'optional - character encoding returned by PWN::Plugins::Char.list_encoders (defaults to UTF-8)', response_timeout: 'optional - float (defaults to 0.9)', request_rate_limit: 'optional - float (defaults to 0.3)' ) #{self}.authors " end |
.socket(opts = {}) ⇒ Object
- Supported Method Parameters
-
socket_fuzz_results_arr = PWN::Plugins::Fuzz.socket(
target: 'required - target host or ip', port: 'required - target port', protocol: 'optional - :tcp || :udp (defaults to tcp)', tls: 'optional - boolean connect to target socket using TLS (defaults to false)', fuzz_delimeter: 'optional - fuzz delimeter used in request to specify where payloads should reside (defaults to \u2665)', request: 'required - String object of socket request w/ \u001A as fuzz delimeter (e.g. "GET /\u001A\u001A HTTP/1.1\r\nHost: \u001A127..0.0.1\u001A\r\n\r\n")', payload: 'required - payload string', encoding: 'optional - :base64 || :hex || :html_entity || :url (Defaults to nil)', encoding_depth: 'optional - number of times to encode payload (defaults to 1)', char_encoding: 'optional - character encoding returned by PWN::Plugins::Char.list_encoders (defaults to UTF-8)', response_timeout: 'optional - float (defaults to 0.9)', request_rate_limit: 'optional - float (defaults to 0.3)'
)
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/pwn/plugins/fuzz.rb', line 27 public_class_method def self.socket(opts = {}) target = opts[:target].to_s.scrub port = opts[:port].to_i protocol = opts[:protocol] tls = opts[:tls] opts[:encoding].nil? ? encoding = nil : encoding = opts[:encoding].to_s.strip.chomp.scrub.downcase.to_sym opts[:encoding_depth].nil? ? encoding_depth = 1 : encoding_depth = opts[:encoding_depth].to_i opts[:char_encoding].nil? ? char_encoding = 'UTF-8' : char_encoding = opts[:char_encoding].to_s opts[:fuzz_delimeter].nil? ? fuzz_delimeter = "\u2665" : fuzz_delimeter = opts[:fuzz_delimeter] request = opts[:request].to_s.encode(char_encoding, 'UTF-8') payload = opts[:payload].to_s.encode(char_encoding, 'UTF-8') if encoding case encoding when :base64 if encoding_depth > 1 (1..encoding_depth).each do payload = Base64.strict_encode64(payload) end else payload = Base64.strict_encode64(payload) end when :hex if encoding_depth > 1 (1..encoding_depth).each do hex_payload = '' payload.each_byte { |b| hex_payload = "#{hex_payload}#{format('\x%02x', b)}" } payload = hex_payload end else hex_payload = '' payload.each_byte { |b| hex_payload = "#{hex_payload}#{format('\x%02x', b)}" } payload = hex_payload end when :html_entity if encoding_depth > 1 (1..encoding_depth).each do payload = HTMLEntities.new.encode(payload) end else payload = HTMLEntities.new.encode(payload) end when :url if encoding_depth > 1 (1..encoding_depth).each do payload = CGI.escape(payload) end else payload = CGI.escape(payload) end else raise "Encoding type: #{encoding} not supported." end end opts[:response_timeout].nil? ? response_timeout = 0.9 : response_timeout = opts[:response_timeout].to_f opts[:request_rate_limit].nil? ? request_rate_limit = 0.3 : request_rate_limit = opts[:request_rate_limit].to_f socket_fuzz_results_arr = [] # Find fuzz delimeter index numbers in request request_delim_index_arr = [] request.each_char.with_index do |char, char_index| request_delim_index_arr.push(char_index) if char == fuzz_delimeter end # request_delim_index_arr should always return an even length, # otherwise the request is missing a fuzz delimeter. request_delim_index_arr.each_slice(2).with_index do |placeholder_slice, placeholder_slice_index| this_socket_fuzz_result = {} begin_delim_char_index_shift_width = placeholder_slice_index * 2 begin_delim_char_index = placeholder_slice[0].to_i - begin_delim_char_index_shift_width end_delim_char_index_shift_width = (placeholder_slice_index * 2) + 2 end_delim_char_index = placeholder_slice[1].to_i - end_delim_char_index_shift_width this_request = request.dup.delete(fuzz_delimeter).encode(char_encoding, 'UTF-8') if end_delim_char_index.positive? this_request[begin_delim_char_index..end_delim_char_index] = payload else # begin_delim_char_index should always be 0 this_request[begin_delim_char_index] = payload end sock_obj = PWN::Plugins::Sock.connect( target: target, port: port, protocol: protocol, tls: tls ) this_socket_fuzz_result[:timestamp] = Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s this_socket_fuzz_result[:request] = this_request this_socket_fuzz_result[:request_encoding] = this_request.encoding.name this_socket_fuzz_result[:request_len] = this_request.length # Send Fuzz Payload in its rawest form (as long as it will undump first) sock_obj.write(this_request.encode('ASCII-8BIT', undef: :replace).undump) does_respond = sock_obj.wait_readable(response_timeout) if does_respond response = sock_obj.read response_len = response.length this_socket_fuzz_result[:response] = response.to_s.inspect this_socket_fuzz_result[:response_len] = response_len else this_socket_fuzz_result[:response] = '' this_socket_fuzz_result[:response_len] = 0 end sleep request_rate_limit sock_obj = PWN::Plugins::Sock.disconnect(sock_obj: sock_obj) # TODO: dump into file once array reaches max length (avoid memory consumption issues) socket_fuzz_results_arr.push(this_socket_fuzz_result) rescue Errno::ECONNRESET => e response = e. this_socket_fuzz_result[:response] = response this_socket_fuzz_result[:response_len] = response.length sleep request_rate_limit sock_obj = PWN::Plugins::Sock.disconnect(sock_obj: sock_obj) unless sock_obj.nil? # TODO: dump into file once array reaches max length (avoid memory consumption issues) socket_fuzz_results_arr.push(this_socket_fuzz_result) next rescue StandardError => e response = "#{e.class}: #{e.} #{e.backtrace}" this_socket_fuzz_result[:response] = response this_socket_fuzz_result[:response_len] = response.length sleep request_rate_limit sock_obj = PWN::Plugins::Sock.disconnect(sock_obj: sock_obj) unless sock_obj.nil? # TODO: dump into file once array reaches max length (avoid memory consumption issues) socket_fuzz_results_arr.push(this_socket_fuzz_result) next end socket_fuzz_results_arr rescue StandardError => e raise e ensure sock_obj = PWN::Plugins::Sock.disconnect(sock_obj: sock_obj) unless sock_obj.nil? end |