Class: Rex::Proto::Http::Request
- Defined in:
- lib/rex/proto/http/request.rb
Overview
HTTP request class.
Direct Known Subclasses
Defined Under Namespace
Constant Summary collapse
- PostRequests =
['POST', 'SEARCH']
Instance Attribute Summary collapse
-
#conn_id ⇒ Object
An identifier associated with the incoming request, can be used to match requests with sessions.
-
#junk_directories ⇒ Object
add junk directories.
-
#junk_end_of_uri ⇒ Object
add junk end of URI.
-
#junk_param_start ⇒ Object
add junk start of params.
-
#junk_params ⇒ Object
add junk params.
-
#junk_pipeline ⇒ Object
add junk pipeline requests.
-
#junk_self_referring_directories ⇒ Object
add junk self referring directories (aka /././././).
-
#junk_slashes ⇒ Object
add junk slashes.
-
#method ⇒ Object
The method being used for the request (e.g. GET).
-
#proto ⇒ Object
The protocol to be sent with the request.
-
#raw_uri ⇒ Object
The raw URI being requested, before any mucking gets to it.
-
#relative_resource ⇒ Object
The resource path relative to the root of a server mount point.
-
#uri_encode_mode ⇒ Object
encoding uri.
-
#uri_parts ⇒ Object
The split up parts of the URI.
Attributes inherited from Packet
#auto_cl, #body_bytes_left, #bufq, #chunk_max_size, #chunk_min_size, #compress, #error, #headers, #incomplete, #inside_chunk, #keepalive, #max_data, #state, #transfer_chunked
Instance Method Summary collapse
-
#body ⇒ Object
Returns a hijacked version of the body that shoves the request’s query string in as a replacement in cases where there is no body.
-
#cmd_string ⇒ Object
Returns the command string derived from the three values.
-
#initialize(method = 'GET', uri = '/', proto = DefaultProtocol) ⇒ Request
constructor
Initializes an instance of an HTTP request with the supplied method, URI, and protocol.
-
#meta_vars ⇒ Object
Returns a hash of variables that contain information about the request, such as the remote host information.
-
#normalize!(str) ⇒ Object
normalize out multiple slashes, directory traversal, and self referrential directories.
- #param_string ⇒ Object
-
#parse_cgi_qstring(str) ⇒ Object
Parses a CGI query string into the var/val combinations.
-
#qstring ⇒ Object
If there were CGI parameters in the URI, this will hold a hash of each variable to value.
-
#resource ⇒ Object
Returns the resource that is being requested.
-
#resource=(rsrc) ⇒ Object
Changes the resource URI.
-
#to_s ⇒ Object
Returns a request packet.
-
#update_cmd_parts(str) ⇒ Object
Updates the command parts for this specific packet type.
-
#update_uri_parts ⇒ Object
Split the URI into the resource being requested and its query string.
-
#uri ⇒ Object
Puts a URI back together based on the URI parts.
-
#uri=(str) ⇒ Object
Updates the underlying URI structure.
Methods inherited from Packet
#[], #[]=, #body=, #check_100, #chunk, #completed?, #from_s, #output_packet, #parse, #parse_body, #parse_header, #reset, #reset_except_queue, #to_terminal_output
Constructor Details
#initialize(method = 'GET', uri = '/', proto = DefaultProtocol) ⇒ Request
Initializes an instance of an HTTP request with the supplied method, URI, and protocol.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/rex/proto/http/request.rb', line 57 def initialize(method = 'GET', uri = '/', proto = DefaultProtocol) super() self.method = method self.raw_uri = uri self.uri_parts = {} self.proto = proto || DefaultProtocol self.chunk_min_size = 1 self.chunk_max_size = 10 self.uri_encode_mode = 'hex-normal' if self.method == 'GET' || self.method == 'CONNECT' self.auto_cl = false end update_uri_parts end |
Instance Attribute Details
#conn_id ⇒ Object
An identifier associated with the incoming request, can be used to match requests with sessions.
279 280 281 |
# File 'lib/rex/proto/http/request.rb', line 279 def conn_id @conn_id end |
#junk_directories ⇒ Object
add junk directories
305 306 307 |
# File 'lib/rex/proto/http/request.rb', line 305 def junk_directories @junk_directories end |
#junk_end_of_uri ⇒ Object
add junk end of URI
323 324 325 |
# File 'lib/rex/proto/http/request.rb', line 323 def junk_end_of_uri @junk_end_of_uri end |
#junk_param_start ⇒ Object
add junk start of params
320 321 322 |
# File 'lib/rex/proto/http/request.rb', line 320 def junk_param_start @junk_param_start end |
#junk_params ⇒ Object
add junk params
314 315 316 |
# File 'lib/rex/proto/http/request.rb', line 314 def junk_params @junk_params end |
#junk_pipeline ⇒ Object
add junk pipeline requests
317 318 319 |
# File 'lib/rex/proto/http/request.rb', line 317 def junk_pipeline @junk_pipeline end |
#junk_self_referring_directories ⇒ Object
add junk self referring directories (aka /././././)
311 312 313 |
# File 'lib/rex/proto/http/request.rb', line 311 def junk_self_referring_directories @junk_self_referring_directories end |
#junk_slashes ⇒ Object
add junk slashes
308 309 310 |
# File 'lib/rex/proto/http/request.rb', line 308 def junk_slashes @junk_slashes end |
#method ⇒ Object
The method being used for the request (e.g. GET).
284 285 286 |
# File 'lib/rex/proto/http/request.rb', line 284 def method @method end |
#proto ⇒ Object
The protocol to be sent with the request.
297 298 299 |
# File 'lib/rex/proto/http/request.rb', line 297 def proto @proto end |
#raw_uri ⇒ Object
The raw URI being requested, before any mucking gets to it
288 289 290 |
# File 'lib/rex/proto/http/request.rb', line 288 def raw_uri @raw_uri end |
#relative_resource ⇒ Object
The resource path relative to the root of a server mount point.
302 303 304 |
# File 'lib/rex/proto/http/request.rb', line 302 def relative_resource @relative_resource end |
#uri_encode_mode ⇒ Object
encoding uri
326 327 328 |
# File 'lib/rex/proto/http/request.rb', line 326 def uri_encode_mode @uri_encode_mode end |
#uri_parts ⇒ Object
The split up parts of the URI.
293 294 295 |
# File 'lib/rex/proto/http/request.rb', line 293 def uri_parts @uri_parts end |
Instance Method Details
#body ⇒ Object
Returns a hijacked version of the body that shoves the request’s query string in as a replacement in cases where there is no body. YOLO! (shrug)
226 227 228 229 230 231 232 |
# File 'lib/rex/proto/http/request.rb', line 226 def body str = super || '' if str.length == 0 && PostRequests.include?(self.method) str = param_string end str end |
#cmd_string ⇒ Object
Returns the command string derived from the three values.
237 238 239 240 241 |
# File 'lib/rex/proto/http/request.rb', line 237 def cmd_string proto_str = (self.proto =~ /^\d/) ? "HTTP/#{self.proto}" : self.proto "#{self.method} #{self.uri} #{proto_str}\r\n" end |
#meta_vars ⇒ Object
Returns a hash of variables that contain information about the request, such as the remote host information.
TODO
273 274 |
# File 'lib/rex/proto/http/request.rb', line 273 def end |
#normalize!(str) ⇒ Object
normalize out multiple slashes, directory traversal, and self referrential directories
111 112 113 114 115 |
# File 'lib/rex/proto/http/request.rb', line 111 def normalize!(str) i = 0 while (str.gsub!(/(\/\.\/|\/\w+\/\.\.\/|\/\/)/,'/')); i += 1; end i end |
#param_string ⇒ Object
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/rex/proto/http/request.rb', line 171 def param_string params=[] self.uri_parts['QueryString'].each_pair { |param, value| # inject a random number of params in between each param if self.junk_params rand(10)+5.times { params.push(Rex::Text.rand_text_alpha(rand(16) + 5) + '=' + Rex::Text.rand_text_alpha(rand(10) + 1)) } end if value.kind_of?(Array) value.each { |subvalue| params.push(Rex::Text.uri_encode(param, self.uri_encode_mode) + '=' + Rex::Text.uri_encode(subvalue, self.uri_encode_mode)) } else if !value.nil? params.push(Rex::Text.uri_encode(param, self.uri_encode_mode) + '=' + Rex::Text.uri_encode(value, self.uri_encode_mode)) else params.push(Rex::Text.uri_encode(param, self.uri_encode_mode)) end end } # inject some junk params at the end of the param list, just to be sure :P if self.junk_params rand(10)+5.times { params.push(Rex::Text.rand_text_alpha(rand(32) + 5) + '=' + Rex::Text.rand_text_alpha(rand(64) + 5)) } end params.join('&') end |
#parse_cgi_qstring(str) ⇒ Object
Parses a CGI query string into the var/val combinations.
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/rex/proto/http/request.rb', line 331 def parse_cgi_qstring(str) qstring = {} # Delimit on each variable str.split(/[;&]/).each { |vv| var = vv val = '' if (md = vv.match(/(.+?)=(.*)/)) var = md[1] val = md[2] end # Add the item to the hash with logic to convert values to an array # if so desired. if (qstring.include?(var)) if (qstring[var].kind_of?(Array)) qstring[var] << val else curr = self.qstring[var] qstring[var] = [ curr, val ] end else qstring[var] = val end } return qstring end |
#qstring ⇒ Object
If there were CGI parameters in the URI, this will hold a hash of each variable to value. If there is more than one value for a given variable, an array of each value is returned.
263 264 265 |
# File 'lib/rex/proto/http/request.rb', line 263 def qstring self.uri_parts['QueryString'] end |
#resource ⇒ Object
Returns the resource that is being requested.
246 247 248 |
# File 'lib/rex/proto/http/request.rb', line 246 def resource self.uri_parts['Resource'] end |
#resource=(rsrc) ⇒ Object
Changes the resource URI. This is used when making a request relative to a given mount point.
254 255 256 |
# File 'lib/rex/proto/http/request.rb', line 254 def resource=(rsrc) self.uri_parts['Resource'] = rsrc end |
#to_s ⇒ Object
Returns a request packet
209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/rex/proto/http/request.rb', line 209 def to_s str = '' if self.junk_pipeline host = '' if self.headers['Host'] host = "Host: #{self.headers['Host']}\r\n" end str << "GET / HTTP/1.1\r\n#{host}Connection: Keep-Alive\r\n\r\n" * self.junk_pipeline self.headers['Connection'] = 'Closed' end str + super end |
#update_cmd_parts(str) ⇒ Object
Updates the command parts for this specific packet type.
78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/rex/proto/http/request.rb', line 78 def update_cmd_parts(str) if (md = str.match(/^(.+?)\s+(.+?)\s+HTTP\/(.+?)\r?\n?$/i)) self.method = md[1] self.raw_uri = CGI.unescape(md[2]) self.proto = md[3] update_uri_parts else raise RuntimeError, "Invalid request command string", caller end end |
#update_uri_parts ⇒ Object
Split the URI into the resource being requested and its query string.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/rex/proto/http/request.rb', line 93 def update_uri_parts # If it has a query string, get the parts. if ((self.raw_uri) and (md = self.raw_uri.match(/(.+?)\?(.*)$/))) self.uri_parts['QueryString'] = parse_cgi_qstring(md[2]) self.uri_parts['Resource'] = md[1] # Otherwise, just assume that the URI is equal to the resource being # requested. else self.uri_parts['QueryString'] = {} self.uri_parts['Resource'] = self.raw_uri end self.normalize!(resource) # Set the relative resource to the actual resource. self.relative_resource = resource end |
#uri ⇒ Object
Puts a URI back together based on the URI parts
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 |
# File 'lib/rex/proto/http/request.rb', line 118 def uri str = self.uri_parts['Resource'].dup || '/' # /././././ if self.junk_self_referring_directories str.gsub!('/') { '/.' * (rand(3) + 1) + '/' } end # /%3faaa=bbbbb # which could possibly decode to "/?aaa=bbbbb", which if the IDS normalizes first, then splits the URI on ?, then it can be bypassed if self.junk_param_start str.sub!('/', '/%3f' + Rex::Text.rand_text_alpha(rand(5) + 1) + '=' + Rex::Text.rand_text_alpha(rand(10) + 1) + '/../') end # /RAND/../RAND../ if self.junk_directories str.gsub!('/') { dirs = '' (rand(5)+5).times { dirs << '/' + Rex::Text.rand_text_alpha(rand(5) + 1) + '/..' } dirs + '/' } end # //// # # NOTE: this must be done after all other odd directory junk, since they would cancel this out, except junk_end_of_uri, since that a specific slash in a specific place if self.junk_slashes str.gsub!('/') { '/' * (rand(3) + 2) } str.sub!(/^[\/]+/, '/') # only one beginning slash! end # /%20HTTP/1.0%0d%0a/../../ # which decodes to "/ HTTP/1.0\r\n" if self.junk_end_of_uri str.sub!(/^\//, '/%20HTTP/1.0%0d%0a/../../') end Rex::Text.uri_encode(str, self.uri_encode_mode) if !PostRequests.include?(self.method) if param_string.size > 0 str << '?' + param_string end end str end |
#uri=(str) ⇒ Object
Updates the underlying URI structure
203 204 205 206 |
# File 'lib/rex/proto/http/request.rb', line 203 def uri=(str) self.raw_uri = str update_uri_parts end |