网络安全 频道

探测远程操作系统讲座

ICMP错误信息查询 -- 有些(聪明的)操作系统根据RFC 1812的建议对某些类型的错误信息发送频率作了限制。例如,Linux内核(在net/ipv4/icmp.h)限制发送“目标不可到达”信息次数为每4秒80次,如果超过这个限制则会再减少1/4秒。一种测试方法是向高端随机UDP端口发送成批的数据包,并计算接收到的“目标不可到达”数据包的数量。在nmap中只有UDP端口扫描使用了这个技术。这种探测操作系统方法需要稍微长的时间,因为需要发送大量的数据包并等待它们的返回。这种数据包处理方式也会对网络性能造成某种程度
的影响。

ICMP信息引用 -- RFC定义了一些ICMP错误信息格式。如对于一?端口不可到达信息,几乎所有操作系统都只回送IP请求头+8字节长度的包,但Solaris返回的包会稍微长一点,Linux则返回更长的包。这样即使操作系统没有任何监听任何端口,nmap仍然有可能确定Linux和Solaris操作系统的主机。

ICMP错误信息回显完整性 -- 我们在前面已谈到,机器必须根据接收到的数据包返回“端口不可到达”(如果确实是这样)数据包。有些操作系统会在初始化处理过程中弄乱了请求头,这样当你接收到这种数据包时会出现不正常。例如,AIX和BSDI返回的IP包中的“总长度”域会被设置为20字节(太长了)。某些BSDI、FreeBSD、OpenBSD、ULTRIX和VAX操作系统甚至会修改请求头中的IP ID值。另外,由于TTL值的改变导致校验和需要修改时,某些系统(如AIX、FreeBSD等)返回数据包的检验和会不正确或为0。有时这种情况也出现在UDP包检验和。总的说来,nmap使用了九种不同的ICMP错误信息探测技术来区分不同的操作系统。

服务类型(TOS) -- 对于ICMP的“端口不可到达”信息,经过对返回包的服务类型(TOS)值的检查,几乎所有的操作系统使用的是ICMP错误类型0,而Linux使用的值是0xC0。

片段(碎片)处理 -- 不同操作系统在处理IP片段重叠时采用了不同的方式。有些用新的内容覆盖旧的内容,而又有些是以旧的内容为优先。有很多探测方法能确定这些包是被如何重组的,从而能帮助确定操作系统类型。

TCP选项 -- 这是收集信息的最有效方法之一。其原因是:

1)它们通常真的是“可选的”,因此并不是所有的操作系统都使用它们。
2)向目标主机发送带有可选项标记的数据包时,如果操作系统支持这些选项,会在返回包中也设置这些标记。
3)可以一次在数据包中设置多个可选项,从而增加了探测的准确度。

Nmap在几乎每一个探测数据包中都设置了如下选项:

Window Scale=10; NOP; Max Segment Size = 265;
Timestamp; End of Ops;

当接收到返回包时,检查返回了哪些选项,它们就是目标操作系统支持的选项。有些操作系统(如较新版本的FreeBSD)支持以上所有选项,而有些(如Linux 2.0.x)则几乎都不支持。Linux 2.1.x内核支持以上所有选项。

如果有几个操作系统支持相同的选项,可以通过选项的值来进行区分。例如,如果向Linux机器发送一个很小的MSS值,它一般会将此MSS值返回,而其它系统则会返回不同数值。

如果支持相同的选项,返回值也相同,又怎么办呢?仍然可以通过返回选项的顺序进行区分。如Solaris系统返回‘NNTNWME’,而如果是Linux 2.1.122系统,相同的选项,相同的返回值,但顺序却有所不同:MENNTNW。

目前还没有其它操作系统探测工具利用TCP选项,但它确实非常有效!另外还有其它一些选项也可用于进行探测,如T/TCP支持等。

译者注:还有至少两种颇具攻击性的探测方法。由于它们能导致拒绝服务攻击,而这也是在nmap中没有实现这些方法的主要原因。

NMAP探测细节和结果

上面我们讨论了操作系统类型探测的多种技术(除了某些攻击性方法外)。这些技术都在nmap扫描器中实现。Nmap扫描器收集了众多操作系统端口打开和关闭时的特征,支持目前流行的Linux、*BSD和Solaris 2.5.1/2.6多种操作系统。

目前版本的nmap扫描器从一个文件中读取操作系统特征模板。下面是一个实例:

FingerPrint IRIX 6.2 - 6.4 # Thanks to Lamont Granquist
TSeq(Class=i800)
T1(DF=N%W=C000|EF2A%ACK=S++%Flags=AS%Ops=MNWNNT)
T2(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
T3(Resp=Y%DF=N%W=C000|EF2A%ACK=O%Flags=A%Ops=NNT)
T4(DF=N%W=0%ACK=O%Flags=R%Ops=)
T5(DF=N%W=0%ACK=S++%Flags=AR%Ops=)
T6(DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(DF=N%W=0%ACK=S%Flags=AR%Ops=)
PU(DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=E%ULEN=134%DAT=E)

让我们来看一下每一行的含义:

> FingerPrint IRIX 6.2 - 6.3 # Thanks to Lamont
Granquist

它说明这是一个IRIX 6.2 - 6.3操作系统特征,注释指出该特征由Lamont Granquist提供。

> TSeq(Class=i800)

它说明ISN特征是"i800 class",即每一个新序列号比上一个序列号大800的整数倍。

> T1(DF=N%W=C000|EF2A%ACK=S++%Flags=AS%Ops=MNWNNT)

T1代表test1。这个测试是向打开的端口发送带有多个TCP选项的SYN数据包。DF=N说明返回包的"Don't fragment"位必须没有设置。W=C000|EF2A说明返回包的窗口值必须为0xC000或0xEF2A。ACK=S++说明返回包的ACK值必须为初始化序列号加1。Flags=AS说明返回包的ACK和SYN标记位必须被设置。Ops=MNWNNT说明返回包的TCP选项及其顺序必须为:

> T2(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)

Test 2(第二个测试)向打开端口发送带有相同TCP选项的NULL(空)数据包。Resp=Y说明必须接收到返回包。Ops= 说明返回包中的所有TCP选项必须都没有被设置。‘%Ops=’匹配任意TCP选项。

> T3(Resp=Y%DF=N%W=400%ACK=S++%Flags=AS%Ops=M)

Test 3(第三个测试)向打开端口发送带有TCP选项的SYN|FIN|URG|PSH数据包。

> T4(DF=N%W=0%ACK=O%Flags=R%Ops=)

这是向打开端口发送ACK数据包。注意这里没有Resp=字符串。说明返回包不是必须的(例如数据包被丢弃或有防火墙)。

> T5(DF=N%W=0%ACK=S++%Flags=AR%Ops=)
> T6(DF=N%W=0%ACK=O%Flags=R%Ops=)
> T7(DF=N%W=0%ACK=S%Flags=AR%Ops=)

以上测试是针对关闭端口的SYN、ACK和FIN|PSH|URG数据包测试,并设置了相同的TCP选项。

>
PU(DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=E%ULEN=134%DAT=E)

这个是对“端口不可到达”信息的测试。DF=N前面已经介绍过了。TOS=0说明IP服务类型域应为0。接着的两个是IP包头总长度和返回IP包总长度(16进制值)。RID=E说明期望返回包RID值与发送的UDP包的值相同。RIPCK=E说明校验和应该正常(如果不正常则RIPCK=F)。UCK说明UDP包校验和也应该正常。ULEN=134是
UDP包长度为0x134。DAT=E说明正确返回UDP数据,这个是大多数情况下的缺省设置。

0
相关文章