如何安全地下载文件
How to securely download files
以下方法用于根据用户 param/selection.
下载 YAML 文件
这肯定不安全,因为我可以下载层次结构中的其他 YAML 文件。
def download
language_code = params[:code]
send_file(
"#{Rails.root}/config/locales/#{language_code}.yml",
filename: "#{language_code}.yml",
type: "application/yml"
)
end
我无法控制 params[:code]
,它本质上是动态的。
如何保护此处易受攻击的 download
方法?
正如评论所暗示的那样,您的第一选择是完全 dis-allow 用户与
language_code
字符串。评论中有许多建议的选项:受限
列表、数据库实现等
另一种选择(尽管考虑到您的限制,这可能无效)是进行长度检查:language_code.length <= 4
。根据 wikipedia's list of language codes.
,这假设您的语言代码不超过 4 个字符
作为最后的手段你也可以清理用户输入并清理它,这样文件路径就不能
操纵。 I've written a post about file sanitization functions here。您有两个选择:
- 白名单,只接受一小部分字符:
A-Z, a-z, 0-9
- 黑名单并剔除危险字符:
/ \ ? % * : | " < > . (and space)
在您的情况下(我假设您可以完全控制 config/locals
)我将列入白名单。白名单功能是
易于创建:
def sanitize(file_name)
# Remove any character that aren't 0-9, A-Z, or a-z
filename.gsub(/[^0-9A-Z]/i, '_')
end
不知道您的语言文件是如何实现的,您可能需要使用下划线以外的字符 _
用于更换。
为了额外预防,您还可以 pre-check 目录查看文件是否存在,这将防止
路径遍历攻击。像这样:
def valid_path?(filename)
Dir["#{Rails.root}/config/locales/*"].include?("#{Rails.root}/config/locales/#{filename}")
end
这里的好处是您明确声明该文件必须存在于 config/locales
目录中
在你上菜之前。如果攻击者尝试目录遍历攻击,此函数将 return false。
以下方法用于根据用户 param/selection.
下载 YAML 文件这肯定不安全,因为我可以下载层次结构中的其他 YAML 文件。
def download
language_code = params[:code]
send_file(
"#{Rails.root}/config/locales/#{language_code}.yml",
filename: "#{language_code}.yml",
type: "application/yml"
)
end
我无法控制 params[:code]
,它本质上是动态的。
如何保护此处易受攻击的 download
方法?
正如评论所暗示的那样,您的第一选择是完全 dis-allow 用户与
language_code
字符串。评论中有许多建议的选项:受限
列表、数据库实现等
另一种选择(尽管考虑到您的限制,这可能无效)是进行长度检查:language_code.length <= 4
。根据 wikipedia's list of language codes.
作为最后的手段你也可以清理用户输入并清理它,这样文件路径就不能 操纵。 I've written a post about file sanitization functions here。您有两个选择:
- 白名单,只接受一小部分字符:
A-Z, a-z, 0-9
- 黑名单并剔除危险字符:
/ \ ? % * : | " < > . (and space)
在您的情况下(我假设您可以完全控制 config/locals
)我将列入白名单。白名单功能是
易于创建:
def sanitize(file_name)
# Remove any character that aren't 0-9, A-Z, or a-z
filename.gsub(/[^0-9A-Z]/i, '_')
end
不知道您的语言文件是如何实现的,您可能需要使用下划线以外的字符 _
用于更换。
为了额外预防,您还可以 pre-check 目录查看文件是否存在,这将防止 路径遍历攻击。像这样:
def valid_path?(filename)
Dir["#{Rails.root}/config/locales/*"].include?("#{Rails.root}/config/locales/#{filename}")
end
这里的好处是您明确声明该文件必须存在于 config/locales
目录中
在你上菜之前。如果攻击者尝试目录遍历攻击,此函数将 return false。