Skip to content

Commit 2b5105b

Browse files
committed
Land rapid7#3353, @jjarmoc's Rex::Text::uri_encode improvements
2 parents b5ba261 + a3cc499 commit 2b5105b

File tree

9 files changed

+32
-12
lines changed

9 files changed

+32
-12
lines changed

lib/msf/core/exploit/http/client.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def initialize(info = {})
5858

5959
register_evasion_options(
6060
[
61-
OptEnum.new('HTTP::uri_encode_mode', [false, 'Enable URI encoding', 'hex-normal', ['none', 'hex-normal', 'hex-all', 'hex-random', 'u-normal', 'u-all', 'u-random']]),
61+
OptEnum.new('HTTP::uri_encode_mode', [false, 'Enable URI encoding', 'hex-normal', ['none', 'hex-normal', 'hex-noslashes', 'hex-random', 'hex-all', 'u-normal', 'u-all', 'u-random']]),
6262
OptBool.new('HTTP::uri_full_url', [false, 'Use the full URL for all HTTP requests', false]),
6363
OptInt.new('HTTP::pad_method_uri_count', [false, 'How many whitespace characters to use between the method and uri', 1]),
6464
OptInt.new('HTTP::pad_uri_version_count', [false, 'How many whitespace characters to use between the uri and version', 1]),

lib/rex/proto/http/client_request.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ClientRequest
4040
#
4141
'encode_params' => true,
4242
'encode' => false,
43-
'uri_encode_mode' => 'hex-normal', # hex-all, hex-random, u-normal, u-random, u-all
43+
'uri_encode_mode' => 'hex-normal', # hex-all, hex-noslashes, hex-random, u-all, u-noslashes, u-random
4444
'uri_encode_count' => 1, # integer
4545
'uri_full_url' => false, # bool
4646
'pad_method_uri_count' => 1, # integer

lib/rex/text.rb

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -788,15 +788,18 @@ def self.uri_encode(str, mode = 'hex-normal')
788788

789789
return str if mode == 'none' # fast track no encoding
790790

791-
all = /[^\/\\]+/
791+
all = /./
792+
noslashes = /[^\/\\]+/
792793
# http://tools.ietf.org/html/rfc3986#section-2.3
793794
normal = /[^a-zA-Z0-9\/\\\.\-_~]+/
794795

795796
case mode
796-
when 'hex-normal'
797-
return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
798797
when 'hex-all'
799798
return str.gsub(all) { |s| Rex::Text.to_hex(s, '%') }
799+
when 'hex-normal'
800+
return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
801+
when 'hex-noslashes'
802+
return str.gsub(noslashes) { |s| Rex::Text.to_hex(s, '%') }
800803
when 'hex-random'
801804
res = ''
802805
str.each_byte do |c|
@@ -806,10 +809,12 @@ def self.uri_encode(str, mode = 'hex-normal')
806809
b.gsub(normal){ |s| Rex::Text.to_hex(s, '%') } )
807810
end
808811
return res
809-
when 'u-normal'
810-
return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
811812
when 'u-all'
812813
return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
814+
when 'u-normal'
815+
return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
816+
when 'u-noslashes'
817+
return str.gsub(noslashes) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
813818
when 'u-random'
814819
res = ''
815820
str.each_byte do |c|

modules/exploits/multi/http/gitorious_graph.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def exploit
5555
# Make sure the URI begins with a slash
5656
uri = normalize_uri(datastore['URI'])
5757

58-
command = Rex::Text.uri_encode(payload.raw, 'hex-all')
58+
command = Rex::Text.uri_encode(payload.raw, 'hex-noslashes')
5959
command.gsub!("%20","%2520")
6060
res = send_request_cgi({
6161
'uri' => "/api"+ uri + "/log/graph/%60#{command}%60",

modules/exploits/multi/http/php_cgi_arg_injection.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def rand_encode(string, max = string.length)
196196
max.times { chars << rand(string.length)}
197197
end
198198
end
199-
chars.uniq.sort.reverse.each{|index| string[index] = Rex::Text.uri_encode(string[index,1], "hex-all")}
199+
chars.uniq.sort.reverse.each{|index| string[index] = Rex::Text.uri_encode(string[index,1], "hex-noslashes")}
200200
string
201201
end
202202

modules/exploits/multi/http/spree_search_exec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def initialize(info = {})
5151
end
5252

5353
def exploit
54-
command = Rex::Text.uri_encode(payload.raw, 'hex-all')
54+
command = Rex::Text.uri_encode(payload.raw, 'hex-noslashes')
5555
res = send_request_raw({
5656
'uri' => normalize_uri(datastore['URI']) + "?search[send][]=eval&search[send][]=Kernel.fork%20do%60#{command}%60end",
5757
'method' => 'GET',

modules/exploits/multi/http/spree_searchlogic_exec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def initialize(info = {})
5353
end
5454

5555
def exploit
56-
command = Rex::Text.uri_encode(payload.raw, 'hex-all')
56+
command = Rex::Text.uri_encode(payload.raw, 'hex-noslashes')
5757

5858
urlconfigdir = normalize_uri(datastore['URI']) + '/' + "api/orders.json?search[instance_eval]=Kernel.fork%20do%60#{command}%60end"
5959
res = send_request_raw({

modules/exploits/windows/browser/foxit_reader_plugin_url_bof.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def on_request_uri(cli, request)
182182
sploit << self.send(my_target[:rop])
183183
sploit << p.encoded
184184

185-
resp['Location'] = request.uri + '.pdf?' + Rex::Text.uri_encode(sploit, 'hex-all')
185+
resp['Location'] = request.uri + '.pdf?' + Rex::Text.uri_encode(sploit, 'hex-noslashes')
186186
cli.send_response(resp)
187187

188188
# handle the payload

spec/lib/rex/proto/http/client_request_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@
189189
'foo[]' => 'bar',
190190
'bar' => 'baz',
191191
'frobnicate' => 'the froozle?',
192+
'foshizzle' => 'my/nizzle',
192193
}
193194
end
194195

@@ -215,6 +216,7 @@
215216
str.should include("foo[]=bar")
216217
str.should include("bar=baz")
217218
str.should include("frobnicate=the froozle?")
219+
str.should include("foshizzle=my/nizzle")
218220
end
219221
end
220222

@@ -226,6 +228,18 @@
226228
str.should include("foo%5b%5d=bar")
227229
str.should include("bar=baz")
228230
str.should include("frobnicate=the%20froozle%3f")
231+
str.should include("foshizzle=my/nizzle")
232+
end
233+
end
234+
235+
context "and 'uri_encode_mode' = hex-noslashes" do
236+
let(:encode_mode) { 'hex-noslashes' }
237+
it "should encode all chars" do
238+
str = client_request.to_s
239+
str.should include("%66%6f%6f%5b%5d=%62%61%72")
240+
str.should include("%62%61%72=%62%61%7a")
241+
str.should include("%66%72%6f%62%6e%69%63%61%74%65=%74%68%65%20%66%72%6f%6f%7a%6c%65%3f")
242+
str.should include("%66%6f%73%68%69%7a%7a%6c%65=%6d%79/%6e%69%7a%7a%6c%65")
229243
end
230244
end
231245

@@ -236,6 +250,7 @@
236250
str.should include("%66%6f%6f%5b%5d=%62%61%72")
237251
str.should include("%62%61%72=%62%61%7a")
238252
str.should include("%66%72%6f%62%6e%69%63%61%74%65=%74%68%65%20%66%72%6f%6f%7a%6c%65%3f")
253+
str.should include("%66%6f%73%68%69%7a%7a%6c%65=%6d%79%2f%6e%69%7a%7a%6c%65")
239254
end
240255
end
241256

0 commit comments

Comments
 (0)