13.4 示例:使用有向图识别僵尸网络

黑产团伙通过控制僵尸网络,如图13-13所示,主要达到以下几个目的:

·发送广告邮件;

·发起DDoS攻击;

·发起恶意广告点击展现请求;

·全网扫描漏洞并自动化渗透具有漏洞的主机,不断扩充肉鸡的规模。

黑产通常会对整个僵尸网络发布相同的控制指令,所以通过统计一段时间内攻击源IP和被攻击者域名之间的关联关系,可以初步确定哪些IP可能是被同一个黑产团体控制,如图13-14所示。

图13-13 黑产控制僵尸网络发起攻击示意图

图13-14 IP与被攻击域名处理流程图

完整演示代码请见本书GitHub上的13-4.py。

1.数据整理

获取开源攻击数据网站http://www.secrepo.com/ 上的数据并整理成训练集合,格式如下:


97.74.144.16* *nggui.cn
97.74.144.16* *lfinancetips.*
97.74.144.16* *zc.*
97.74.237.19* *000.*
98.150.210.24* *qi-steel-shot.*
98.21.4.24* *dapower.*

其中IP地址和域名做了脱敏处理。

脱敏函数实现为:


with open(filename) as f:
    for line in f:
        line=line.strip('\n')
        ip,domain=line.split()
        ip=re.sub(r'\d$', '*', ip)
        domain= re.sub(r'\w{3}$', '*', domain)
        domain = re.sub(r'^\w{3}', '*', domain)
        print "%s %s" % (ip,domain)

2.数据导入

逐行读取攻击数据,按照攻击源IP建立hash表,hash表的键值为被攻击的域名:


with open(filename) as f:
    for line in f:
        (ip,domain)=line.split(" ")
        if not ip=="0.0.0.0":
            if not iplist.has_key(ip):
                iplist[ip]={}
            iplist[ip][domain]=1

定义阈值R,攻击的域名超过R的IP才列入统计范围:


for ip in iplist.keys():
    if len(iplist[ip]) >= R:
        goodiplist[ip]=1

定义计算jarccard系数的函数,作为衡量两个IP攻击集合相似度的方式。所谓jarccard系数,指的是两个集合交集除以并集的比值。定义阈值N,当两个IP攻击的域名jarccard大于等于N时才列入统计范围:


#jarccard系数
def get_len(d1,d2):
    ds1=set()
    for d in d1.keys():
        ds1.add(d)
    ds2=set()
    for d in d2.keys():
        ds2.add(d)
    return len(ds1&ds2)/len(ds1|ds2)

满足阈值的IP导入图数据库:


for ip1 in iplist.keys():
    for ip2 in iplist.keys():
        if not ip1 == ip2 :
            weight=get_len(iplist[ip1],iplist[ip2])
            if (weight >= N) and (ip1 in goodiplist.keys()) and (ip2 in goodiplist.keys()):
                #点不存在会自动添加
                G.add_edge(ip1,ip2,weight=weight)

3.查询分析

定于阈值M,当同一团伙的IP大于等于M时才显示结果:


n_sub_graphs=nx.number_connected_components(G)
sub_graphs=nx.connected_component_subgraphs(G)
for i,sub_graph in enumerate(sub_graphs):
    n_nodes=len(sub_graph.nodes())
    if n_nodes >= M:
        print("Subgraph {0} has {1} nodes {2}".format(i,n_nodes,sub_graph.nodes()))

定义全局阈值,包括相似度、黑客团伙IP最小个数等:


#相似度
N=0.5
#黑客团伙IP最少个数
M=3
#黑客IP攻击目标最小个数
R=2

结果举例为:


Subgraph 2 has 20 nodes ['58.219.226.23*', '58.208.34.6*', '58.255.121.17*', '60.220.65.4*', '61.188.148.12*', '59.56.44.*', '58.241.12.14*', '58.255.125.22*', '60.161.88.13*', '59.55.101.24*', '59.63.58.*', '60.168.24.11*', '60.206.64.11*', '59.59.165.22*', '58.209.126.20*', '58.52.199.*', '61.180.116.22*', '59.56.126.3*', '61.154.37.20*', '60.186.111.3*']
Subgraph 3 has 3 nodes ['58.49.86.23*', '60.22.103.2*', '59.53.67.20*']
Subgraph 5 has 5 nodes ['58.217.185.12*', '59.63.28.17*', '59.47.7.11*', '59.47.7.12*', '59.63.248.4*']

可视化聚类结果如图13-15所示。

图13-15 僵尸网络聚类效果图