Ruby on Rails中如何限制Liquid模板render/include的文件访问范围?
如何在Ruby on Rails中限制Liquid主题仅访问自身目录及子目录
完全可以实现这个限制,核心思路是通过自定义Liquid文件系统拦截并校验模板的路径访问请求,确保只能读取当前主题目录及其子目录内的文件。
1. 实现自定义受限文件系统
继承Liquid自带的Liquid::LocalFileSystem,重写full_path方法,在返回文件路径前做合法性校验:
class RestrictedFileSystem < Liquid::LocalFileSystem def initialize(root) # 确保根目录是绝对路径,避免相对路径歧义 @root = File.expand_path(root) end def full_path(template_path) # 解析模板路径为绝对路径 full_path = super(template_path) real_path = File.realpath(full_path) # 检查解析后的路径是否在主题根目录范围内 unless real_path.start_with?(@root) raise Liquid::FileSystemError, "无权访问该路径: #{template_path}" end full_path end end
这个类会在每次Liquid尝试加载render或include引用的文件时,校验目标路径是否属于当前主题的根目录,越权请求会直接抛出错误。
2. 渲染模板时使用自定义文件系统
在Rails中渲染用户上传的Liquid模板时,指定使用上面的受限文件系统:
# 假设当前主题的根目录是theme_root theme_root = Rails.root.join("themes", current_user_theme.id.to_s).to_s file_system = RestrictedFileSystem.new(theme_root) # 解析并渲染模板 template = Liquid::Template.parse(template_content, file_system: file_system) rendered_content = template.render(assigns: { ... })
3. 额外的安全加固
- 上传时校验文件路径:用户上传主题文件时,检查文件名/路径是否包含
../等相对路径跳转字符,直接拒绝这类文件。 - 禁用符号链接:确保主题目录不允许创建符号链接,或者在路径校验时用
File.realpath解析真实路径,防止通过符号链接绕过目录限制。 - 文件系统权限控制:给每个主题目录设置独立的文件权限,避免进程能跨目录读取其他主题的文件。
内容的提问来源于stack exchange,提问作者Jake McAllister
相关产品推荐
相关产品推荐

