以下方法用于根据用户参数/选择下载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
方法?
答案 0 :(得分:1)
您的#1选项,因为评论暗示完全禁止用户与之交互
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
不知道您的语言文件是如何实现的,您可能需要使用下划线以外的字符_
替换。
为了提供额外的预防措施,您还可以预先检查目录以查看该文件是否存在,从而阻止了该目录 路径遍历攻击。像这样:
def valid_path?(filename)
Dir["#{Rails.root}/config/locales/*"].include?("#{Rails.root}/config/locales/#{filename}")
end
此处的好处是您明确声明该文件必须存在于config/locales
目录中
在你服务之前。如果攻击者尝试进行目录遍历攻击,则此函数将返回false。