参考资料:
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 : [email protected]
# 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 : [email protected]
# 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 = '[email protected]'
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()