资源占用率监测方法

CPU

TOP,地球人都知道
[root@~]# top
top – 14:50:56 up 22:31, 7 users, load average: 45.76, 33.64, 15.93
Tasks: 622 total, 1 running, 621 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.6 us, 0.2 sy, 0.0 ni, 93.9 id, 2.4 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 13198510+total, 56110604 free, 41665376 used, 34209120 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 89487664 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2566 root 20 0 629720 561460 70156 D 67.2 0.4 0:19.35 clang
3197 root 20 0 144644 69224 42192 D 15.6 0.1 0:00.66 clang
3057 root 20 0 308968 234124 53692 D 12.6 0.2 0:06.64 clang

磁盘IO

[root@~]# iostat -x

Linux 3.10.0-514.el7.x86_64 (bsabj36) 02/10/2020 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle 11.12 0.00 2.45 0.70 0.00 85.73
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %utilsda 0.01 0.22 8.82 7.20 1072.97 386.24 182.17 0.17 10.34 2.75 19.65 9.98 15.99sdb 0.02 0.57 9.43 8.03 1064.23 325.95 159.18 0.20 11.41 22.09 29.59 11.08 19.35sdc 0.00 0.17 9.58 1.88 955.05 222.93 205.64 0.01 0.51 12.96 68.48 8.94 10.24sdd 0.05 0.56 1.97 3.99 42.70 73.31 38.93 0.14 22.93 5.20 31.71 3.53 2.10dm-0 0.00 0.00 1.34 3.35 30.00 29.12 25.22 0.11 22.51 5.16 29.43 3.13 1.47dm-1 0.00 0.00 0.06 0.16 0.23 0.64 8.00 0.11 484.35 7.16 652.83 0.19 0.00dm-2 0.00 0.00 0.64 0.77 12.43 43.54 79.25 0.05 36.75 5.56 62.72 5.55 0.78
看来rkB/s wkB/s比较高,可能存在io竞争看看哪些进程io占用率高?iotop -oPTotal DISK READ : 3.37 M/s | Total DISK WRITE : 1689.08 K/sActual DISK READ: 3.37 M/s | Actual DISK WRITE: 15.33 M/s PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND 991980 be/4 qemu 3.37 M/s 0.00 B/s 0.00 % 9.29 % qemu-kvm -name WANNA_defend_win7_update_BJOBM1 -S -machine~alloon-pci,id=balloon0,bus=pci.0,addr=0x7 -msg timestamp=on 845146 be/4 qemu 0.00 B/s 1520.52 K/s 0.00 % 3.57 % qemu-kvm -name WANNA_defend_win7_update_GDSZ1 -S -machine ~alloon-pci,id=balloon0,bus=pci.0,addr=0x7 -msg timestamp=on 232279 be/4 qemu 0.00 B/s 158.02 K/s 0.00 % 0.73 % qemu-kvm -name MNG_ESPC -S -machine pc-i440fx-rhel7.0.0,ac~alloon-pci,id=balloon0,bus=pci.0,addr=0x8 -msg timestamp=on 860489 be/4 qemu 0.00 B/s 0.00 B/s 0.00 % 0.01 % qemu-kvm -name WANNA_SECURITY_RSAS_off -S -machine pc-i440~alloon-pci,id=balloon0,bus=pci.0,addr=0x7 -msg timestamp=on 993858 be/4 bsaworke 0.00 B/s 10.53 K/s 0.00 % 0.00 % java -Dproc_nodemanager -Xmx1000m -Dhadoop.log.dir=/home/b~rties org.apache.hadoop.yarn.server.nodemanager.NodeManager

网络IO

[root@~]# iftop -n -i eth0
-n表示不解析域名,-i表示对应网络接口

                            191Mb                                    381Mb                                    572Mb                                    763Mb                               954Mb
└───────────────────────────────────────┴────────────────────────────────────────┴────────────────────────────────────────┴────────────────────────────────────────┴────────────────────────────────────────
192.168.19.14 => 101.6.8.193 42.5Kb 34.5Kb 34.5Kb
<= 2.75Mb 2.45Mb 2.45Mb 192.168.19.14 => 10.63.1.90

RSAC 2020 | 云安全观察

RSAC 2020如期在旧金山举办,还是2月,还是在Moscone Center,只是没有了诸多中国同行的参加,也没有了百度游艇。很可惜我没有亲身参加本届RSAC,(也不知道市场街梅西百货外面的市政有没有弄好,这也似乎成为一个旧金山新景点了,囧),因而文中不会出现身临其境的感受,所以更多的谈的是从会议session中观看和阅读的感觉。

时间有限,还没来得及看所有的胶片,不过从云安全高峰论坛(CSA Summit)、云安全和虚拟化(Cloud Security & Virtualization)和DevSecOps 和应用安全(DevSecOps & Application Security)几个Track的内容中,我有以下几个观点,仅供探讨。

观点1 :云计算已经成为了互联一切的基础设施,云安全已经成为了纯安全问题

    第一天早上CSA高峰论坛[1]、第一天下午创新沙盒,第二天上午Keynote乎已经成为RSA的近几年标配,也是三大看点。CSA高峰论坛作为先发阵容中的先发队员,其影响力可见一斑。不过很有意思的是,每年CSA的影响力是越来越大,各种标准、工作组和培训,应该都让它挣得钵满盆满,覆盖范围也从最初的云计算安全扩展到物联网安全、软件定义边界等交叉领域,可见,云计算已经成为互联一切的基础设施,云安全联盟的触角已然不满足狭义的公有云和私有云计算安全领域了。

可以说,CSA和安全厂商和已经成为了合作伙伴的关系,在共同的研究点和产品方向互为背书,互为推广。例如,2019年的高峰论坛上几家做SDWAN安全的厂商在大谈软件定义边界,也为它在2013年提出的SDP捧场。今年OneTrust的VP Kevin Kiley在讲供应链安全,其中就是对供应链中的第三方厂商的安全进行评估,也就是Gartner近两年提的IRM(Integrated Risk Management)中的VRM(Vendor Risk Management),为什么OneTrust会在云安全的会场谈这个话题呢?因为云计算一个很大的挑战是用户对云服务商的信任,CSA在前几年提出了Consensus Assessments Initiative (CAI)[2],即对用户让云服务商就Cloud Controls Matrix (CCM)标准填写评估,从而得到第三方云基础设施的可靠度。显然OneTrust的方案也是契合该方向的。可以说云安全联盟在商业运作上非常成功,通过与厂商的合作,与客户的培训,形成了云安全领域很好的生态体系,共同推进云计算安全的发展。

另一方面,云计算既然成为了普适的基础设施,提供了计算、存储、网络、函数等服务,那么客户就会将云计算作为一种内生资源,嵌入在他的基础设施中,最终形成统一的IT架构,近两年多云(Multi-Cloud)、混合云(Hybrid Cloud)、SDWAN就比较热,在这样的IT环境中提供安全产品、安全服务,那前几年的云安全产品或方案必然要融入传统环境,提供统一的功能。可以预见,在未来几年,安全厂商的安全方案不会显示地带有“云安全”的定语,因为这就是默认选项,即云安全已经成为纯安全问题。一个证据是今年CSA高峰论坛的话题则覆盖了网络检测响应(NDR)、供应链安全、数据泄露响应、CISO视角等各安全细分领域的话题,但上午的session标题中都没有出现cloud一词。当然细看内容,其实云安全的理念已经融入其中,甚至可以说,大家无论谈安全理念,或是安全技术、安全方案,都是面向云计算环境。例如Extrahop Networks的COO Raja Mukerji在谈检测响应,主张将NDR、EDR、SIEM组合,构建面向公有云的检测响应机制,实现云原生的安全。

当然,虽然传统安全问题会发生在云计算场景中,但云环境也有其独特的地方,所以在云安全和虚拟化(Cloud Security & Virtualization)session中,如子域名接管[3]的原因在于一些子域名是租用的,管理不当容易被恶意租户发现并接管;又如好几个胶片谈到暴露面检查,就是Gartner说的CSPM(Cloud Security Posture Management),本质来看就是传统的服务(端口)暴露和弱口令(正如现在很多互联网上脆弱的物联网设备一样),转变成了公有云上的存储资源暴露和弱口令。所以这些本质来说是传统安全问题,但公有云计算环境下有新的特点,值的我们重视。

观点2: 云安全更加实战,已从纯合规性要求转向攻防要求

从前几年AWS在各个大会上有独立session做AWS安全入门培训,彼时大部分的客户对公有云还不太熟悉,一部分是因为公有云服务太多、配置太复杂了,另一部分原因是,对于攻击者而言也比较新,相对而言,IaaS和PaaS的云安全还是以合规性要求居多。

而如今,云计算对于攻击者而言,开放API、灵活的资源编排,俨然成为了另一个维度好用的攻击资源;另外,云用户错误配置,也给觊觎云上敏感数据的攻击者可乘之机。所以无论是数据面安全CWPP(Cloud Workload Protection Platform),还是管理面安全CSPM,各类云安全厂商也兴起,从本届RSAC云安全session中的内容来看,跟往届相比更加实战。

例如前面提到的子域名接管攻击,在两个胶片[3,4]中提到,其中[3]是星巴克安全团队作为受害者出来讲,更令人信服。而[4]则更全,介绍了十种面向云平台的攻击链,其中侦查阶段大部分是CSPM关注的暴露token、bucket等,另一部分则是恶意内部攻击者,即前面提的供应链覆盖的内容。

当然只有用户和安全厂商显然不全,session中还有一个是来自AWS的Ben Potter,职位是the security lead for Well-Architected,属于架构师,介绍了AWS的架构(Well-Architected)中的安全设计,可以看出,AWS的安全体系已经覆盖了事前管理、准备,事中检测和响应,事后恢复的闭环,其中还提到使用了金丝雀账户,部署了一些诱饵,这说明云厂商的安全团队已经不止关注传统的清理(hygiene)和被动防护的工作,也开始做一些主动防御的工作了。

总体而言,检测响应已经从传统企业环境转向云计算环境,如[5,6]都介绍了云服务商和用户如何做检测响应的经验,[6]则是介绍了在线交易的领域如何实现身份和访问控制(SSO、MFA,RBAC),数据安全(加密、密钥管理),应用安全(API安全,session管理),日志和监控(分析,日志集中),事件响应(告警、IR剧本),在云计算环境中必须要引入自动化和xDR才能满足规模化的要求。

作为防守方,一家小公司IMG Security的咨询师,[9]介绍了云环境下的威胁狩猎,案例非常具体,涉及到渗透测试和事件响应

观点3:云原生进入主流,从只谈容器安全、Kubernetes安全到云原生安全,代码、应用

在2019年的RSAC的早期厂商展览,已经有一两家做Kubernetes和容器安全了,而今年的云安全和DevSecOps session中,有两篇Kubernetes攻防的胶片,还有一篇介绍云原生安全和Serverless安全,说明这话题已经被主流观众所关注,而且关注点不断向上,从容器到编排,再到无服务和云原生安全。

例如,SANS的培训师在[7]hack了AWS的lamda函数,通过反向代理获得无服务的操作系统细节,见下图。

图片包含 屏幕截图

描述已自动生成

然后分析了如何从外部获取凭证进入容器,进而收集容器内部更多凭证,横向移动,建议将函数放在vpc里面,减少暴露面。

在[8]中,讲者是一家安全资讯公司inguardians的CTO,先介绍了Kubernetes下的攻击思路,在master节点攻击api server等几个核心组件,在slave攻击kubelet和运行时容器,给了一个自己开源Kubernetes的渗透测试工具(https://github.com/inguardians/peirates),该工具主页demo介绍了获得暴露的secret,然后从api-server创建账号,新建容器,并得到反连shell。另外给了一个测试训练环境,供学习 https://www.bustakube.com/

从以上几个胶片的内容可以看出,今年云计算安全很明显的,安全倾向于攻防细节,环境则侧重于编排系统之上的部分。

观点4:DevSecOps成为热点,DevSecOps和云原生安全不断融合,创造了一些共同的话题

敏捷开发DevOps似乎与云计算是两个维度,但“容器-编排”可以支撑敏捷CI/CD的开发模式,而“编排-无服务”的云原生运营模式可以支撑大规模弹性的应用场景,这套技术栈似乎为全世界绝大多数的开发者所青睐,而容器-Kubernetes-Serverless又是云原生的底层技术,所以随着敏捷开发本身的安全机制(DevSecOps)不断发展,两种安全视角的融合不断加深。今年的云安全session中有一些问题的起源,如代码中的硬编码token、代码仓库的暴露凭证,都是安全敏捷开发需要关心的内容,而今年的DevSecOps 和应用安全(DevSecOps & Application Security)session中,则有一篇[10]是专门介绍Kubernetes的访问控制安全的。

观点5:人是对抗永远的主题,人的因素不可忽视

今年大会的主体是Human Element,不可避免地很多胶片中也出现了这个元素,大部分都是简单涉及,不过确实有两篇是专门对人的因素进行探讨。

如[11]介绍了在传统环境和云环境中不同的思路,在云环境中做安全应该与云计算的思路匹配,如安全即代码,拥抱自动化,此外要避免人为错误所造成的影响,组织红蓝对抗。而[12]是出现在敏捷开发的session中的,很有意思的讨论了工作时间、团队规模和修改他人代码频繁度等因素对代码安全性产生的影响。总之,技术、流程和人是信息安全的三个组成部分,人的因素在不断的提升。如何发挥人的主观能动性,对于提升安全防护效率至关重要。

总之,云计算已经成为了连接万物的普适的基础设施,云计算安全已经进入了下半场,如何形成统一的安全体系,如何提升云计算的真实安全水平,如何提升使用云计算的各种团队的安全能力,将是接下来云安全的发展方向。

参考链接

[1]  https://www.rsaconference.com/usa/agenda/csa-summit-privacy-and-security-in-the-cloud

[2]  https://cloudsecurityalliance.org/research/working-groups/consensus-assessments/

[3] Same Thing We Do Every Few Minutes, Pinky – Try to Take Over All Your Subdomains ,RSAC 2020

[4] Break the Top 10 Cloud Attack Killchains, RSAC 2020

[5] Using Automation for Proactive Cloud Incident Response,RSAC 2020

[6] Untangling SaaS Security in the Enterprise, RSAC 2020

[7] Defending Serverless Infrastructure in the Cloud, RSAC 2020

 [8] Kubernetes Practical Attack and Defense, RSAC 2020

[9] Cloud Threat Hunting, RSAC 2020

[10] Compromising Kubernetes Cluster by Exploiting RBAC Permissions, RSAC 2020

[11] Hacking Your Security Culture for the Cloud,RSAC 2020

[12] Which Developers and Teams Are More Likely to Write Vulnerable Software,RSAC 2020

家事一趣

早上,看到老二跟着老大进卧室,就说,“bubu,不要当姐姐跟屁虫哦”

老二说,“我才不是跟屁虫,我是前屁虫!”

小孩的注意力永远跟大人不一样…

Kubernetes离线安装

为什么要有这个项目

Kubernetes的软件源和镜像是托管在google的服务的,所以你懂的。这个项目是将google侧的东东缓存到本地,加速安装过程。

项目的地址为 https://github.com/marvelliu/kubernetes-offline-installer

安装说明

目前支持Ubuntu 18.04(其他版本需要自己下载了),因为是离线的,所以版本部署最新,可能对已有的软件要降级,可安装完再apt-get upgrade即可

确定安装kubernetes的版本

目前支持Ubuntu 18.04,默认安装的kubernetes版本为install_master/slave.sh的KUBE_VER,如果需要安装其他版本则修改$KUBE_VER,目前支持的版本见debs/images下的目录。

安装

主节点运行install_master.sh,从节点运行install_slave.sh

当主节点运行完后,会出现如下提示:

kubeadm join 192.168.19.244:6443 –token 3103e3.33cc37005f04433c \ –discovery-token-ca-cert-hash sha256:7697a85c0199533f9c891f9f2e2f92931b02d5a60ef25dfc0ad52c25f7f0f0eb

则将该命令在所有从节点运行即可。

注意事项

运行过程中会连接dl.k8s.io,事先已重定向到了127.0.0.1,出现warning不需要管

基于全局流表的流异常检测机制

一、引言

随着信息化的快速发展,攻击者越来越多地有针对性地对某些企业发动有利可图的攻击,如探查内部消息、进行破坏或窃取数据等,而单一的安全防护手段很难防范这些复杂攻击。其一,攻击者采用多种高级攻击手段,普通的检测机制不能有效及时检测到威胁;其二,通过持续渗透,攻击者获得内部资源的权限或内部用户的身份,便会绕过白名单机制。

综合而言,对抗持续高级威胁,应该采用多种防护手段,灵活地通过软件定义的应用编排和安全资源准备,发现攻击链的某一环并及时阻断。面对大型内部网络的海量数据,检测的第一步往往可以通过流量的统计信息入手,及时发现一些异常的访问模式,进而对这些异常流量进行进一步分析。近年来SDN(Software-Defined Networking,软件定义网络)技术越来越流行,SDN控制器提供了实时全局流量的视图,无疑为上述的异常流量检测提供了有力的支撑。

本文介绍了如何使用SDN技术实现全局流表,可记录和查询历史时刻内的所有的访问记录,并能防范如伪造源地址等恶意攻击。

关键字 全局流表 SDN 流异常检测

二、全局流表

全局流表(Global Flow)是指给定网络范围内的所有网络设备上的全部流量汇聚而成的流知识,通过构建全局和实时的流表,可知任意两点间数据流向和访问细节,这对先期分析异常行为有很大的帮助。

全局流表借助安全控制平台通过SDN控制器向网络设备收集流信息,并通过安全控制平台的数据服务进行存储和查询,如图1所示。软件定义安全体系已在前几期技术内刊中已有介绍,本文不做赘述。


图1 全局流表的架构图

本文讨论的场景在OpenFlow/SDN环境中,在 SDN网络中,数据包进入交换机后,按照 Flow Entry的优先级对流表中匹配域中的字段依次进行匹配,如果一个表项匹配成功,则执行相应的指令。所以交换机上的一条流表可以指示流自身信息及其下一步动作。从 SDN通过流表控制数据转发这一机制可以分析,一条流在流经交换机的过程中,在每一台交换机上控制其转发的流表中的 match 匹配字段是一定的,如果某条流的action 域中有修改该流数据包的命令时,match 中的某些字段才会发生改变,但是改变前的 match 和改变后的 match 控制的仍然属于同一条流。

全局流表的意义在于可以将整个网络中的交换机的流表融合,给定一个匹配域(如源IP->目的IP),就能找到所有存在该匹配域的交换机,并按照数据包转发顺序(上一个交换机的output端口与下一个交换机的inport端口可匹配),形成一个路径,可真实还原某个数据包在网络中完整的转发路径。这条路径一方面包含了访问关系的两个端点,记录了所有时刻所有访问记录的详细信息,建立了详细的流数据库;另一方面还包含了访问关系在转发平面上的每个中间点,可避免恶意攻击者伪造地址、攻破网络控制器操纵转发路径等攻击。

2.1. 全局的流量信息融合

全局流表算法的主要思想是首先根据弱节点覆盖求网络最小有效测量集,需满足该有效测量集(弱节点集合)收集的流量在一定误差范围内代表全网流量,然后定时收集弱节点上的流表,经过流分类整合步骤,整合出每条流流经的弱节点集合。由于只获得了每条流流经的弱节点,为部分节点,所以最后通过路径还原算法,将流的路径由弱节点还原至整个网络路径。全局流算法流程如图2所示。


图2 基本算法流程图

为了减少收集流表对网络性能的影响,测量节点应选择的越少越好,因此应求出一个最小的有效测量集,通过该集合收集到网络的全局流量,并可以计算出每一条流的路径。大量实验证明交换机或者路由器具有流量守恒定律,利用这一特性可以有效的减少测量节点,从而减少收集流量对网带来的压力。


遍历过所有的流表信息后,可以将每一条流流经的交换机统计出来,这一操作过程称为分类。

在遍历流表在找每一条流流经的交换机时,将该交换机与其转发端口存成NodePortTuple二元组,在每个集合中保存有多个二元组,构成一个二元组集合,每个二元组可以表示为(niu),该二元组表示该数据流流经交换设备ni,通过其转发端口u转发出去。

假设一条流流经交换机dpid1,该流从该交换机的转发端口为3,那么将<dpid1,3>一起存入到hashmap中。经过分类之后的数据结构举例如图3所示。

图3 分类操作后的全局流表结构

但需要考虑一种前述的复杂场景:同一条流在流经不同交换机后,其流的某些字段的可能会被修改,所以一条流可能有多个不同匹配的流表,最终全局流表算法输出结果是一个 map

Key:是该流在整个流经过程中经历的所有交换机的 match 集合的 md5 值。比如 key_list=match_1+match_2+match_3,那么 key 为 key=md5(match_1+match_2+match_3),match_1,match_2,match_3 是按照其被修改的顺序排列。

Value:是一个复合的对象,包含该流的所有 match 集合以及该流流经的交换机路径。Match 集合是一个 list 对象,list={ match_1,match_2,match_3},路径是一个链表集合,path={dpid1,dpid2,dpid3……}。此时全局流结构如图4所示:


图4支持地址转换的全局流表数据结构

2. 2 全局流表样例

全局流表模块利用网络控制器的拓扑API收集拓扑信息,假设网络控制器返回的数据格式如下所示,其中列表中的每个JSON对象表示了一条交换机与交换机的连接关系。

[

{

“src-switch”: “00:00:00:11:22:03:04:01”,

“src-port”: 3,

“dst-switch”: “00:00:fa:40:d0:82:71:4a”,

“dst-port”: 1,

“type”: “internal”,

“direction”: “bidirectional”

},


{

“src-switch”: “00:00:1e:15:3a:5d:7f:4e”,

“src-port”: 2,

“dst-switch”: “00:00:fa:40:d0:82:71:4a”,

“dst-port”: 2,

“type”: “internal”,

“direction”: “bidirectional”

}

]

那么全局流表模块把所有交换机的流表信息收集起来之后,通过特定的算法(弱顶点覆盖算法),解析出全局流信息。通过API获取的全局流的两条样本数据如下:

{

    "status": "ok",

    "result": {

        "99194ec2bdc26f53b7ce1492265cc1ac": {

            "matchlist": [

                {

                    "id": "c7fc6816e5d6acb6d9ada6d95683c2fd",

                    "wildcards": 3678448,

                    "inputPort": 20,

                    "dataLayerSource": "fa:16:3e:c8:43:53",

                    "dataLayerDestination": "fa:16:3e:9d:c8:58",

                    "dataLayerVirtualLan": -1,

                    "networkSourceInt": -1,

                    "networkDestinationInt": -1,

                    "queryPage": 1,

                    "querySize": 5,

                    "match": "fa:16:3e:c8:43:53;fa:16:3e:9d:c8:58;0.0.0.0;0.0.0.0;0;0;0;-1;-1;0;0;0;0;3678448",

                    "redirect": true

                }

            ],

            "pathlink": [

                {

                    "nodeId": "00:00:3a:99:81:f9:19:44",

                    "portId": 0

                }

            ],

            "packetCount": 3,

            "byteCount": 163

        },

        …

        "66443400e3237e55876168a2d911cc36": {

            "matchlist": [

                {

                    "id": "3441e9d7d33ad5e6c9ce1d2b3b58007d",

                    "wildcards": 3678448,

                    "inputPort": 3,

                    "dataLayerSource": "fa:16:3e:3b:69:23",

                    "dataLayerDestination": "44:03:a7:74:a6:4a",

                    "dataLayerVirtualLan": -1,

                    "networkSourceInt": -1,

                    "networkDestinationInt": -1,

                    "queryPage": 1,

                    "querySize": 5,

                    "match": "fa:16:3e:3b:69:23;44:03:a7:74:a6:4a;0.0.0.0;0.0.0.0;0;0;0;-1;-1;0;0;0;0;3678448",

                    "redirect": true

                }

            ],

            "pathlink": [

                {

                    "nodeId": "00:00:e0:db:55:1f:99:b4",

                    "portId": 0

                },

        {

                    "nodeId": "00:01:45:90:ff:1f:89:b3",

                    "portId": 1

                }

            ],

            "packetCount": 50,

            "byteCount": 22330

        }

    }

}

    其中result中的每个JSON对象表示了一条全局流数据,pathlink表示流经的交换机。

三、GFaaS

全局流表可作为一种服务对外提供接口,供安全控制平台之上的应用调用,形成全局流表即服务(GFaaS),如图5所示。

 


5 全局流表服务示意图

该服务包括数据的存储和查询。简单而言,可以订阅-推送的方式,将安全控制平台收到的流数据推送到存储节点,目前该存储节点支持ElasticSearch(ES),可提供丰富多样的实时搜索查询功能。前端Django站点调用ESPython API,完成数据的查询功能。

3.1. 全局流数据的存储

全局流数据是通过订阅-推送模式进行存储,根据事件类型分别保存为当前流量和历史流量库。

安全控制器使用分布式消息队列把需求的数据绑定到相应的事件上,运行时把事件推送到消息队列中,那么只需要在固定的模块中订阅相应的事件,就能够在事件被触发的时候获取需求的数据。

安全控制器定时收集的流信息,将当前的流量存储到当前流量库中;同时,如果发现某些上一时刻的流消失后,会触发一个流结束事件并推送到消息队列。全局流表模块收到该事件则表明数据流已结束,则将该流存储到历史流量库。

经过解析后的全局流数据,一个记录包含13个字段,最终以JSON格式保存到ES数据库中。样本数据截图如下:


3.2 全局流数据检索

全局流数据检索应用,可以检索目前网络中存在的符合查询条件的流,并以表格的形式呈现。目前可支持对源目的MAC、源目的IP和源目的端口的匹配。查询得到获知满足条件流在所有交换机上经过的路径。前端如图6所示。

图6 全局流表查询图

全局流历史记录查询应用,查询的数据不止当前网络中的数据,还可以包括历史时刻的数据,这对安全事件发生后的取值是有帮助的。

四、全局流数据的应用

全局流表记录了网络中的所有访问信息,可以为多个安全应用所服务。

4.1. 流异常检测和回朔

通过全局流表知识,安全应用可以获知任意时刻源目的连接的起止时间和流量大小,进而可以建立一个正常访问的基线(Baseline)。

运行时,安全应用从全局流表中遍历当前流的数据,如果发现某条流在基线之上(即不符合正常访问的模式),则认为该访问存在风险。例如正常情况下数据库服务器B只会被前端Web服务器C访问,但某日办公主机A突然与某日连接B,这就存在异常;再如某内网服务器D短时间内向整个网络进行大量TCP SYNC尝试,这也触发了异常报警。

一旦安全应用检测到流级别的异常后,则可通过SDN控制器将异常流量牵引到如IDS或TAC做进一步的数据包payload检测或文件行为分析。

当安全应用或安全专家确认内网中确实发生了恶意攻击后,需进行取证和加固。此时可借助全局流表,找出攻击者的攻击路径。因为历史流表中记录了攻击者从一开始的尝试,到渗透成功后的进一步攻击行为痕迹,只要找出恶意样本对外连接的模式,以及攻击者在受害节点对外扫描、攻击等特征,就能分析攻击者是如何一步一步进入,也能获知有哪些主机被攻破,可生成相应的调查报告,并对受害主机进行恢复和加固。

4.2. 伪造源地址欺骗

伪造源地址的攻击(如某些SYNC Flood)在传统网络中较难防范,但全局流表可抵御这些攻击。

文中3.2展示了检索满足某些条件的流经过哪些交换机,也就是说全局流表可展示流量在二层网络中的路径。那么对于伪造源地址的攻击而言,尽管这些数据包的源地址被改写为不存在的地址或其他用户的地址,但其经过的交换机却真实地记录了它们的轨迹,如果攻击者的源主机就在本网络中,那么流表路径上的第一个交换机的inport所连主机就是恶意主机,这在事后的审计追查非常有用。

4.3 全局流数据可视化

对全局流数据进行可视化,能够对流信息有更为直观的判断。图7为全局流数据可视化的截图:

图7 全局流表展示图

图中蓝色圆圈为交换机,红色圆圈为主机,黑色的线表示物理链接关系,高亮的线表示网络中的流信息,并且根据每条流的颜色随该流的byte_count字段而改变。

下一步工作将会以历史时刻为搜索条件,动态展现某个时刻的流量信息。

五、结束语

全局流数据有着更广阔的应用场景,比如在入侵检测方面,能够通过设置阈值、数据挖掘等各种方式,一定程度上检测到异常流,提供安全服务。

安全应用超市:购君所需,付君所用

刘文懋 行盼宁

摘要:安全应用超市是一种新型的安全产品交付和运维模式,通过云端商店可有效管理客户多个环境的安全应用,借助软件定义的安全架构可快速部署和更新安全应用,

1 背景

当前企业安全公司的产品交付模式大致有两类,第一类是以硬件设备的模式,即客户根据销售对产品的介绍,选择符合要求的硬件设备,然后由工程团队将该设备部署在客户网络的特定位置,最后调试完上线;第二类是以服务或咨询的模式,即用户购买相应的安全服务后,安全公司提供一定时间的人工支持,已解决某些问题。然而,在虚拟化、云计算和SDN等新型环境中,前者需部署硬件设备,已经越来越难以适应客户业务的需求,难开发难部署;而后者则需要大量的人月开销,无疑增加了企业的成本。

另一方面,安全企业往往有大量不同细分行业的客户,每个客户的安全需求和网络环境千差万别,那么安全产品的开发者在开发和测试产品的时候,不能保证与客户的实际场景完全一致,因而会产生很多技术问题无法及时解决。

那么有没有一种更适合未来新兴网络环境的安全产品交付方案呢?一种方法是将安全产品SaaS化,即为客户提供弹性可扩展的安全服务,隐藏了各种底层复杂的安全设备和安全机制。笔者在前几期内刊中曾提出过软件定义的安全架构,通过可编程、开放的安全控制平台实现安全资源抽象池化,为客户提供开放可编程的应用接口,进而实现安全应用的快速开发。

软件定义的安全应用可以满足客户需求,但还有几个问题亟待解决:首先,官方开发的安全应用毕竟是少数,不能覆盖所有业务场景,也不是所有用户都具备二次开发的能力,那么大多数用户会面临只有少量安全应用可用的尴尬境地;其次,每个应用所适配的环境不同,那么如何部署这些应用,将是极大的挑战;最后,随着安全威胁的日益增加,安全应用的升级必不可少,那么如何做到无缝升级,也是需要解决的问题。

2 安全应用超市简介

事实上,应用市场的概念源于Apple的一款软件AppStore,该模式是一个基于IOS平台的自营销体系,与广大开发者和用户共同形成了良好的生态环境,并获得了很好的商业收益。虽然个人消费市场与企业安全市场无论从营销模式还是技术实现方面,都有千差万别,但这一新概念无疑为我们提供了一个很好的思路:图1描述了安全应用超市的概念图,安全厂商在云端收集、推广和分发某些用户开发的应用,其他用户可以一键购买或租赁、部署和更新所需的应用服务。


图1 应用超市的模式概念图

 

安全应用超市与以往的安全产品交付模式有革命性的变化,终端用户将不需要关注具体的安全硬件功能、性能甚至型号,而只需要关注是否适合其适用的业务场景,例如WEB服务运营客户不需要了解厂商是否有WEB扫描器或WEB防火墙,或安全产品是否支持透明代理或反向代理,或需要多少台安全设备;相反,他们只需要关注WEB安全防护应用是面向游戏、电商或其他类型的站点,是否具有定时检查和实时防护功能,以及确定需要防护多大量级的WEB服务即可,应用便会自动通过软件定义的安全控制平台准备好相应的虚拟安全设备,设置好网络流向路径,配置相应的安全策略。这些复杂的操作,绝大部分对客户是透明的。

正如前述,要做到安全应用自动化运维,企业安全应用的部署和管理存在很多困难,例如:

  1. 安全应用体积巨大 一个安全应用可能包含多个安全产品,如抗APT检测应用会包含流量分析、入侵检测、行为检测和系统扫描等产品,每个安全产品都是独立庞大的系统,如果说初始化下载尚可,那不断的维护更新的开销则对安全管理员完全不可接受。
  2. 安全应用部署环境复杂 一个安全应用除了安全设备外,还包含如何准备网络、计算和存储环境的脚本和配置文件,那么这些控制信息和元数据是否能适用于不同行业的客户环境,又或另外一个问题,不同行业的客户环境出现异常,研发团队是否能够快速重现和解决问题?
  3. 认证和计费支持 以往厂商向客户交付的是硬件设备,而客户获得应用服务和更新的方式是在线购买或租赁,获得这些服务的凭据则是认证的密钥,所以对于安全控制平台和安全设备,都需要支持集中式的认证和计费

3 系统支撑技术

3.1 软件定义安全架构

软件定义安全的架构将安全设备的控制平面上移到了集中控制的安全平台,将众多底层设备抽象为安全资源池,以松耦合的方式与IaaS和SDN等新型业务环境交互,并以通过开放和可编程的方式为北向的安全应用提供高效可靠的安全接口。该架构如图2所示,已在前几期内刊中已有介绍,本文不做赘述。


图2 软件定义安全的架构

3.2 轻量级虚拟化Docker

Docker是介于IaaS和PaaS之间的虚拟化方案,有高效、隔离和轻量级等优点。Docker技术涉及三大概念,包括镜像(Image)、容器(Container)、仓库(Repository)。下面结合本项目对其进行详细介绍。

Docker镜像对应预安装的操作系统和若干应用软件的系统,也是启动一个Docker容器的基础。

Docker容器是基于主机之上的操作系统虚拟化,作为普通进程运行于宿主机器之上。Docker利用容器来运行应用,而容器是基于镜像创建的运行实例,可以被启动、开始、停止、删除等。Docker镜像是静态的,而Docker容器是动态的,Docker容器启动需要先装载Docker镜像,启动之后的容器可以进行动态化管理,也可以对容器进行打包,生成新的镜像。

与与虚拟机一样,每个Docker容器之间相互隔离,安全性得到操作系统级别的保证;而容器对于虚拟机有明显的优势,主要有:

  • VMs运行整个虚拟操作系统于主机之上,而Docker容器直接加在应用程序在主机上运行,一个主机可以同时运行数千个容器;
  • Docker容器启动速度远远快于VMs,实现高效快速化,容器的启动时间是秒级的;
  • Docker容器比VMs轻量级,节约资源,便于管理。

Docker仓库是集中存放Docker镜像的场所。分为远程和本地,本地指的是存放本地的镜像仓库,而远程仓库就是指Registry仓库,对外提供Docker镜像下载,上传等服务。

此外,Docker使用了AUFS文件系统 允许用户将一次对磁盘做的读写操作变为文件系统中一层增量的部分,面向不同层面应用的镜像可以树形结构建立,子镜像的容量只比父镜像大了增量部分,如图3所示。不同用户的不同镜像的不同版本都可源于同一个安全厂商提供的预置的镜像,这样所有的应用更新都可以只传输增量部分,大大较少了传输的时间和网络开销。


图3 Docker镜像层次图

最后,Docker提供的了很好的版本管理和资源隔离,安全厂商的研发Docker环境与客户部署的Docker环境可以完全一致,当客户遇到非预期的应用异常时,研发只需要检出对应版本的Docker镜像,启动的容器中操作系统、网络和应用软件环境与用户侧则是相同的,很容易排查问题。

可见,Docker作为刚刚新型的虚拟化技术,适合App的快速交付和部署,App的迁移扩展比较高效简单,有更高效的虚拟化效率,以及更一致的研发和生产环境,非常适用于企业级的安全应用超市的底层支撑技术。

4 安全应用超市设计

安全应用超市设计是面向软件定义网络(SDN,Software-defined networking)和网络虚拟化(NV,Network Virtualization)新型网络架构环境,实现App的提交、审核、购买以及自动化部署等功能。


图4 安全应用超市架构图

该系统的架构如图4所示,分为两大核心部件:应用超市和安全控制平台(SC)。应用超市主要负责云端App的管理,并对外提供App下载上传接口;安全控制平台可以从应用超市进行认证并下载App,从而部署App到本地服务器上。

4.1典型交互案例

我们先做一些假定:应用超市对多个客户开放,一个客户可能有多套业务系统,每个业务系统部署一个安全控制平台,该控制平台可长期与应用超市端连接,用于接收应用数据和控制信息。

那么,一个简单的使用案例的流程说明如图5所示:

  • 首先,用户打开打开应用超市的Web Portal,使用用户名密码或证书登陆
  • 其次,用户浏览或根据关键字、应用场景等搜索应用,找到感兴趣的应用
  • 接着,用户点击购买,或选择租赁时间,获得应用超市的授权
  • 然后,应用超市提示所有连接的安全控制平台,用户选择相应的位置,应用被推送到相应的安全控制平台
  • 最后,用户在安全控制平台启动应用,或先选择应用部署在哪些可用节点上随后启动


图5 AppStore用例设计

4.2 应用超市与Docker技术的关联

在本项目中,应用超市的架构使用的底层支撑技术是Docker,那么逻辑概念上两者会存在对应关系。

从概念上,应用程序对应的是Dokcer中的镜像,App的下载上传对应Docker镜像的下载上传。由于Docker镜像是分层的,那么我们 也可将镜像分为三层管理,以提高镜像管理效率:最顶层的是基础镜像层,安装所有容器都需要的软件;中间层是服务镜像层,更具能力不同安装不同的服务软件; 最底层是应用镜像层,仅安装应用程序相关的软件。

其次,每个容器的运行对应于本项目中App的部署和运行,当安全控制平台得镜像后,按照策略将其部署到可用节点上,并启动该镜像对应的容器,那么容器所提供的服务就是App的功能。

最后,Docker仓库对应到本项目中的应用超市私有云服务和用户端的安全控制平台,即首先安全控制平台先从超市仓库获得镜像,保存在本地的私有仓库中,然后每个节点从该私有仓库获取镜像,进而启动容器。

 


安全应用超市技术细节图

所以,总体的安全应用超市用Docker实现如图所示,具体技术对应关系如下所示:

  • 静态概念映射
    • Docker镜像->App
    • Docker Registry仓库->Cloud AppStore
    • Docker Local仓库->client AppStore
  • 动态概念映射
    • Docker镜像转容器->运行部署App
    • Docker容器转镜像->App创建,环境搭建等
    • Docker镜像下载(Registry仓库到Local仓库)->App下载(Cloud AppStore到Client AppStore)
    • Docker镜像上传(Local仓库到Registry仓库)-〉App上传(Client AppStore到Cloud AppStore)

5 安全应用超市实现

技术路线采取Java技术实现App Supermarket和Security controller,采用Docker容器实现前述两者的底层管理,并将系统运行在IaaS和SDN环境中,利用SDN的特性,可设计实现流量牵引和流 量获取等应用,如抗DDoS、Web防护。

 

超市云服务

安全控制平台

安全应用超市 Web展示



应用超市展示

6 结论

安全应用超市的概念将改变安全产品发布和运营的模式,为用户提供一键购买、租赁和升级等功能,隐藏了安全产品复杂的实现和部署环节,通过标准化的应用上载、下载和部署,可大大增加应用的适用环境,降低开发和维护成本。

此外,通过Docker技术实现该系统具有高效、可扩展、易维护等优点;通过安全控制平台可快速支持应用的下载、部署和更新,以及提供高效开放的应用接口,使得用户端整个安全系统可利用软件定义和虚拟化等特性加快安全检测和防护的效率。

浅谈网络虚拟化安全

摘要:本文简要介绍了网络虚拟化的发展,分析了网络虚拟化方面的一些安全问题,并给出了一些可行的措施

关键字
网络虚拟化
安全 SDN OpenFlow

 

经过多年的技术准备和商业模式探索,云计算已然进入快速发展的阶段。当前有不少大型数据中心和的企业IT系统可为云计算提供设施级别的强大支撑平台,然而业务快速增加给数据中心和大型企业的复杂网络管理带来了极大的挑战。网络虚拟化技术和软件定义网络(SDNSoftware Defined Networking)技术以软件可编程的方式管理虚拟和实体网络资源,很大程度上解决上述问题,近年来得到了极大的关注。本文主要介绍了面向数据中心和企业级应用的网络虚拟化技术,并探讨网络虚拟化对于传统安全的挑战,与之可能的安全解决技术。

1网络虚拟化技术简介

在虚拟化应用中,大规模应用对计算和存储的天然需求使得计算虚拟化和存储虚拟化技术较为成熟,与之相比,网络虚拟化的相关技术还在开发阶段,远没有达到成熟的程度。不过随着应用规模不断变大和业务快速变化,实体和虚拟网络的融合、快速管理和可扩展性将成为巨大的挑战,网络虚拟化已受到越来越多的关注,可预计其发展会进入快车道。

网络虚拟化将物理和虚拟网络资源整合成一个可管理的虚拟网络,特别SDN的出现对网络管理带来了颠覆性的变化:可通过编程的方式迁移虚拟机、动态组网,大大加快变更网络拓扑的进度。ONF指出SDN具备三个核心特征[1]:控制平面和数据平面相互分离、智能和状态在逻辑上集中以及底层网络基础设施从应用中抽象出来。SDN是层次化的集中控制架构,如图1所示:网络控制器处于SDN架构的中心,北向与应用连接,进行业务交互;南向连接底层的交换机,下发路由控制命令。功能上,网络中心的控制器掌握网络拓扑、数据转发的策略,而分布在各处的网络设备接受控制器的命令,执行数据转发和路由的行为。操作上,网络管理员可以随时更新网络拓扑、调整网络规模,或快速部署安全策略,如果操作失败或存在问题可方便的进行回滚恢复到原来的状态,可见SDN确实提供了快捷方便的网络管理途径。


1 SDN的应用实例

需要说明的是网络虚拟化、SDNOpenFlow三者不是等价的。网络虚拟化可以不使用SDN技术,SDN也不一定要用于虚拟化环境,但SDN的控制数据平面分离非常适合网络虚拟化的场景。同样地,OpenFlow是一种可实现SDN场景的控制器设备协议,但非唯一的SDN实现方式,还如NVGRE等技术。本文在讨论网络虚拟化时都是基于SDN的,所采用的协议标准是OpenFlow

  1. 主流的网络虚拟化解决方案

通过软件重构网络是大势所趋,不同厂商在SDN中根据自身情况制定各自的策略,总体来说,SDN的研发领域可能会出现三足鼎立的局面: OpenFlow标准的相关开源系、Cisco主导的Cisco One系和Vmware主导的SDN系,参与三个体系的厂商关系如图2所示。


2 SDN厂商阵营图

1.2.1 OpenFlow/ONF

当前参与量最大的开放SDN阵营是由90多家公司组成的非盈利组织组成的ONFOpen Networking Foundation),其成员不乏IBMIntelGoogle等重量级的公司,还有BigSwitchCitrix等专注虚拟化的公司,此外还有国内的企业如腾讯、华为和中兴等。ONF最重要的成果是OpenFlowOpenFlow是网络控制器和交换机之间通信的协议,控制器通过统一的路由策略下发基于流的数据交换命令,实现了上层软件管理和更新路由表、底层交换机执行转发策略的软硬件分离模式。OpenFlow协议处理数据的过程如图3所示,交换机在遇到未知模式的数据包时,会向控制器上传相关特征,控制器检查自己的策略库,生成数据交换的模式,然后将这些模式以控制信息的形式下发到对应的交换机,从而底层的交换机可以根据全局的路由策略执行相应的数据交换。

由于OpenFlow定义了控制器和交换机间的通信协议和安全通道,并规定交换机应遵循的规则,交换机只执行数据交换的功能,所以各厂商容易开发出支持OpenFlow的交换机,如Nicira的虚拟交换机OpenvswitchNECIBM等支持OpenFlow的实体交换机。对应地,控制器负责整个SDN中的网络拓扑管理、数据包路由决策、QoS管理和安全控制等复杂的功能,所以控制器是整个网络的核心,当前比较著名的控制器有BigSwitchfloodlightNiciranoxNECProgrammableFlow Controller等。

OpenFlow只定义了控制器交换机的南向通信标准,没有给出应用控制器的北向接口标准,所以相关厂商可以针对控制器开发自己的网络应用时,需要考虑不同控制器的应用接口。


3 基于OpenFlow协议的数据交换

1.2.2 Cisco One

20127月,Cisco公司推出了自己的SDN计划思科开放式网络环境
Cisco ONEOpen Network Environment
Cisco ONE实现网络环境的可编程性的同时,有更大的战略规划:它将SDN定位于五个目标市场:学术和研究、企业、服务提供商、云服务提供商和数据中心,并认为OpenFlow只是其中的学术和研究市场。Cisco ONE是对OpenFlow功能的扩展,包括Cisco onePK开发套件和Nexus 1000V等虚拟覆盖网等技术。其中Nexus 1000V包含了控制器Virtual supervisor module (VSM)和交换机Virtual Ethernet module (VEM) ,实现了完整的SDN功能。

1.2.3 VMWare/Nicira

老牌虚拟化巨头VMware在网络虚拟化方向也有大量投入。早在做研发服务器虚拟化时,VMware就使用虚拟网桥和NAT的方式建立了宿主机和虚拟机之间虚拟网络。在最新的企业级虚拟化产品vSphere中,网络虚拟化解决方案要有两方面:管理虚拟网络中的数据和流量的Network I/O Control,以及集中式管理、监控和可视化虚拟网络的Distributed Switch

此外,VMware2012年收购了Nicira Networks公司,后者主导开发了虚拟交换机项目Openvswitch。可预见VmwareNicira的网络控制器等产品集成到vSphere后,会在SDN方向进一步发力,保持其在虚拟化市场中领先的地位。

  1. 网络虚拟化面临的安全挑战

虚拟化给数据中心和企业网络带来了新的问题和挑战。一方面,传统的安全产品和安全解决方案无法解决在虚拟化后出现新的网络安全问题;另一方面,网络虚拟化自身也面临一些安全问题。网络在虚拟化后主要的问题有:

  • 物理安全设备存在观测死角

虚拟机与外界存在数据交换,在虚拟化环境中的数据流有两类:跨物理主机的VM数据流和同一物理主机内部的VM数据流。前者一般通过隧道或VLAN等模式进行传输,现有的IDS/IPS等安全设备需要在所有的传输路径上进行监控,后者只经过物理主机中的虚拟交换机,无法被实体的安全设备监控到,成为整个安全系统的死角。攻击者可以在内部虚拟网络中发动任何攻击,都不会被安全设备所察觉。如图4中攻击者在虚拟机VM1中攻击VM2,数据流量没有经过物理交换机的,也不会传输到防火墙和IDS。所以虚拟化改变了数据的流向,增大了大量物理设备不可见的区域,增加了整个虚拟化网络的安全管理难度。

4 物理安全设备无法观测到内部虚拟网络的数据交互

  • 虚拟网络的数据流难以理解

虽然安全设备无法获得物理主机内部的VM间的数据包,但可以获取跨物理主机间VM的数据流。尽管如此,传统的安全设备还是不能理解这些数据流,也就无法应用正确的安全策略。例如在图5中,租户X和租户Y分别在两台物理主机上租用了一台虚拟机,当租户XVM1VM3发数据包时,防火墙能接收到物理主机1到物理主机2的数据包,但不知道到底是租户X还是租户Y的程序在发送数据包,也不知道是哪两台VM在通信。此外,很多虚拟机之间的数据包是经过GRE隧道传输的,所以传统的网络安全设施可能不能解析这些封装后的数据流。


5 物理安全设备不能理解跨物理主机间数据流

  • 安全策略难以迁移

虚拟化解决方案的重要优点是弹性和快速,例如当VM从一台物理主机无缝快速地迁移到另一台物理主机时,或当增加删除VM时,网络虚拟化管理工具可快速调整网络拓扑,在旧物理网络中删除VM的网络资源(地址、路由策略等),并在新的物理网络中分配VM的网络资源。相应地,安全解决方案也应将原网络设备和安全设备的安全控制(ACLQoS)也跟随迁移,然而现有安全产品缺乏对安全策略迁移的支持,导致安全边界不能适应虚拟网络的变化。

  • 网络流量不可见

在传统网络中,所有数据包经由交换或路由设备,这些设备具有可以感知并学习当前环境的数据流量,可以针对目前的网络状况动态调整路由策略。但基于OpenFlowSDN架构中的网络控制器只会收到底层设备发来的部分的数据包,并不了解控制域中大部分直接被转发的数据流具体内容。

  • 控制器的单点失效

除了传统网络升级到SDN后网络层的新问题外,SDN本身也会存在漏洞,特别是复杂的SDN的控制器。数据平面和控制平面的分离主要是由控制器实现的,所以控制器就成为了网络虚拟化的最重要的设施。

然而控制器需要应对各种动态的网络拓扑、解析各种类型的数据包、接收上层应用的信息,并控制底层网络设备的行为,所以功能实现将会非常复杂,也就可能存在不少漏洞。当攻击者攻破控制器,就可以向所有的网络设施发送指令,很容易瘫痪整个网络;或将某些数据流重定向到恶意VM,造成敏感信息的泄露。

控制器控制整个网络的拓扑,处理几百甚至上千个应用的路由策略,每个应用的路由路径可能不同,那么如果这些不同应用产生的路由项之间存在不一致,就可能会出现非法路径。Porras等人提出图6的攻击场景[2],系统根据安全策略应禁止主机10.0.0.2与主机10.0.0.4通信,但如果控制器中有三项看似合法的不同应用需要的路由策略,那么当数据包从10.0.0.2传输到10.0.0.3,会在交换机上被替换掉源和目的地址,成为从10.0.0.1传输到10.0.0.4的数据包,最终被允许转发,而这原本应该是被禁止的。可见控制器中的路由项如果不一致,攻击者就有可趁之机绕过控制器实施攻击。


6 控制器上三条合法策略组形成一条非法路径

  • 控制信息难验证

除了攻击控制器外,控制器和网络设备间的通信也可能存在安全问题。虽然OpenFlow协议规定两者通信可使用加密的通道,但如何保证交互双方可信是一个问题。

一方面,攻击者假冒网络控制器,发送恶意控制命令即可改变网络拓扑、破坏安全策略,或修改数据流绕过防火墙。另一方面,攻击者也可以通过控制某些网络设施,向控制器发送伪造的数据包,影响控制器对网络流量的判断。

如果不解决网络虚拟化后产生的安全威胁,就可能会破坏整个网络的可用性和可靠性,造成租户的隐私泄露,并给攻击者后续攻击内部VM提供条件。

3 网络虚拟化的安全对策

本章主要针对探讨虚拟化环境中出现的安全问题,提出一些可行的安全对策。首先是确保新增的网络设施的安全,然后检测虚拟资源的安全性,最后设计自动高效的安全控制网络控制联动机制。

3.1 保护SDN网络的虚拟资源

传统的网络安全认为被攻击目标有应用、服务器和实体网络,SDN场景还增加了网络控制器和虚拟网络设备,所以网络虚拟化安全的第一步就是要保证这些新资源的安全。

3.1.1 设计安全可靠的网络控制器

网络控制器是SDN网络的中心,也是其前置安全保证,所以保障网络虚拟化必须设计一个高可信、安全和健壮的网设计控制器。

首先,控制器需要加入审计机制,检查访问控制器的用户,保证是合法可信的,避免恶意攻击者发动各类攻击,并记录原始日志,做到定时或事后检测异常行为。

其次,保证控制器和交换设备的通信安全,如OpenFlow协议就要求两者通信必须存在一个加密通道,需防止中间人攻击。

最后,针对内部攻击或管理员不正确的配置,安全产品可实时或定时检测控制器的路由规则是否兼容并满足安全需求。如针对前面提到的”控制器不一致策略”问题,Porras等针对控制器Nox设计了一个第三方插件FortNox,可实时检测规则是否冲突。

3.1.2 保证虚拟网络设备安全

在大二层交换网络中,虚拟网络设备主要是指支持OpenFlow的虚拟交换机,如果交换机出现异常,会造成网络拓扑变化,甚至会影响控制器的正常工作。

为保护虚拟交换机,需要及时更新Hypervisor软件,防止攻击者逃逸虚拟机后利用被攻破的虚拟交换机发送恶意或异常的消息。

此外,应设计网络设备配置的一致性检查,避免发生网络风暴,减少控制器端收到的非必要PacketIn数据包请求。

3.1.3 保证控制器和网络设备的通信安全

当前OpenFlow协议中规定控制器和交换机之间的通信使用TCPTCP/TLS协议,如果使用不加密的TCP方式,攻击者很容易伪造交换机的消息,扰乱控制器所获知的网络拓扑;但如果使用认证的加密方式,在大规模网络中控制器容易遭受拒绝服务攻击。所以设计一个轻量级可认证的通信方式,保证控制器收到的消息秘密性、完整性和可用性,将是一个重要的研究课题。

3.2 推出支持虚拟化的安全产品

针对传统安全产品对内部网络不可见的缺点,安全厂商需推出支持虚拟化的安全产品,这些安全产品以软件的形式存在,并兼容主流的虚拟化解决方案,可监控内部虚拟网络中的数据流。一般而言,支持虚拟化的安全产品通常有虚拟机形态和Agent形态。前者可以不对网络拓扑和计算节点不进行任何改动,非常方便,但缺点是安全产品容易遭到被感染的虚拟机的攻击,配置也比较复杂;后者可感知虚拟机和网络变化并应用策略,而且产品部署在VM不可见的Hypervisor层面,在很大程度上减少了对安全产品的攻击,但需要修改物理主机的系统。可预见虚拟机形态和Agent形态会相互配合,与安全控制器协同,完成较完备的安全功能。

3.3 设计软件定义的安全解决方案

要想达到真正的软件定义安全(SDSec, Software-Defined Security),就需要在保护现有和新增设备,以及内部虚拟网络的基础上,深刻理解SDN的工作模式,提出松耦合但与之匹配的安全架构,设计网络控制器和安全控制器联动的安全机制,建立基于环境的数据传输决策模型。

SDN网络与传统网络的最大不同是可编程化(programmable),整个网络的数据流和拓扑都是在控制器的指令下快速变化,那么安全产品必须理解这种变化,并能程序化地快速自动调整底层设备策略。对于虚拟化场景下的主体,Vmware公司首席安全和网络架构师Rob Randell认为可被分成三级[3]:虚拟数据中心vDC、虚拟应用vApp和虚拟机VM(如图7所示),然后将各类安全应用根据功能组成策略模板,最后多个策略模板可以组成若干个安全组。安全组间能组成复杂的策略,应对不同级别的主体。那么对于一个虚拟化应用而言,不管其VM分布在何处,也不管其数据流的路径是什么,总能建立安全组的结构,使之能处理该应用的工作流(workload),实现安全管理的功能。


7 虚拟化场景下安全策略的分解

 

  1. 结论

SDNOpenFlow将网络的逻辑视图与物理视图分离,使得网络配置更加灵活,硬件设备成本大大下降,是计算机网络的又一次革命。SDN带来了巨大的便利的同时,也带来了大量尚未解决的安全问题。本文在分析了SDN的安全挑战后,给出了一些安全对策。

虽然网络虚拟化为数据中心和企业的网络安全带来了巨大的挑战,但也给网络安全防护带来了提供了新思路和新方法,如SDN集中式控制提高产品防护能力、为快速重定向可疑的DdoS流量、快速自动地构建攻防实验网络,并降低安全产品的成本。所以研究虚拟环境下的安全问题,研发支持SDN的安全产品对保护整个虚拟化网络是必要且有益的。

 

 

1 F5 NetworksSDNADN 竞争还是合作?

2 Phillip Porras, Seungwon Shin, Vinod Yegneswaran, Martin Fong, Mabry Tyson, Guofei Gu. A Security Enforcement Kernel for Openflow Networks. Proceedings of the ACM Sigcomm Workshop on Hot Topics in Software-Defined Networking (HotSDN), August 2012.

3 Rob Randell, How the software defined datacenter is turning security on its head, RSA conference, 2013

SOAR:软件定义安全之编排篇

摘要:自动化编排已经成为行业内讨论很多的话题,但自动化编排的场景、如何实现自动化编排,还在探索中。本文从软件定义安全的角度,讨论了安全编排的必要性、关键支撑技术、实现架构和发展方向。

关键字:安全编排 软件定义安全

一,安全为什么要编排

1.1 什么是软件定义安全

Gartner自提出了软件定义安全的理念,为安全防护指出了一个可行的方向。软件定义安全连续xx被列入了十大新技术。软件定义安全从概念上借鉴了软件定义网络,即将安全的控制平面和数据平面解耦,控制面关注安全业务逻辑,数据面关注能力抽象和性能提升,从而避免厂商锁定,提高整个安全防护的灵活性和响应速度。

图1 软件定义安全架构

需要说明的是软件定义安全虽然源于软件定义网络SDN,也可以借助SDN的流量调度、控制技术加快安全防护的速度、增加安全防护的能力,但软件定义安全强调的是安全自身的体系重构,最终分离为安全应用、安全控制器和安全设备(资源池)三层,该体系是可以独立于SDN、NFV及其他特定的业务系统。

在云中的软件定义安全落地技术有:

1 CWPP,对于云中业务变化频繁的特点,不能依赖固定的安全防护机制,需要感知业务迁移,动态部署相关的安全机制。

2 软件定义分段(或微分段),可根据业务而非固定的网络地址进行全局的网络隔离和访问控制,访问控制策略是通过控制平面下发到不同的enforcer中,可能是主机上的agent,也可能是网络设备。

所以本文讨论的软件定义安全不会聚焦于如何调度流量、如何对接虚拟化平台,而是假定安全应用具备了流量调度、资源管理和策略下发的能力,进一步关注应用间的编排:这些应用于不同场景的应用彼此间什么关系,不同应用的策略如何生效。

 

1.2 编排是软件定义安全的核心价值

随着云计算等应用持续发展,安全平台与业务系统的管理平台对接已日趋完善。如主流的公有云和私有云平台内部都支持了SDN和NFV技术,安全厂商的设备可以SaaS服务的方式与之对接,形成如脆弱性评估、Web安全、DDoS缓解等特定的防护能力。

这个机制可遵从软件定义安全的架构:

  1. 控制层,安全控制和分析平台对接云平台,进行流量控制和安全虚拟机部署,
  2. 应用层,租户访问SaaS应用,配置策略和查看事件
  3. 数据层,安全设备部署和接入后,根据策略对流量进行检测或阻断

然而,随着业务的发展和攻防场景的不断深化,面向单攻击场景的单个安全应用无法应对拥有多种网络武器库的攻击团伙,那就需要一种机制,能够将现有的安全应用组织起来,根据当前的上下文和攻击者行动灵活调用相应的安全应用,进而快速、稳定、一致地准备好安全应对能力。

这就需要使用到编排技术,编排(Orchestration)的本意是在如大型的交响乐演奏中,乐者各司其职,根据指挥的指令演奏乐章中自己的部分。同样,如果将安全应用比喻成乐者,那么要实现敏捷、弹性的软件定义安全机制,就需要有两个核心:

1) 剧本(即前述的乐章),体现了安全防护的逻辑,指示如何调度安全能力,我们称之为剧本(Playbook)

2) 编排引擎,一套能够根据剧本有效指挥安全应用的机制,

如果说云环境中,用户在网页中下发策略将安全防护简单化、傻瓜化,那通过编排引擎,自动化、API化地驱动各应用,却是将安全防护规模化、敏捷化、智能化了。

而且用户可以根据自己的需求,编写灵活简单的剧本,去按需调用某些应用,实现某些特定场景中的安全功能,摆脱了以往只能依靠安全厂商标准化产品的窘境。

所以安全编排大大地扩展了安全防护的场景,提升了安全防护的能力,加快了各类安全机制协同的速度,是实现软件定义安全体系的核心能力。

Gartner在XX年提出了SOAR(Security Orchestration Automation and Response),并列入十大新技术,可见软件定义安全理念落地时,编排已经成为非常有前景的使能技术。

二,如何编排安全

2.1 编排系统的架构

安全控制器的核心功能是对虚拟化资源、网络流量和安全策略进行控制,安全应用的编排更多的是发生在业务层面,例如入侵检测系统发现挖矿软件外联行为,接下来应该如何处理,应该调用防护墙阻断,还是通知EDR杀掉异常进程,则应由编排逻辑决定。

所以,在原有的软件定义安全体系的应用层之上,可独立加一层编排层,如图2所示。虽然安全控制器可实现诸多控制层面的功能,如资源池化,策略拆解、设备管理等,但不可否认在现阶段安全控制器无法接管所有厂商的安全设备和安全工具,所以作为重敏捷的编排系统,必须能够支持第三方的安全应用,这些安全应用可以直接操作安全设备或工具,这样安全运营团队就可以最短的时间驱动现有的安全功能。

图2 可编排的安全架构

其核心是编排引擎,输入是剧本和订阅事件,输出则是到安全应用的策略。

图3 编排系统架构

 

编排系统还会和其他业务系统对接,例如Splunk收购Phantom Cyber后,将大数据分析平台与编排系统打通,形成检测事件到行动的闭环;而【xx】则将编排系统与威胁情报平台对接,当发现异常的IOC后,则转入自动处置的环节。

当然还有一些提供MDR和MSSP安全服务商,为了降低大规模应急响应处置的边际成本,为应急响应团队的提供简单的编排运行时环节,不需要很重的安全平台,只需要利用现有的小工具,也能快速的处置,但这样的编排系统需要与服务报告系统打通。

2.3 编排实例

绿盟科技2019年《安全事件响应观察报告》(以下简称《报告》)中给出了几个典型的安全事件场景,其中有勒索软件、挖矿软件、Web入侵等,利用编排引擎,可以大大提升这些场景下的安全处置效率。

2.3.1 勒索软件的处置

勒索软件是近几年日益显著的威胁之一,典型的如《报告》中所提的GrandCrab、Satan等,我们可总结其共性特征,利用多种安全机制实现对勒索软件的快速检测和处置,具体针对每类恶意软件,则有针对性地编写剧本。

编写剧本前需了解客户环境中所具有的安全能力,我们假定客户A的办公环境中是Windows台式机组成的局域网,网络边界有防火墙FW,网络中部署入侵检测系统IDS,客户终端部署EDR软件,并存在EDR的管理平台EDRM。设备和平台的告警数据都接入大数据分析平台SIEM。

图4 网络拓扑图

安全团队分析完需求后,整理出现有安全能力:EDR具有终端侧的行为检测(如勒索软件批量加密并删除文件)和响应(将恶意代码清除、删除持久化文件或注册表)能力,IDS具有网络侧的异常流量(如勒索软件与CnC通信)识别能力,防火墙具有网络侧流量(如勒索软件与CnC通信)阻断能力。在编写剧本的时候也应注意,优先处理靠前攻击阶段的告警,这样避免在勒索软件最后对文件加密造成不可挽回的后果。整理如下的流程图:

 

图5 处理流程图

该剧本启动后,会定期地从SIEM中获得告警信息,如果发现某终端存在勒索行为,或IDS发现存在符合勒索软件通信的流量,则转入处置环节。此时,剧本会寻找找到被入侵终端上的EDR软件,执行清除勒索软件的指令;但如果EDR软件没有安装,则向防火墙下发策略,阻断勒索软件和主控端的通信,并切断感染主机的传播通道。如果没有任何安全处理机制,则在SOC中提交一个工单,让安全管理团队人工处理。

运营团队通过自动化工具画出上图后,系统自动转化成如下代码:

 

import sdk.nsfocus.com as sdk

 

def on_start(container):

filter_1(container=container)

 

def block_ip_1(action=None, success=None, container=None, results=None,

handle=None, filtered_artifacts=None, filtered_results=None):

config = [ {

‘plugin’: “nsfocus_firewall”,

“asset”: “firewall_1”

}, ]

ret_artifacts_1 = sdk.collect2(container=container, datapath=[

‘filtered-data:filter_1:condition_1:artifact:*.cef.destinationAddress’,

‘filtered-data:filter_1:condition_1:artifact:*.id’])

 

parameters = []

for ret_artifacts_item_1 in ret_artifacts_1:

if ret_artifacts_item_1[0]:

parameters.append({

‘ip’: ret_artifacts_item_1[0],

})

sdk.act( “block ip”, parameters=parameters, callback=test_callback,

config=config, name=”block_ip_1″)

return

 

def filter_1(action=None, success=None, container=None, results=None,

handle=None, filtered_artifacts=None, filtered_results=None):

ret_artifacts_1, ret_results_1 = sdk.condition(

container=container,

action_results=results,

conditions=[

[“artifact:*.name”, “==”, “挖矿程序连接DNS矿池服务器通信”],

[“artifact:*.name”, “==”, “watchdogs挖矿木马DNS通信”]

],

logical_operator=’or’,

name=”filter_1:condition_1″)

if ret_artifacts_1 or ret_results_1:

block_ip_1(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=ret_artifacts_1, filtered_results=ret_results_1)

return

ret_artifacts_2, ret_results_2 = sdk.condition(

container=container,

action_results=results,

conditions=[

[“artifact:*.name”, “==”, “批量加密操作”],

],

name=”filter_1:condition_2″)

if ret_artifacts_2 or ret_results_2:

call_agent_1(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=ret_artifacts_2, filtered_results=ret_results_2)

return

 

def call_agent_1(action=None, success=None, container=None, results=None,

handle=None, filtered_artifacts=None, filtered_results=None):

config = [ {

‘plugin’: “nsfocus_edr”,

“asset”: “edr_platform”

}, ]

ret_artifacts_1 = sdk.collect2(container=container, datapath=[

‘filtered-data:filter_1:condition_1:artifact:*.cef.destinationAddress’,

‘filtered-data:filter_1:condition_1:artifact:*.id’])

parameters = []

with open(‘Clean_Wanna_Virus.py’, ‘r’) as f:

script = f.read()

for ret_artifacts_item_1 in ret_artifacts_1:

if ret_artifacts_item_1[0]:

parameters.append({

‘ip’: ret_artifacts_item_1[0],

“script”: script

})

sdk.act( “call_agent”, parameters=parameters, callback=callback,

config=config, name=”call_agent_1″)

return

def on_finish(container, summary):

return

if __name__ == “__main__”:

on_start(“ransomware”)

将流程图转换为代码是一个常规自动化的过程,但在运营过程中可能需要针对勒索软件变种的新行为对原剧本做一些微调,这要求安全团队有一定的开发能力。此外,真正的剧本代码会比上图更复杂,比如satan恶意软件除了连接主控端外,还会以蠕虫的方式传播,所以防火墙的策略不仅要阻断恶意网站下载、恶意软件连接主控端的流量,还需要对受害主机和内网其他主机进行隔离,以防其进一步感染内网。

2.3.2 大规模安全应急处置

报告中提到的”利用 WebLogic 组件漏洞挖矿”等案例,根源在于攻击者会将新出的漏洞利用加入到自己的武器库,并快速扫描互联网上可用脆弱主机并入侵。在安全漏洞爆发的开始阶段,安全团队需要检查企业生产环境大量的服务器是否受到影响,如是则进行临时缓解,等待安全补丁发布并进行升级,通过剧本可以显著提升处置效率。

由于生产环境有比较复杂,所以剧本还需要做大量的环境判断工作,以提高处置的准确率。例如需要关注当前安全漏洞处置的阶段,是漏洞刚曝光,安全设备已有缓解策略,还是已经有完整的安全更新,每种情况都需要做相应的处置。此外,TTL很小的容器环境中,不应对容器实例进行安全评估,而应对容器仓库的镜像进行评估。

如下为安全处理的流程图,当{X}集合非常大时,剧本的执行效率会非常高,而且通过闭环化的安全评估,最终可以使所有受到影响的终端得到及时修复,整个过程是完整、一致和可验证的。

图7 处理流程图

由于流程较为复杂,此处就不给出具体的剧本伪代码了,有兴趣的同学可自行编写。

 

2.3 编排自动化后不需要人了吗?

既然编排可以通过脚本化的剧本实现,那是否就不需要安全运营团队,实现全自动的流程实现秒级响应呢?

诚然,编排可以将以往大量繁琐、重复的人工活动变成自动化的流程,从而大大提高处置效率。然而,不可否认编排系统还需要人的参与,原因有两点:

  1. 安全运营始终是安全团队根据现有的需求建立安全体系,该体系中大量的工作是非技术的人力投入,安全工具也只是技术体系中的一个辅助手段,所以编排系统只是一个不错的补充,不能代替现有的流程。
  2. 攻防情势总是在变化,剧本只能处理已知的流程,当出现新的安全威胁或处置请求时(特别是阻断、隔离和删除操作),如果没有专家参与和确认,容易产生严重的后果。

 

3 下一代安全编排

安全控制器为自动化安全功能提供了驱动数据平面资源的能力,编排系统为自动化安全业务提供了驱动控制平面(安全策略)的能力,所以两者提供了自顶向下的敏捷自动化的能力。但剧本中如何指示安全应用目前大部分还是通过简单的程序控制逻辑,缺乏对环境变化的适应性。

3.1 智能化决策

可预见,自动化和智能化结合会是安全编排的未来:首先通过学习以往经专家处置事件的报告,以及建立自学习的攻防靶场,下发策略后评估效果,训练得到模型和参数;当运行时获知安全事件后,剧本可通过分析当前的安全上下文,做出准确的判断,进而进行一系列合理有效的处置。

分析过程中,剧本可以通过人工智能或机器学习的算法,构造输入事件、输出策略的模型和参数,如通过深度学习的模型可以隐藏决策过程中的特征集合,但同样能够得出正确的结论,而非使用现有剧本的if-then这样的固定规则,避免攻击者通过改变若干变量就可绕过安全处置。

当然,如果防守方采用了人工智能的方式,攻击者也会利用人工智能寻找决策模型中的过拟合部分,进行自动化攻击,这就对决策的机器学习模型的健壮性和稳定性提出了要求。

3.2 策略冲突消除

应用策略的目标、颗粒度、作用域是业务相关的,所以多个安全应用之间的策略可能会出现不一致的地方,比如DLP应用A发现虚拟网络中出现数据泄露,需要对10.0.0.0/16网段的主机进行隔离;而BCM应用B则认为网络地址为10.0.0.10的主机是重要资产,通信不能中断,那么此时编排系统是否能获知下发的策略是否存在冲突,甚至在策略下发之前就预测并消除潜在的策略冲突。

在《软件定义安全》一书的1.2.2和4.3.4小节介绍了NFV和SDN方面的策略冲突消除的工作,从笔者的经验来看,根据业务的特性,为策略定义优先级,是消除冲突的可行的方法。但即便如此,也不能完全保证通过算法冲突消除是合理的,所以让应用和运营者感知到发生的潜在策略冲突,也是编排系统需要支持的功能。

3.3 跨厂商的剧本兼容

前面我们提到,安全控制器无法支持所有厂商的设备,那就可能出现没有安全控制器支持的第三方应用。那么会出现以下场景:客户C1侧有厂商A的防护设备DA,但未接入安全控制器,则运营者快速根据X的接口编写了应用APP1和剧本PB1,PB1通过APP1向DA下发策略,而如果运营者发现另一个客户C2也有此需求,但C2只有厂商B的防护设备DA,那就只能再编写新的应用APP2和剧本PB2,虽然PB1和PB2大体相差不大,但调用应用部分还是有区别。随着剧本中调用的第三方应用频次和类型增加,剧本的管理复杂度会呈指数级上升。

所以是否能够对应用的语义本身做一层抽象,实现相同功能的应用也形成池化,编排引擎通过应用语义和剧本需求寻找到合适的应用,然后通过应用适配器下发策略。

 

总结

在网络对抗过程中,攻击者手法多变,防守者所处的环境上下文、拥有的安全能力也难标准化,所以造成了既有固定的安全机制难以有效对抗恶意攻击。安全编排可编写特定场景下的剧本,灵活调度安全能力,是解决上述难题的有效手段。

尽管安全编排有诸多优点,同样也存在很多挑战。例如:

攻防对抗日益加剧,攻击者能在小时级利用新漏洞导入已有武器库,防守方也同样需要在小时级完成漏洞分析和规则更新,以及部署相关安全能力,这就要求安全公司具有快速响应能力,企业安全团队具有一定的编码能力,对安全应用和剧本做一定的微调以适应其环境。

此外,企业环境纷繁复杂,安全编排系统只有驱动各个厂商的安全设备和安全工具,才有可能编写适合自己环境的剧本。这就要求安全编排系统从一开始就具备第三方应用介入的能力,且能在持续运营中实现安全能力的正反馈闭环。正所谓海纳百川,有容乃大。

Linux hook函数简单实践

#起因
最近对hook函数比较感兴趣,希望能捕获所有某种系统调用,看网上有一篇文章(http://opensourceforu.com/2011/08/lets-hook-a-library-function/) 介绍hook malloc函数,但可能内核实现不同,4.4.0上有问题。特写一篇文章进行更新。

原文中,hook函数中调用printf,其实printf、fprintf等函数都会再调用malloc函数,导致segment fault。正确的方式应该是用snprintf写入内存,然后调用write函数输出。同理,如果在hook open函数的时候,调用了open函数,也会造成segment fault的问题。

#示例
a.c:

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
int main(void)
{
int p;
printf("calling from main...\n");
p=(int *)malloc(10);
if(!p)
{
printf("Got allocation error...\n");
exit(1);
}
printf("returning to main...\n");
free(p); /
freeing memory from heap */
printf("freeing memory...\n");
return 0;
}

prog2.c

#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <dlfcn.h> /* header required for dlsym() */
#include <unistd.h>

/* lcheck() is for memory leak check; its code is not shown
here /
void lcheck(void);
void print(const char
format, ...);

void* malloc(size_t size)
{
static void* (my_malloc)(size_t) = NULL;
print("inside shared object...\n");
if (!my_malloc)
my_malloc = dlsym(RTLD_NEXT, "malloc"); /
returns the object reference for malloc /
void *p = my_malloc(size); /
call malloc() using function pointer my_malloc /
print("malloc(%lu) = %p\n", size, p);
lcheck(); /
calling do_your_stuff function */
print("returning from shared object...\n");

return p;

}

void free(void* p){
static void (my_free)(void ) = NULL;
if (!my_free)
my_free = dlsym(RTLD_NEXT, "free"); /* returns the object reference for free /
my_free(p); /
call malloc() using function pointer my_free */
print("free %p\n", p);
return;

}

int open(const char pathname, int flags, mode_t mode){
static int (
my_open)(const char *, int , mode_t ) = NULL;
if (!my_open)
my_open = dlsym(RTLD_NEXT, "open"); /* returns the object reference for open /
int res = my_open(pathname, flags, mode); /
call malloc() using function pointer my_open */
print("open %s, flags: %d, mode: %u\n", pathname, flags, mode);
return res;
}

ssize_t read(int fd, void buf, size_t count){
static int (
my_read)(int ,void*, size_t) = NULL;
if (!my_read)
my_read = dlsym(RTLD_NEXT, "read"); /* returns the object reference for open /
ssize_t size= my_read(fd, buf, count); /
call malloc() using function pointer my_open */
print("read fd %d, buf: %s, count: %u, read size: %u\n", fd, buf, count, size);
return size;
}

ssize_t recv(int sockfd, void buf, size_t len, int flags){
static int (
my_recv)(int ,void*, size_t, int) = NULL;
if (!my_recv)
my_recv = dlsym(RTLD_NEXT, "recv"); /* returns the object reference for open /
ssize_t size= my_recv(sockfd, buf, len, flags); /
call malloc() using function pointer my_open */
print("recv fd: %d, buf: %s, len: %u, flags: %d, read size: %u\n", sockfd, buf, flags, size);
return size;
}

int accept(int sockfd, struct sockaddr addr, socklen_t *addrlen){
static int (
my_accept)(int ,struct sockaddr*, socklen_t) = NULL;
if (!my_accept)
my_accept = dlsym(RTLD_NEXT, "accept"); /
returns the object reference for open /
ssize_t size= my_accept(sockfd, addr, addrlen); /
call malloc() using function pointer my_open */
print("accept fd: %d, addr: %u, len: %u, fd: %u\n", sockfd, addr, addrlen, size);
return size;
}

ssize_t write(int fd, const void buf, size_t count){
static int (
my_write)(int ,const void*, size_t) = NULL;
if (!my_write)
my_write = dlsym(RTLD_NEXT, "write");
ssize_t size= my_write(fd, buf, count);
print("write %d, buf: %s, count: %u, write size: %u\n", fd, buf, count, size);
return size;
}

void lcheck(void)
{
print("displaying memory leaks...\n");
/* do required stuff here */
}

void print(const char* format, ...){
static char buf[1024*2];
char tmp[1024];

static int logfd = -1;
if (!my_open)
    my_open = dlsym(RTLD_NEXT, "open");

if (!my_write)
    my_write = dlsym(RTLD_NEXT, "write");

if (!my_close)
    my_close = dlsym(RTLD_NEXT, "close");

if(logfd <0 || lseek(logfd, 0, SEEK_CUR)<0){
    logfd = my_open(logfile, O_RDWR | O_CREAT| O_APPEND, 600);
}


va_list argptr;
va_start(argptr, format);
vsprintf(buf, format, argptr);
va_end(argptr);
//int res = my_write(1, buf, strlen(buf));
int res = my_write(logfd, buf, strlen(buf));
if(res <0){
    perror("write error");
}

}

然后编译,运行:


gcc prog2.c -o libprog2.so -ldl -fPIC -shared
LD_PRELOAD=/home/liuwenmao/hook/libprog2.so /usr/sbin/sshd -D -p 9999

很奇怪的是sshd会有问题,root下面运行客户端会有错误:

root@node10:~/hook# LD_PRELOAD=/home/liuwenmao/hook/libprog2.so /usr/sbin/sshd -D -p 9999

#------客户端----
liuwenmao@node10:~$ ssh localhost -p 9999 -l test
test@localhost's password:
Permission denied, please try again.
test@localhost's password:
close[31596] 4
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-78-generic x86_64)

  • Documentation: https://help.ubuntu.com
  • Management: https://landscape.canonical.com
  • Support: https://ubuntu.com/advantage

1 package can be updated.
0 updates are security updates.

*** System restart required ***
Last login: Fri Sep 29 15:51:02 2017 from ::1
write error: Bad file descriptor
write error: Bad file descriptor
write error: Bad file descriptor
write error: Bad file descriptor
test@node10:~$

但是在普通用户下sudo是ok的:

liuwenmao@node10:~/hook$ LD_PRELOAD=/home/liuwenmao/hook/libprog2.so sudo /usr/sbin/sshd -D -p 9999

#------客户端----
liuwenmao@node10:~$ ssh localhost -p 9999 -l test
test@localhost's password:
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-78-generic x86_64)

  • Documentation: https://help.ubuntu.com
  • Management: https://landscape.canonical.com
  • Support: https://ubuntu.com/advantage

1 package can be updated.
0 updates are security updates.

*** System restart required ***
Last login: Fri Sep 29 15:51:20 2017 from ::1
test@node10:~$

猜测可能是ssh有一些suid等操作,对LD_PRELOAD有一些影响。

探讨

作为检测方来说,其实用户态函数hook并不是一种要的选择,因为
1. 攻击者可以检测环境变量,如果存在LD_PRELOAD,就可以认定有监测程序,作为处置方式也很简单,要不unset掉这个环境变量,这样检测方就无法hook了;要不直接放弃这台主机,避免被捕获下一步的攻击样本。
2. 检测方法并不可扩展,一方面,需要hook很多很多很多函数,例如新建文件描述符就涉及到open、accept、listen等函数,如果漏掉一个,就可能监控不全;另一方面,很多程序是非预期的,例如docker新启动一个容器,就可能会将所有的环境变量清空,这样默认场景下是无法监控到容器内部的操作的(虽然容器里的进程是docker run的子进程)
3. hook函数编写较为复杂,至少它调用的方法不能是hook函数之一。