Skip to content

Commit 08ef21a

Browse files
jfirebaughjosh
authored andcommitted
Check for directory traversal after unescaping
The `forbidden_request?` check could be trivially bypassed by percent encoding .. as %2e%2e. After auditing Sprockets and Hike and fuzzing a simple server, I don't believe this is exploitable. However, better safe than sorry/defense in depth/etc.
1 parent 2997be9 commit 08ef21a

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

lib/sprockets/server.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,6 @@ def call(env)
2525

2626
msg = "Served asset #{env['PATH_INFO']} -"
2727

28-
# URLs containing a `".."` are rejected for security reasons.
29-
if forbidden_request?(env)
30-
return forbidden_response
31-
end
32-
3328
# Mark session as "skipped" so no `Set-Cookie` header is set
3429
env['rack.session.options'] ||= {}
3530
env['rack.session.options'][:defer] = true
@@ -38,6 +33,11 @@ def call(env)
3833
# Extract the path from everything after the leading slash
3934
path = unescape(env['PATH_INFO'].to_s.sub(/^\//, ''))
4035

36+
# URLs containing a `".."` are rejected for security reasons.
37+
if forbidden_request?(path)
38+
return forbidden_response
39+
end
40+
4141
# Strip fingerprint
4242
if fingerprint = path_fingerprint(path)
4343
path = path.sub("-#{fingerprint}", '')
@@ -85,12 +85,12 @@ def call(env)
8585
end
8686

8787
private
88-
def forbidden_request?(env)
88+
def forbidden_request?(path)
8989
# Prevent access to files elsewhere on the file system
9090
#
9191
# http://example.org/assets/../../../etc/passwd
9292
#
93-
env["PATH_INFO"].include?("..")
93+
path.include?("..")
9494
end
9595

9696
# Returns a 403 Forbidden response tuple

test/test_server.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ def app
185185
test "illegal require outside load path" do
186186
get "/assets/../config/passwd"
187187
assert_equal 403, last_response.status
188+
189+
get "/assets/%2e%2e/config/passwd"
190+
assert_equal 403, last_response.status
188191
end
189192

190193
test "add new source to tree" do

0 commit comments

Comments
 (0)