參考資料: ZoomEye API: https://www.zoomeye.org/api/doc Weblogic-Weakpassword-Scnner: https://github.com/dc3l1ne/Weblogic-Weakpassword-Scnner Python 調用 ZoomEye API 批量獲取目標網站IP: http://www.cnblogs.com/anka9080/p/ZoomEyeAPI.html
本文參考以上資料,經過部分修改,以便於自己使用,現將其分享出來。為了表示對原作者敬意,特將其工作列在文首。
本文涉及兩方面的工作,從ZoomEye API獲取到想要的IP列表,再用Weblogic 弱口令掃描器對得到的地址進行掃描。
Github傳送: ZoomEye
一、從ZoomEye API獲取IP地址列表
"首先要說明的是,使用ZoomEye API需要先注冊賬號,使用方法是先提交賬戶,密碼獲得一個唯一的訪問令牌(access_token)"
"然后每次調用 API 的時候在 HTTP 的 Headers 里加上格式化后的 access_token 就可以使用了"
使用python腳本從ZoomEye API 獲取到的IP地址數量是有限的,但由於其數量巨大,我們可以得到的便利也是巨大的。且ZoomEye 的爬蟲是一直在運行的,搜索得到的結果也是變動的,因此我們可以多注冊幾個賬號...
下面是從ZoomEye API 獲取IP地址的Demo
# coding: utf-8 # author : evilclay # datetime: 20160330 # http://www.cnblogs.com/anka9080/p/ZoomEyeAPI.html # Modified by : starnight_cyber@foxmail.com # Time : 2016.12.1 import os import requests import json import time access_token = '' ip_list = [] def login(): """ 輸入用戶名密碼 進行登錄操作 :return: 訪問口令 access_token """ user = raw_input('[-] input : username :') passwd = raw_input('[-] input : password :') data = { 'username': user, 'password': passwd } # dumps 將 python 對象轉換成 json 字符串 data_encoded = json.dumps(data) try: r = requests.post(url='https://api.zoomeye.org/user/login', data=data_encoded) # loads() 將 json 字符串轉換成 python 對象 r_decoded = json.loads(r.text) global access_token # 獲取到賬戶的access_token access_token = r_decoded['access_token'] except Exception, e: print '[-] info : username or password is wrong, please try again ' exit() def saveStrToFile(file, str): """ 將access_token寫如文件中 :return: """ with open(file, 'w') as output: output.write(str) def saveListToFiles(ip_list): ''' :param ip_list: 使用ZoomEye接口獲得的ip列表 : 會寫入到多個文件,保存格式不同,僅ip和 http://ip/console/login/LoginForm.jsp : 如http://162.105.205.162/console/login/LoginForm.jsp :return: ''' # 以當前運行腳本的時間創建文件,這樣就可以保證腳本運行時創建的文件不會重名 xtime = time.strftime("%Y-%m-%d[%H.%M.%S]") ip_list_file = open(xtime + 'ip.txt', 'w') url_list_file = open(xtime + 'url.txt', 'w') # 將list以一定格式寫入到文件中 for line in ip_list: # ip格式 ip_list_file.write(line + '\n') # weblogic 后台登錄地址格式 url_list_file.write('http://' + line + '/console/login/LoginForm.jsp' + '\n') # 關閉文件 ip_list_file.close() url_list_file.close() def apiTest(): """ 進行 api 使用測試 :return: """ page = 1 # 表示第幾頁 num = 1 # 頁數 index = 1 # 循環下標 global access_token with open('access_token.txt', 'r') as input: access_token = input.read() # 將 token 格式化並添加到 HTTP Header 中 headers = { 'Authorization': 'JWT ' + access_token, } # 要搜索的字符串 # query = 'port:80 weblogic country:China' query = raw_input('[*] please input search string : ') # 設置獲取結果的起始頁面,對於量比較大的時候比較有用 page = int(raw_input('[*] please input start page : ')) # 設置獲取的結果頁數 num = int(raw_input('[*] please input number of pages you want to retrieve : ')) while (True): try: # 將查詢字符串和頁數結合在一起構造URL searchurl = 'https://api.zoomeye.org/host/search?query=' + query + '&page=' + str(page) r = requests.get(url=searchurl, headers=headers) print searchurl r_decoded = json.loads(r.text) # print r_decoded # print r_decoded['total'] for x in r_decoded['matches']: print x['ip'] ip_list.append(x['ip']) print '[-] info : count ' + str(index * 10) except Exception, e: # 若搜索請求超過 API 允許的最大條目限制 或者 全部搜索結束,則終止請求 if str(e.message) == 'matches': print '[-] info : account was break, excceeding the max limitations' break else: print '[-] info : ' + str(e.message) else: # 判斷頁數 if index == num: break page += 1 # 用於獲取下一頁的結果 index += 1 # 輸出提示 print 'page : ' + str(page) + ' - ' + 'index : ' + str(index) def main(): # 訪問口令文件不存在則進行登錄操作 if not os.path.isfile('access_token.txt'): print '[-] info : access_token file is not exist, please login' login() # 保存access_token到文件中 saveStrToFile('access_token.txt', access_token) # 從ZoomEye API 獲取IP地址列表 apiTest() # 將結果保存到文件中 saveListToFiles(ip_list) if __name__ == '__main__': main()
運行:
運行結束后保存了以時間命名的文件
獲取到的IP列表
Weblogic 后台登錄地址形式:
這樣,我們的第一步就完成了,得到了我們想要的IP地址列表。
二、使用Weblogic-Weakpassword-Scnner 掃描weblogic 后台弱口令
得到有效的weblogic后台登錄地址:
將第一步得到的url格式的文件,重命名為url.txt, 運行Weblogic-Weakpassword-Scnner 中的spider.py 腳本, 清除無效的url,得到u.txt, 為有效的weblogic 后台登錄地址,可以用來暴力破解。
python spider.py
暴力破解:
運行Weblogic-Weakpassword-Scnner 中的main.py 腳本, 進行暴力破解。
python main.py 100
命名為*.txt的文件中,保存了weblogic的后台登錄地址,及用戶和密碼。
得到IP地址后,不僅僅是可以用來掃描Weblogic后台弱口令,接下來...
最后,附上Top5的弱口令:
weblogic
weblogic123
12345678
11111111
weblogic123456
三、ZoomEye Version 2
在處理上做了些小的修改,之前端口處理有點問題,現已修正...
# -*- coding: utf-8 -*- # author : evilclay # datetime: 20160330 # http://www.cnblogs.com/anka9080/p/ZoomEyeAPI.html # Modified by : starnight_cyber@foxmail.com # Time : 2016.12.8 import os import requests import json import time access_token = '' ip_list = [] ip_port_list = [] def login(): """ 輸入用戶名密碼 進行登錄操作 :return: 訪問口令 access_token """ user = raw_input('[-] input : username :') passwd = raw_input('[-] input : password :') data = { 'username': user, 'password': passwd } # dumps 將 python 對象轉換成 json 字符串 data_encoded = json.dumps(data) try: r = requests.post(url='https://api.zoomeye.org/user/login', data=data_encoded) # loads() 將 json 字符串轉換成 python 對象 r_decoded = json.loads(r.text) global access_token # 獲取到賬戶的access_token access_token = r_decoded['access_token'] except Exception, e: print '[-] info : username or password is wrong, please try again ' exit() def saveStrToFile(file, str): """ 將access_token寫如文件中 :return: """ with open(file, 'w') as output: output.write(str) def saveListToFiles(ip_list): ''' :param ip_list: 使用ZoomEye接口獲得的ip列表 : 會寫入到多個文件,保存格式不同,僅ip和 http://ip/console/login/LoginForm.jsp : 如http://162.105.205.162/console/login/LoginForm.jsp :return: ''' # 以當前運行腳本的時間創建文件,這樣就可以保證腳本運行時創建的文件不會重名 xtime = time.strftime("%Y-%m-%d[%H.%M.%S]") ip_list_file = open(xtime + 'ip.txt', 'w') ip_port_list_file = open(xtime + 'ip:port.txt', 'w') # 將ip以一定格式寫入到文件中 for line in ip_list: ip_list_file.write(line + '\n') # 將ip,port寫入文件中 for line in ip_port_list: ip_port_list_file.write(line + '\n') # 關閉文件 ip_list_file.close() ip_port_list_file.close() def apiTest(): """ 進行 api 使用測試 :return: """ page = 1 # 表示第幾頁 num = 1 # 頁數 index = 1 # 循環下標 global access_token with open('access_token.txt', 'r') as input: access_token = input.read() # 將 token 格式化並添加到 HTTP Header 中 headers = { 'Authorization': 'JWT ' + access_token, } # 要搜索的字符串 # query = 'port:80 weblogic country:China' query = raw_input('[*] please input search string : ') # 設置獲取結果的起始頁面,對於量比較大的時候比較有用 page = int(raw_input('[*] please input start page : ')) # 設置獲取的結果頁數 num = int(raw_input('[*] please input number of pages you want to retrieve : ')) while (True): try: # 將查詢字符串和頁數結合在一起構造URL searchurl = 'https://api.zoomeye.org/host/search?query=' + query + '&page=' + str(page) r = requests.get(url=searchurl, headers=headers) print searchurl r_decoded = json.loads(r.text) # print r_decoded # print r_decoded['total'] for x in r_decoded['matches']: print x['ip'], x['portinfo']['port'] ip_list.append(x['ip']) ip_port_list.append(x['ip'] + ', ' + str(x['portinfo']['port'])) print '[-] info : count ' + str(index * 10) except Exception, e: # 若搜索請求超過 API 允許的最大條目限制 或者 全部搜索結束,則終止請求 if str(e.message) == 'matches': print '[-] info : account was break, excceeding the max limitations' break else: print '[-] info : ' + str(e.message) finally: # 判斷頁數 if index == num: break page += 1 # 用於獲取下一頁的結果 index += 1 # 輸出提示 print 'page : ' + str(page) + ' - ' + 'index : ' + str(index) def main(): # 訪問口令文件不存在則進行登錄操作 if not os.path.isfile('access_token.txt'): print '[-] info : access_token file is not exist, please login' login() # 保存access_token到文件中 saveStrToFile('access_token.txt', access_token) # 從ZoomEye API 獲取IP地址列表 apiTest() # 將結果保存到文件中 saveListToFiles(ip_list) if __name__ == '__main__': main()
三、ZoomEye Version 3 [2018.1.8更新]
直接貼代碼吧:
#!/usr/bin/python # encoding: utf-8 import requests as req import json import optparse import time import sys import os class ZoomEye: def __init__(self): self.initParameter() username = 'zl15@foxmail.com' password = 'liu120808' self.account = {'username': username,'password': password} self.headers = {'Authorization': 'JWT ' + self.getToken()} def search(self): self.isFIle(self.options.file) queryType = self.options.type queryStr = self.options.query try: result = req.get('https://api.zoomeye.org/'+ queryType + '/search?query=' + queryStr + '&page=1', \ headers=self.headers, timeout = 15) except: print "Error exit..." sys.exit() if result.status_code != 200: print "error: ", print result.content print "exit..." sys.exit() resultDict = json.loads(result.content) # print result.content #獲取第一頁的所有結果 pages = self.getPageNum(int(resultDict['total'])) print 'There are %d pages to fetch' % pages userAgent = {'user-agent': 'Mozilla/5.0(iPad; U; CPU OS 3_2_1 like Mac OS X; en-us)AppleWebKit/\ 531.21.10(KHTML, like Gecko)Mobile/7B405'} self.headers['user-agent'] = userAgent start = time.time() starPage = 0 for i in xrange(starPage, pages, 1): targetList = [] try: result = req.get('https://api.zoomeye.org/' + queryType +'/search?query='+ queryStr +'&page='+\ str(i+1), headers=self.headers, timeout=15) # print "Get page " + str(i+1) + " info ..." now = time.time() print '[ %d / %d ] ==> time elapse %s s ...' % (i, pages, int(now - start)) except: print "Page " + str(i) + " , Error exit..." # sys.exit() continue if result.status_code != 200: print "error: ", print result.content print "exit..." sys.exit() # print result.content #每頁的結果 self.getFileContent(targetList, result.content) self.writeTofile(self.options.file, targetList) print "The result in " + self.options.file def getFileContent(self, targetList, result): result = json.loads(result) # print result if self.options.type == 'web': for eachResult in result['matches']: # print eachResult # 獲取目標站點 targetList.append(eachResult['site']) print targetList return targetList for eachResult in result['matches']: # targetList.append(eachResult['ip'] + ':' + str(eachResult['portinfo']['port'])) ip_port = eachResult['ip'] + ':' + str(eachResult['portinfo']['port']) print ip_port targetList.append(ip_port) return targetList def getPageNum(self, total): if total == 0: print "No result, exit.." sys.exit() page = total/10 if total%10 == 0: return page return page + 1 def getToken(self): token = req.post('https://api.zoomeye.org/user/login',json.dumps(self.account)).content print token return json.loads(token)['access_token'] def writeTofile(self, filename, targetList): with open(filename, 'a') as f: for eachTarget in targetList: f.write(eachTarget + "\n") time.sleep(0.2) def isFIle(self,filename): if not os.path.isfile(filename): return print 'result file is exists, continue ?', choice = raw_input("(y/n): ") if choice.lower() == 'n': print 'Please rename filename, exit ...' sys.exit() if choice.lower() == 'y': return else: return self.isFIle(filename) def initParameter(self): usage = ''' _____ _____ |__ /___ ___ _ __ ___ | ____| _ ___ / // _ \ / _ \| '_ ` _ \| _|| | | |/ _ / /| (_) | (_) | | | | | | |__| |_| | __/ /____\___/ \___/|_| |_| |_|_____\__, |\___| |___/ ''' parser = optparse.OptionParser(usage = usage) parser.add_option("-t", "--type", default='web', help='''Search type like host ,web (e.g. "https://api.zoomeye.org/host/\ search?query=port:21")''') parser.add_option("-q", "--query", help="What you search is your need") parser.add_option("-f", "--file", help="The file will save result's IP or domain") (self.options, args) = parser.parse_args() if self.options.query == None or self.options.file == None: print parser.print_help() print "Please Completed parameters, you can show -h to get help" sys.exit() else: print usage if __name__ == '__main__': ZE = ZoomEye() try: ZE.search() except KeyboardInterrupt: print "Ctrl + C exit..." sys.exit()