Class: Rex::Proto::Http::Request
- Defined in:
- lib/rex/proto/http/request.rb
Overview
HTTP request class.
Defined Under Namespace
Constant Summary collapse
- PostRequests =
['POST', 'SEARCH']
Instance Attribute Summary collapse
-
#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, #bufq, #chunk_max_size, #chunk_min_size, #compress, #error, #headers, #incomplete, #max_data, #state, #transfer_chunked
Instance Method Summary collapse
- #body ⇒ Object
-
#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
#[], #[]=, #chunk, #completed?, #from_s, #parse, #reset, #reset_except_queue
Constructor Details
#initialize(method = 'GET', uri = '/', proto = DefaultProtocol) ⇒ Request
Initializes an instance of an HTTP request with the supplied method, URI, and protocol.
55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/rex/proto/http/request.rb', line 55 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' update_uri_parts end |
Instance Attribute Details
#junk_directories ⇒ Object
add junk directories
294 295 296 |
# File 'lib/rex/proto/http/request.rb', line 294 def junk_directories @junk_directories end |
#junk_end_of_uri ⇒ Object
add junk end of URI
312 313 314 |
# File 'lib/rex/proto/http/request.rb', line 312 def junk_end_of_uri @junk_end_of_uri end |
#junk_param_start ⇒ Object
add junk start of params
309 310 311 |
# File 'lib/rex/proto/http/request.rb', line 309 def junk_param_start @junk_param_start end |
#junk_params ⇒ Object
add junk params
303 304 305 |
# File 'lib/rex/proto/http/request.rb', line 303 def junk_params @junk_params end |
#junk_pipeline ⇒ Object
add junk pipeline requests
306 307 308 |
# File 'lib/rex/proto/http/request.rb', line 306 def junk_pipeline @junk_pipeline end |
#junk_self_referring_directories ⇒ Object
add junk self referring directories (aka /././././)
300 301 302 |
# File 'lib/rex/proto/http/request.rb', line 300 def junk_self_referring_directories @junk_self_referring_directories end |
#junk_slashes ⇒ Object
add junk slashes
297 298 299 |
# File 'lib/rex/proto/http/request.rb', line 297 def junk_slashes @junk_slashes end |
#method ⇒ Object
The method being used for the request (e.g. GET).
273 274 275 |
# File 'lib/rex/proto/http/request.rb', line 273 def method @method end |
#proto ⇒ Object
The protocol to be sent with the request.
286 287 288 |
# File 'lib/rex/proto/http/request.rb', line 286 def proto @proto end |
#raw_uri ⇒ Object
The raw URI being requested, before any mucking gets to it
277 278 279 |
# File 'lib/rex/proto/http/request.rb', line 277 def raw_uri @raw_uri end |
#relative_resource ⇒ Object
The resource path relative to the root of a server mount point.
291 292 293 |
# File 'lib/rex/proto/http/request.rb', line 291 def relative_resource @relative_resource end |
#uri_encode_mode ⇒ Object
encoding uri
315 316 317 |
# File 'lib/rex/proto/http/request.rb', line 315 def uri_encode_mode @uri_encode_mode end |
#uri_parts ⇒ Object
The split up parts of the URI.
282 283 284 |
# File 'lib/rex/proto/http/request.rb', line 282 def uri_parts @uri_parts end |
Instance Method Details
#body ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/rex/proto/http/request.rb', line 216 def body str = super || '' if str.length > 0 return str end if PostRequests.include?(self.method) return param_string end '' end |
#cmd_string ⇒ Object
Returns the command string derived from the three values.
231 232 233 234 235 |
# File 'lib/rex/proto/http/request.rb', line 231 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
267 268 |
# File 'lib/rex/proto/http/request.rb', line 267 def end |
#normalize!(str) ⇒ Object
normalize out multiple slashes, directory traversal, and self referrential directories
105 106 107 108 109 |
# File 'lib/rex/proto/http/request.rb', line 105 def normalize!(str) i = 0 while (str.gsub!(/(\/\.\/|\/\w+\/\.\.\/|\/\/)/,'/')); i += 1; end i end |
#param_string ⇒ Object
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/rex/proto/http/request.rb', line 165 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.
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
# File 'lib/rex/proto/http/request.rb', line 320 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.
257 258 259 |
# File 'lib/rex/proto/http/request.rb', line 257 def qstring self.uri_parts['QueryString'] end |
#resource ⇒ Object
Returns the resource that is being requested.
240 241 242 |
# File 'lib/rex/proto/http/request.rb', line 240 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.
248 249 250 |
# File 'lib/rex/proto/http/request.rb', line 248 def resource=(rsrc) self.uri_parts['Resource'] = rsrc end |
#to_s ⇒ Object
Returns a request packet
203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/rex/proto/http/request.rb', line 203 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.
72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/rex/proto/http/request.rb', line 72 def update_cmd_parts(str) if (md = str.match(/^(.+?)\s+(.+?)\s+HTTP\/(.+?)\r?\n?$/)) self.method = md[1] self.raw_uri = URI.decode(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.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/rex/proto/http/request.rb', line 87 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
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 |
# File 'lib/rex/proto/http/request.rb', line 112 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
197 198 199 200 |
# File 'lib/rex/proto/http/request.rb', line 197 def uri=(str) self.raw_uri = str update_uri_parts end |