使用 wireshark 高效,准确地鉴别出入站的恶意流量
这篇博文实际上是 http://shayi1983.blog.51cto.com/4681835/1558161
的继续,讲解一些实用的数据包分析技巧,帮助安全架构师们迅速,准确地定位那些恶意的数据包;
在分秒必争的安全突发事件与安全取证工作中,这些高效的方法显得格外重要.
**********************
wireshark 网络层地址解析
wireshark 中的网络层名称解析功能,与真实场景的 DNS 解析刚好相反,默认情况下,wireshark 抓取的数据包是不会将网络层源 IP 与目标 IP 解析到主机名的,
除非在主菜单 view -> name resolution ->勾选 "enable for network layer",这样,wireshark 会实时用本地配置的 DNS 服务器信息,对其发送解析请求与接收应答,而这个过程刚好与正向解析--从域名或主机名到 IP 的过程相反。
多数情况下,勾选"enable for network layer"后,在 wireshark 抓取数据包前,名称解析的工作已经由操作系统上的 DNS 客户端服务完成,但也有少数情况,从域名或主机名到 IP 的解析是在 wireshark 抓取并显示数据包后完成的,此时的解析结果仅保存在内核缓冲区里,wireshark 不会主动"更新"这里面的信息,因此你也许会看到,即便勾选了 "enable for network layer",列表中的某些数据包的 IP 地址还是无法被"反向"显示为域名或主机名.
此时,你可以单击主菜单 view -> reload ,这将强制 wireshark 从系统那里更新名称解析的结果并显示。
实际上,wireshark 请求本地 DNS 客户端进行名称解析,本地 DNS 客户端的实现取决于操作系统,在 windows server 2008 R2 SP1 中,本地 DNS 客户端叫做
DNS Client(dnscache) ,这是一个 windows 服务例程,
一个纳宿服务的进程,叫做 svchost.exe ,在启动的时候,会加载动态链接库
dnsrslvr.dll ,并且以多线程的方式启动数个 DNS Client(dnscache) 服务,
它负责处理所有网络应用程序的名称解析请求(提交给 DNS 服务器,或查看本地的 host 文件),如果禁用该服务,那么任何网络应用程序,Chrome web browser 也好,wireshark 也好,都无法正常工作,这一点必须注意。
值得指出,Dnscache 仅仅是系统服务,负责在本地缓存通过网络解析到的域名—IP的映射,我们可以在cmd命令行下执行:
ipconfig /displaydns
来输出本机的dns缓存内容:
这些内容可以提供给浏览器使用,加速网页打开过程。
Dnscache服务并不负责具体的dns解析,
真正负责的是前文提及的某个加载了 dnsrslvr.dll 的 svchost.exe 进程中的一些线程,由这些执行在 dnsrslvr.dll 内特定代码逻辑的线程负责。(显然,dns查询包的发送,接收远程dns服务器的应答包等,必须由内核中的TCP/IP协议栈代码完成)
因此,我们停止并且禁用Dnscache服务,只是无法缓存解析结果:
并不会影响域名解析(浏览器和其他基于域名的网络应用程序照常工作),但是,如果杀掉载入了dnsrslvr.dll(或者dnsapi.dll)的 svchost.exe 进程,那么计算机就可能无法将域名解析成IP,因为解析功能是实现在这2个dll中。各位可以在虚拟机中创建快照,然后删除这2个dll,看看能否解析。
即便如上所示禁用了操作系统级别的dns缓存,浏览器自身也可以缓存dns解析结果,例如在Chrome的地址栏输入:
chrome://net-internals/#dns
将显示chrome自身缓存的dns解析结果:
****************************
****************************
wireshark 链路层 MAC 地址解析
这个解析唯一具有价值之处在于,它将 6 字节的 MAC 地址中的前 3 个 16 进制字节解析为网络设备(例如个人 PC 的网卡适配器,以及路由器)制造商的名称缩写。
注意,前 3 个 16 进制字节是由 IEEE 分配的,用于唯一标识各厂商的地址,而链路层 MAC 地址解析就是将其转换为可读性更强的厂商缩写名。
单击 wireshark 主菜单 view -> name resolution -> enable for MAC layer ,即可启用链路层 MAC 地址解析功能。
另外,通过单击主菜单 statistics -> show address resolution ,在打开的对话框中,你可以找到一个列表,包含有 wireshark 内置的所有厂商 MAC 地址与厂商缩写的对应关系,如下所示:
注意,即便这些信息能在渗透测试中帮助判断目标的基础设施类型,但是这些信息可以通过技术手段更改,因此并不总是准确,但是对于多数组织机构而言,我们可以认为这里的信息是可采用的。
*****************************
*****************************
关于 wireshark 的验证 "TCP 校验和"功能
一般来讲,在发送数据包前,发送方(的 TCP/IP 协议堆栈,通常作为操作系统内核的组成部分)使用某种摘要算法对该包计算,生成该包的校验和,然后在 TCP 首部的校验和字段中携带;接收方(的 TCP/IP 协议堆栈)对收到的包进行同样的计算,将计算结果与校验和字段中的值进行比对,如果两者相等,说明数据在传输的过程中是完整无损坏的,如果不相等,则取决于 TCP/IP 协议堆栈的具体实现,有可能
发送方在一个计时器到时后,还未收到接收方用以汇报该包完整的 ACK 包,那么发送方有可能重传先前发送的数据包,直到收到接收方的 ACK 包为止。
这个验证工作通常是由双方的操作作系统完成的,然而,你也可以使用 wireshark 的验证 "TCP 校验和"功能,对抓取到的包进行再次验证;
使用 wireshark 重复验证的好处在于,它可以明确地告诉你一个数据包的完整性与否,而操作系统不会自动发送消息通知你;
通过单击主菜单 edit -> Preferences ,打开首选项对话框,点击并展开左侧的 Protocols 树型节点,找到 TCP 协议,然后勾选右侧的 "Validate the TCP checksum if possible" 复选方块,这样 wireshark 会显示抓取到的数据包,其校验和是否正确。
谨慎使用这一功能,前面我有提到,真正进行验证的其实是操作系统,而 wireshark 如果验证校验和发现错误(此时,正确校验和的包已经再次通过双方系统发送与接收了,而 wireshark 捕获的是"重传"前的错误校验和包),则 wireshark 拒绝对一些 TCP 分段包进行重组装(尽管操作系统已经正确重新组装了"重传"的包)
从而,我们也就无法获得完整的数据包信息(通常是指 TCP 分段承载的应用层数据)
下面这张截图说明该数据包的 TCP 校验和经过 wireshark 验证,是正确的:
上面第一张截图是 TCP 校验和经过 wireshark 验证无误后的结果,如果验证出错,我们将在所选择数据包的详情窗口(位置在中间的窗口)中,看到被红色高亮显示的 TCP 头部,将其展开,就可以查看错误的校验和字段,如下截图所示:
除了上面截图中讲到的过滤表达式
tcp.checksum_good == 0
可以用来显示所有校验和错误的数据包之外,下面这个表达式也有相同的效果,当然,你也可以在上图的 "bad checksum: true" 字段右击鼠标,在弹出的上下文级联菜单选择 "apply as filter" -> "selected" 来达到相同目的,请自行实践!
tcp.checksum_bad == 1
顺便提一下,从上图可以很清楚地看到,过滤出来的所有校验和错误的数据包,基本上都是从本地客户端(很可能是 web 浏览器)发往远程 web 服务器的 HTTP 请求,
一般来讲,检测到这些数据包的 TCP 检验和错误,不会有太大的问题,因为校验和是给接收方验证的,如果发送方自行验证有无错误,那么校验和就失去其存在的意义了;
反之,如果在过滤列表中看到来自服务器返回的 HTTP 响应数据包,其校验和错误,那就完全不同,因为在这个场景中,本地客户端是接收方,如果验证出错,表明该数据包在传输的过程中损坏,或丢失,也有可能是被篡改;
尽管双方系统的网络协议堆栈可能已经正确地"重传"数据包,但既然 wireshark 检测到"曾经"有错误,那么作为网络工程师或安全架构师的我们,就应该检查自己这一端可控的链路状态(从物理层到应用层),确保后续稳定地发送与接收数据.
*********************************
*********************************
综合分析技巧举例1
拿到一个捕获的数据包文件样本,其中通常有成百上千个数据包等着我们去查看,如何快速地定位我们感兴趣的信息?
点击主菜单 "statistics" -> "Summary" ,会显示当前你所打开的捕获文件的概要信息,其中最有价值的信息,包括捕获第一个包的日期时间与最后一个包的日期时间,
以及由此计算出的整个捕获过程持续的时间(elapsed),数据包文件里的总字节数,单个数据包大小上限,链路层封装类型.....等等.
接下来需要关注的,应该是了解这个样本文件中,所有的端点(endpoints)以及
会话(conversations)
端点可以列出一张清单,包括捕获的包文件中,所有与本地通信的远程机器的 IP;
会话则显示一张更详细的清单,包括了通信双方的 IP 以及端口(TCP 或 UDP);
下面的截图显示出,从一个样本文件中提取出来的端点列表,通常我们仅关注
IPv4 端点,因为它可以帮助你判断是否连接到了任何恶意站点或机器,至于详细的出入站流量,应该使用会话来查看,因为它能列出本地端口与远程端口:
要打开端点列表,点击主菜单 "statistics" -> "Endpoints"
要打开会话列表,点击主菜单 "statistics" -> "Conversations"
*******************************
*******************************
综合分析技巧举例2
我们在访问一个网站的时候,浏览器通常需要下载大量的 HTML 代码,CSS 样式表,javascript 脚本文件,jepg/gif 图片,视频动画等等,才能完整呈现一个站点的主页,而且这些资源经常存储在各种独立的物理主机上;
有的站点主页甚至通过 <embed> ,<iframe> 等标签,跨域引用资源,例如各种第三方广告,读取用户在各大搜索引擎输入的字符串本地 cookie,再返回相关广告内容的 javascript API 等。。。。
要知道这些资源都是从哪些服务器下载回来的,是否下载了恶意的第三方站点上的脚本到本地并执行,除了可以通过浏览器开发者工具的网络模块来监视外(具体可以参考这篇博文 :http://shayi1983.blog.51cto.com/4681835/1553095)
还可以在访问前先启动 wireshark 进行抓包,当然,此时应该没有捕获任何流量,然后启动浏览器访问页面,这个时候任何可疑流量都会被抓取,经过一段时间后,停止抓包,然后分析得到的数据,从中寻找任何蛛丝马迹。
假设我们访问的一个论坛或社交网站的评论页面存在存储型跨站脚本漏洞,并且成功被攻击者利用了,我们的浏览器会试图访问这个被嵌入的恶意站点链接(假设你的浏览器没有配置任何安全策略来阻止运行第三方域的 javascript,或者安装类似 NoScript 的安全插件),如果你在后台运行 wireshark 抓包,就可以捕获相关的流量。
具体来讲:
浏览器访问任何主页上引用的第三方域之前,都需要进行 DNS 查询,而后才能通过得到的 IP 地址访问目标,因此,在 wireshark 中过滤出所有的 DNS 请求与应答数据包就非常关键;
要过滤(仅显示)DNS 流量最简单的方法,直接在 wireshark 的显示过滤文本输入框中键入 dns 后回车,然后点击右侧的 apply 按钮;但是这样做的显示结果中,会包含所有本地发送的请求流量与接收的应答流量,通常情况,我们更关注于:究竟浏览器查询了哪些域名的 IP 地址,然后从中找出 "evil.com"(下文用于指称非预期的或恶意站点)。
首先过滤出所有的 dns 包,然后在包列表的 Info 列中,选取任意一个带有 "Standard query"说明字串的包,正如其注释暗示的,这是类型为标准查询的 DNS 请求包,其后面跟着要查询的域名或主机名;
在中间的详情窗口中,展开该包的 "Domain Name System (query)" 头部,找到其中的 "Flags: 0x0100 Standard query" 字段,在其上右击鼠标,在弹出的上下文级联菜单中,选择 "apply as filter" -> "selected"(手段和前面讲的类似)
这样,就可以过滤出所有 DNS 查询包。
聪明的你或许也已经意识到了:直接在显示过滤文本框中键入
dns.flags == 0x0100
也可以达成相同的效果,事实就是如此,下面截图验证:
既然浏览器向 4.2.2.1 请求解析这些域名的地址,那么后者是否正确地给出查询结果了?这很重要,因为它决定了浏览器是否实际访问了 "evil.com"
下面的显示过滤表达式,可以找出所有的 DNS 应答包(来自名字服务器的):
dns.flags == 0x8180
上面列出的例子都是"间接"地分析浏览器可能访问了哪些与目标站点相关的其它站点,我们需要一份清单,列出浏览器访问的所有其它站点,以及下载的这些站点上面的具体资源(html,js,css,jepg,swf....)
要生成这个统计信息清单,在主菜单中点击 "statistics" -> "HTTP" -> "Requests" ,然后在打开的过滤器中直接点击 "Create Stat" ,这将会显示浏览器实际发送的所有 HTTP 请求,并且以站点的域名或主机名进行分类。
我们知道,任何英特网资源,包括前述组成页面的各种资源,都可以通过 HTTP 这个应用层协议承载并传输,例如,在线播放电影视频的站点,用 HTTP 传输流媒体(需要浏览器插件支持,例如 adobe shockwave flash 播放器用于解码视频流),
再如,51cto 下载站点,使用 HTTP 传输二进制文件等等。。。因此,wireshark 通过对浏览器向服务器发送的 HTTP 请求分析结果,来描述下载的资源,基本上是正确的。
*********************************
*********************************
综合分析技巧举例3
来看另一个例子,这里是一个捕获 facebook 站点登录过程的数据包样本文件,虽然生成该文件的时间点太古老了,站点的登录页面代码和验证逻辑可能发生变化,不过这里讲述的思维和做法应该是不随时间改变的.
这个样本文件以及前面使用的其它样本文件,都属于<wireshark 数据包分析实战>一书的配套资源,该资源可以从 51cto 下载站点搜索并下载.
默认情况下,在软件最上方的包列表窗口,以捕获到的时间先后来排序显示数据包,虽然这种做法没有问题,但是我们不能直观地看出,哪些数据包属于哪个 TCP 会话(以及对应的 TCP 数据流);
例如, web 服务器生成的 HTTP 响应体承载的页面 HTML 代码以及 js 等脚本,其大小通常远超过一个链路层"帧"能容纳的上限(从1500~1518字节不等,取决于帧的封装类型);
因此服务器的网络协议栈在收到 web 服务器生成的 HTTP 响应以及"有效载荷"后,需要将其拆成数个 TCP 分段,对每个分段打上标签(熟知的 TCP 序号),然后发送到客户端网络协议栈,后者再按照序号重组装成一个完整的 TCP 会话中的数据流(即 TCP 流),最后将这个数据流传递给在 TCP 目标端口号所指明的应用层进程(通常是 web 浏览器监听在 1024 以上的临时动态端口);
浏览器对收到的数据流进行分析,通常需要先解压以 gzip 格式压缩的 HTML 代码,还原出浏览器能识别的明文;
(压缩 HTTP 响应体中的应用数据,是为了加速数据传输的速度,以及更高效地利用各种链路的带宽资源,压缩策略取决于 web 服务器支持的特性,例如 apache 与 nginx 应该都支持以 gzip 格式压缩 HTML 页面代码,并且浏览器在先前的 HTTP 请求中,必须通过 Accept-Encoding 请求头部,告诉 web 服务器,自己能识别的压缩方案,这样服务器返回内容后才能正确解压)
解压后的整个数据流将会非常庞大,取决于页面设计的复杂与"花俏"程度,解压后的数据流可以达到数十 KBytes ,甚至数 MBytes(后面我们会以截图验证)
如果浏览器直接向用户显示解压后的数据,那么用户看到的,将会是一串带有左右尖括号的 ASCII 字符(HTML 标签),以及一堆含义不明的 javascript 代码(假设用户不是程序员),还有一些不能识别的编码字符(通常是 jepg,png 等图片的编码,需要相应编×××还原出图像);
所以,浏览器内核中的 HTML 解析器,CSS 解析器,javascript 解释器协同工作,根据每个 HTML 标签与 js 对该标签的操作,构建包含所有标签及其相对位置的抽象 DOM 树,再根据 CSS 对 DOM 上的各标签添加"样式",最后生成用于浏览器内部表示的页面雏形,当然这还不能立即向用户显示,需要进一步计算这些标签在屏幕上的预定位置,大小,也就是页面布局,确定哪个元素该放在屏幕的什么地方;
最后,浏览器调用操作系统提供的图形学 API 函数,包括 2D的,3D的(例如渲染以 WebGL 编写的页面,在 windows 中,这可能需要借助 Direct3D 来实现 ),以及各种图片×××,来"实际"渲染页面,这个过程中可能还需要借助各种浏览器插件,例如前面提到的 flash player ,来解码音频和视频,才能完整地将一个包含各种多媒体资源的页面呈现在用户眼前.
扯太远了,让我们言规正传,前面提到,我们手上有一个捕获整个 facebook 登录过程的 .pcap 格式样本文件,使用 wireshark 打开后,我们如何快速识别所有的 TCP 数据流(其中包含了各种登录过程中的 HTTP 请求与响应,以及各自承载的应用数据,这才是我们关心的)?
或者找出某个特定的数据包承载的数据(可能是单个 TCP 分段,)属于哪个 TCP 数据流?
按照如下方法来操作,首先在任意一个数据包上右击,在弹出的上下文级联式菜单中,选择 "Follow TCP Stream" ,这会弹出一个对话框,显示该数据包所属的完整的 TCP 数据流,同时你可以在显示过滤文本框中看到,wireshark 自动以某个表达式字串来过滤出所有属于相同 TCP 数据流的包。
注意,一个 TCP 数据流可能由数十乃至数百个 TCP 分段包组成,如果是这种情况, wireshark 将在包列表的 Info 列中,标识"TCP segment of a reassembled PDU",这意味着,这个包仅仅是一个重新组装的协议数据单元(PDU)中的一个 TCP 分段,我们可以展开一个 TCP 分段包的传输层头部,定位到 [SEQ/ACK analysics 字段](该字段是 wireshark 自行添加的统计信息,在链路上传输的原生数据包没有这个字段),其中的 "Reassembled PDU in frame : xx" 表明,wireshark 将该包以及其他属于相同 TCP 数据流的 TCP 分段包,在第 xx 帧中进行重组装操作,并向用户显示装配后的完整 TCP 数据流。
*****************************
综合分析技巧举例4