一、米特尼克的圣诞攻击
1、攻击背景
在Unix世界中,可以很容易地给予信任。 假设用户在机器A和机器B上都有一个帐户,为了使两者之间的麻烦最小,就可以在它们之间建立全双工的信任关系。 在A的主目录中,创建一个 .rhosts 文件:
echo "hostB 用户名" > .rhosts
,在B的主目录中做同样的操作,现在,用户可以使用任何 r* 命令来操作另一台服务器,这些命令将只验证地址。
1994年圣诞节,Kevin Mitnick 攻击了下村勉的机器,主要用到了两种技术:IP源地址欺骗和TCP序列号预测
IP源地址欺骗:ip协议并不安全,其源地址可被随意修改,再配合另外一些操作就可以冒充其他主机与目的主机通信
TCP序列号预测:每个TCP报文都会带一个序列号,在数据传输过程中用于对报文段的确认,而在三次握手时需要序号来完成连接。TCP序列号是由网络协议栈生成,通过多次发送SYN包,从收到的SYN+ACK包中的序列号可以预测出对方序列号生成的规律(已被修复,现在初始序列号生成是随机的),这个操作必须在对方主机不活跃时进行,否则其他的TCP连接会扰乱这种规律,这也是为什么选在圣诞节攻击的原因。
2、攻击过程
这次攻击主要涉及四个对象:
- apollo:攻击者先入侵了这台主机,以隐藏自己的行踪
- target:目标下村勉的机器,最终目的是要访问这台机器上的文件
- x-terminal:已经与 target 建立了受信任的连接(不能再伪装成它与 target 连接)
- server:与 x-terminal 通过 .rhosts 互相信任
首先来捋一遍攻击思路:
apollo 需要获得对 target 的访问,此时 x-terminal 已有对 target 的受信任连接,攻击者的目的是劫持这个连接。劫持这个连接,需要先控制 x-terminal,如何控制x-terminal呢?需要被它信任,如何被它信任?需要修改 .rhosts 文件,如何远程修改.rhosts文件呢?需要以它信任的机器的身份,建立一个TCP连接,在TCP连接中传递命令,所以最终是要冒充 server 与 x-terminal 建立连接
开始攻击:
- apollo 利用 SYN 洪泛填充 server 上端口513的“半开”连接队列达到阻塞的目的,使得它不会再响应任何新的连接要求
- apollo 向 x-terminal 发送一串 SYN 请求来预测 x-terminal 生成初始序列号的规律
- apollo 冒充 server 向 x-terminal 发起连接,虽然收不到 SYN-ACK(发到 server 了,但 server 由于阻塞不会响应也不会发送拒绝包),但是预测了序列号,就可以继续回复 ACK 来建立连接
- 以 server 身份向 x-terminal 发命令,修改 rhosts 文件,让它信任任何来源
- apollo 连接 x-terminal,植入内核模块,劫持与 target 的连接
- 成功访问 target,随后发送 RST 到 server 释放阻塞的连接
3.、问题思考
1、为什么说ip传输协议是不可靠的?
- ip协议是无连接的,尽最大努力交付的,并且只对头部进行校验
- 其源地址等信息可由发送方任意设置
2、详细描述一下TCP三次握手
- A --> SYN(seq) --> B
- B --> SYN + ACK(ack=seq+1,seq) --> A
- A --> ACK(ack=seq+1) --> B
3、port的作用是什么?
- 复用 / 分用
4、SYN/ACK/RST分别在什么时候使用?
- SYN:请求建立连接
- ACK:确认连接
- RST:复位因某种原因出现的错误连接,也可以用来拒绝非法数据和请求
5、进行 SYN flooding 以实现 DoS 的可信server的端口号是多少?为什么要选择这个端口?能不能换用一个其他端口?
- 513,因为要冒充这个端口与 x-terminal 建立连接发送远程指令,换其他 <1024 的特权端口也可以
6、在成功添加后门后,攻击者为何要发送RST释放可信Server中的TCP连接?
- 打扫作案现场
二、网络命令
1、route(可加 -n 不解析名字而直接显示ip)
- default 默认路由,当一个数据包的目的网段不在路由记录中,该数据包就会发送到默认路由
- link-local 为链路本地地址,是设备在本地网络中通讯时使用的地址,主要作用于DHCP服务器故障时,或DHCP超时,用于和网段内或广播域中的设备通信,不通过路由器转发,故 Gateway 为 0.0.0.0
- 直连网段的路由记录,当数据包发到直连网段时,数据包不经路由转发,故网关为 0.0.0.0
- Flag标志解释
- U:有效
- G:连接路由,无该标志表示直连目的地址
- H:具体主机,而非网段
2、ping:发送 icmp 包来测试可达性
3、traceroute(路由跟踪)
- 首先它发送一份TTL字段为1的IP数据包给目的主机,处理这个数据包的第一个路由器将TTL值减1,然后丢弃该数据报,并给源主机发送一个ICMP报文(“超时”信息,这个报文包含了路由器的IP地址,这样就得到了第一个路由器的地址),然后traceroute发送一个TTL为2的数据报来得到第二个路由器的IP地址,继续这个过程,直至这个数据报到达目的主机
4、nslookup:域名查询
5、whois
- 一种查询和响应协议,广泛用于查询存储了Internet资源的数据库,例如域名、IP地址块或自治系统
6、netstat
- 显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况
- -t 只显示 TCP 相关,-l 显示处于监听状态的socket,-n 不显示名字而现实真实ip,-p 显示进程pid
三、ARP协议安全
ARP 协议
ARP用于通过目标机 ip 获取目标机 MAC 地址
arp 请求封装在数据链路层报文中:
在发送 arp 请求时,以太网首部的目的地址为全1,表示广播,而 arp 报文部分的目的mac为全0,因为还不知道目的主机的mac地址,正要通过以太网广播询问
有一种ARP包叫做 Gratuition ARP(无故ARP或者免费ARP),作用有:
- 告诉其他计算机自己的 IP 地址和 MAC 地址
- 检测 IP 地址冲突,当一台主机发送了免费 ARP 请求报文后,如果收到了 ARP 响应报文,则说明网络内已经存在使用该 IP 地址的主机
- 更新其他主机的 ARP 缓存表
1、引入ARP缓存的目的是什么
每一台主机维护了一张 ARP 缓存表,其中存储着 <ip, mac> 的映射,该表内的每一个条目都是有有效期的,且它为无状态的,即,只要收到新的ARP信息,ARP缓存表就会更新
在向外发包时,可以直接通过 ARP 缓存来获取目的 IP 和目的 MAC 的映射关系,而不用通过ARP协议来获取
2、ARP缓存中毒的攻击方法和效果是什么
向目标主机发送 ARP 响应报文,效果是,更新目标机器的 ARP 缓存,目标机器发送数据包到指定 ip 时,该包会被发送到我们指定的机器上
四、IP协议安全
针对IP分片的攻击
- DOS攻击:攻击者构造两个分片,一个分片偏移为0,第二个分片偏移为64800,因为IP分片乱序到达,接收方会等待其他分片,同时为其他分片分配空间,这就意味着一个数据包会使用64K的空间,这段空间会持续保留15-225秒
- TearDrop:攻击者构造两个分片,第二个分片被完整包含在第一个分片中,即第二个分片偏移量大于第一个分片的偏移量,且偏移量+分片2总长度小于第一个分片最后一个字节的位置。这种攻击能够成功的条件是,接收主机处理重叠分片的机制是:忽略第二个分片重叠的部分,计算 end2-end1,拷贝这一部分内容形成完整报文。那么当 offset2 > offset1 而 end2 < end1 时,end2-end1 用无符号整数计算将会得到一个非常大的数,从而榨干可用内存
1、为什么需要IP分片?
一个 IP 报文最长可以达到 65535 字节,但网络硬件限制了帧的大小,以太网限制为 1500 字节
2、IP分片如何重组?
IP分片中有 id 字段和 offset 以及 flag 字段,id 相同表示属于同一个IP报文,offset 则表示某分片在原 IP 报文中的偏移量,flag 则有是否分片、更多分片等标志位
3、包过滤防火墙,通过过滤SYN包,防止外部连接。攻击者如何绕过该过滤规则?
可以使用微小碎片攻击,因为防火墙过滤包时,只会将过滤规则应用于初始片段,STD 5,RFC 791规定,每个互联网模块能够转发68B的最小数据报,不允许进一步分段,而IP首部长度最长可达到60B,这样,第一个片段只包含8B的内容,在TCP的情况下,这足以包含源和目标端口号,但它将强制TCP标志字段进入第二个片段,从而使得SYN包绕过过滤规则
重叠碎片攻击,即第一个片段标志位 SYN=0,ACK=1 且足够长,此时可以顺利通过过滤,第二个片段与第一个片段有重叠,且重叠部分含标志位为 SYN=1,如果主机使用后面覆盖前面的算法,此时就成功绕过
五、ICMP协议安全
ICMP是网际报文控制协议,主要是因为IP协议有可能出现报文发送过程中的错误。譬如目标不可达,TTL过期等,需要通知发送方错误原因
有多种不同的ICMP报文,每种报文都有自己的格式,但是所有的ICMP报文都有三个共同的字段:type,code,checksum,不同类型的 icmp 报文通过 type 和 code 来区分:
一些常见的 icmp 报文:
- type=8,code=0:回送请求,也就是ping请求
- type=0,code=0:会送应答,也就是ping应答
- type=5:改变路由(重定向),code=0(对特定网络路由的改变),code=1(对特定主机路由的改变)
- type=4,code=0:源点抑制,为了给 ip 协议增加某种程度的流量控制和拥塞控制
其中,type=5 的重定向报文,是路由器用来向主机通知网络拓扑的变化,在以下情况下, 路由器会向主机发送重定向报文:
在上面的情况中,主机的IP地址是10.0.0.100,主机的路由表中默认网关是10.0.0.1,现在主机100要向 网络X 发送数据包。根据自己的默认网关,100将数据发给了G1。G1检查自己的路由表,发现要到达 网络X,需要经过G2,G1会将数据包转发给G2,同时发现数据包的源地址 10.0.0.100 和 G2 在同一个网段上,这时 G1 会向 Host 发送重定向报文,告诉它下次直接发给 G2 会快一点
主机总会假设路由器的信息更权威,路由器总是对的,所以它会更新自己的路由表,但无论是 icmp 报文还是封装它的 ip 报文都是可以伪造的,这就出现了安全问题
1、什么是Smurf攻击?如何防止?
一种分布式拒绝服务攻击,冒充目标机 IP,向网络中广播 ICMP回送请求报文,那么目标机器就会收到大量的 ICMP回送应答报文,这使得受害者忙于处理 ping 包而无法正常工作
可以用以下方式防止攻击:
- 配置各个主机和路由不响应ICMP请求或广播
- 配置路由不转发定向到广播地址的数据包(1999年以前默认是转发的)
2、什么是ICMP重定向攻击?如何防止?
在同一个局域网下,攻击机 A 伪造成目标机的网关 B,对目标机器发送重定向报文,使得目标机器报文被重定向到指定主机上,从而可以达到无法上网或劫持流量的目的
可以不允许重定向来防止这样的攻击
六、TCP协议安全
1、什么是SYN flooding攻击?效果是什么?如何防止?
主机会维持一个 TCP 半开连接队列,该队列大小有限,一旦满了,主机就会丢弃其他的 TCP 连接报文
那么 SYN flooding 攻击的本质就是用大量的虚假 IP,对目标机器发送 SYN 报文,使得对方的连接队列被占满,从而使得目标机无法处理新的TCP连接
防止:设置tcp_syncookie=1(这也是系统默认值)。在TCP三次握手过程中,在ACK报文未到达之前,主机不为此次连接分配内存空间,而用序列号识别三次握手
2、端口扫描的原理是什么?
使用 nmap 扫描目标地址,它会首先一个个地尝试与一些端口的连接,如果端口有响应,并且能够建立起连接,那么nmap就能够判断得出来,这个端口是open的
3、nmap -sT 和 nmap -sS的区别?
nmap -sT <ip> # connect扫描, 发送SYN报文,若对方回复SYN+ACK,则会回复ACK建立连接
nmap -sS <ip> # 半开扫描,发送SYN报文,若对方回复SYN+ACK,则会回复RST中断连接, 需要sudo权限
4、nmap -sA扫描原理是什么?
向目标机发送 ACK 报文,若端口被过滤,则不会有任何响应,否则,无论端口是开放还是关闭,均会返回RST报文,可以检测端口是否被过滤
配合 nmap -sF 扫描(发送 FIN 报文,端口开放或被过滤不会有响应,端口关闭会收到 RST)就可以准确知道端口状态
5、nmap -idle扫描原理是什么?
通过僵尸主机(zombie)查看目标机器端口状态,zombie 需要满足攻击期间不会自己向外发送报文,且最好能与靶机具有信任关系
- 攻击机向zombie发送 SYN|ACK 报文,得到RST报文并获取到 IP ID
- 攻击机伪造成zombie向靶机发送SYN报文,靶机该端口若开放,则会向zombie发送 SYN|ACK 报文,否则会发送RST报文
- 攻击机向zombie发送 SYN|ACK 报文,得到RST报文并获取到 IP ID
- 比较两次 IP ID,若相隔为1,说明靶机该端口未开放,若相隔为2,说明靶机端口开放。若相隔更大,说明zombie并不是好的僵尸主机
七、防火墙
防火墙,置于内部网络和外部网络之间,内部网络与外部网络通信的必经之地
1、防火墙有哪些种?
包过滤防火墙
也被成为无状态防火墙,静态防火墙。通过ACL规则控制数据流,最核心的五元素为:源IP,目的IP,源端口,目的端口,协议,在一次会话中,这五个元素是不会变化的,所以也叫静态防火墙
优点:实现简单,处理速度快
缺点:难以处理分片,不支持复杂协议,不能防止应用层的恶意攻击(因为它无法检测应用层数据)
应用级网关代理防火墙
客户端与服务器并不建立真正的连接,都是客户端通过访问代理服务器来访问服务器,通信时,数据包均要通过代理服务器的检测
优点:对数据的控制上升到应用层
缺点:每个服务均要实现一个特定的安全代理服务
状态防火墙
会话过程中的数据包并不独立,而是有前后连接状态的。在同一个会话中,五元组不会变化,但是各种状态标识、分片等都是可以变化的
例如:TCP三次握手的过程,若是突然收到一个ACK报文,那么该报文需要丢弃
2、NAT的作用是什么?
网络地址转换,使得一个整体机构以一个公用 IP 地址出现在Internet上。因为IPv4地址不够用,才产生了NAT,即内网中的主机想要访问互联网时,会经过NAT路由器将源地址转化为公网ip后进行访问
3、正向代理和反向代理
正向代理
正向代理代理客户端,主要作用可以是kxsw之类。
反向代理
反向代理代理服务器,主要为了防止服务器的ip地址直接暴露,同时也可以在反向代理上实现请求过滤,在内网安全领域起到很大的作用
4、iptables语句作用分析
iptables/netfilter 是Linux内置的防火墙,通过一些表和规则链过滤包,每张表拥有的规则链数目不同,包进来时按顺序通过每张表上的某条链:
我们可以为每条链指定规则,常用参数有:
基本链管理:
-L, --list [chain]:列出规则;
-F, --flush [chain]:清空指定的规则链上的规则;
-P, --policy [chain] target 制定链表的策略 (ACCEPT|DROP|REJECT)
基本规则管理:
- -A, --append chain rule-specification:追加新规则于指定链的尾部;
- -D, --delete chain rulenum:根据规则编号删除规则;
- -D, --delete chain rule-specification:根据规则本身删除规则;
# 使用 -t 指定表,默认为 filter 表
# 指定 INPUT 链丢弃所有包
$ sudo iptables -P INPUT DROP
# 在 INPUT 链上添加规则,源端口为80的tcp报文可以进来
$ sudo iptables -A INPUT -p tcp --sport 80 -j ACCEPT
八、rootkit
unix下的安全模型
DAC
自主访问控制,即文件拥有者能够决定文件的访问权限
MAC
强制访问控制,在DAC之上构建的可选模块,DAC 验证通过且系统支持的话会验证 MAC
用户管理机制
真实UID:当前登录的 uid
有效UID:当前进程以哪个用户ID来运行的
保存的UID:有效用户ID的一个副本,与SUID权限有关
SUID权限:若一个文件有SUID权限,那么若某用户对它有执行权限,那么执行时就以root权限执行
setuid(uid)
详解ruid:
真实uid
euid:
有效uid
suid:
saveduid
- 用户具有超级用户权限的时候,
setuid(uid)
可将本进程的三个uid均置为uid
- 否则,仅当该 id为 ruid 或者 suid 时,该 id 对 euid 起效
- 若不满足上述情况,报错
- 用户具有超级用户权限的时候,
seteuid(uid)
seteuid(uid)
只请求将euid
置为uid
举例:
若以 user身份登录系统并打开shell,然后在shell中打开一个文件,这个文件有s位(setuid),那么此时
ruid
为 user 的uid
,euid
应该为文件拥有者的 ruid
1、什么是rootkit?
Rootkit中的root来自于unix。在unix主机系统管理员账号为root账号,该账号拥有最小的安全限制,完全控制主机并拥有了管理员权限被称为“root”了这台主机。然而,能够暂时性的控制住主机还不够,因为管理员可以采取一定的安全措施,譬如打补丁。因此Rootkit的作用在于“能维持root权限的一套工具”。它的目的是隐藏自己以及恶意程序,达到长期在目的主机存在并收集信息的目的。
2、LKM的好处是什么?
- 定义:LKM是Linux内核为了扩展其功能所使用的可加载内核模块
- 优点:动态加载,无须实现整个内核。基于此特性,LKM常被用做特殊设备的驱动程序
3、 请描述系统调用劫持的过程
系统调用过程
- 应用程序代码调用系统调用函数 xyz,该函数为一个包装系统调用的库函数
- 库函数xyz负责准备向内核传递的参数(系统调用号),并触发软中断切换到内核态
- 系统调用通过软中断80进入内核态,在 IDT(中段描述符表)中找到 80 对应的中断处理程序,即系统调用处理函数
- 系统调用处理函数通过传进来的系统调用号来调用系统调用服务例程。
那么在上述过程中,linux内核空间中存储着一张表叫做 系统调用表 (system_call_table),该表存储着 系统调用号对应的系统调用服务例程的地址
劫持过程
根据上述过程,那么如何劫持系统调用就很清晰明了。我们要做的就是修改系统调用表,使目标系统调用号对应的系统调用服务例程变为我们自己写的函数即可。
- 找到系统调用表(SCT)的首地址
- 修改SCT中目标系统调用服务例程的地址 (修改时需要关闭写保护,写完需要恢复写保护)
如何寻找SCT地址?
- 在旧版本的linux内核中,SCT是直接被导出的,也就是符号表中是存储了SCT符号的,这样内核程序就可以直接使用。
- 在2.6版本内核后,SCT就不再被直接导出了,于是另外一种查找SCT的方法是通过
/boot/System.map
来查找 - 然而在更高版本中,
System.map
也没有了。这时可以通过/proc/kallsyms
来查询,这个文件中保存了所有linux内核符号。
4、为何Unix可以做到一切皆文件?
虚拟文件系统(VFS)是这样一种特性的关键所在。它是 Linux 内核中的一个软件层,用于给用户空间的程序提供文件系统接口,同时,它也提供了内核中的一个抽象功能,允许不同的文件系统共存。
为了能够支持各种实际文件系统,VFS 定义了所有文件系统都支持的基本的、概念上的接口和数据 结构;同时实际文件系统也提供 VFS 所期望的抽象接口和数据结构,将自身的诸如文件、目录等概念在形式 上与VFS的定义保持一致。换句话说,一个实际的文件系统想要被 Linux 支持,就必须提供一个符合VFS标准 的接口,才能与 VFS 协同工作
因此,VFS 的意义如下:
- 向上,对应用层提供一个标准的文件操作接口
- 对下,对文件系统提供一个标准的接口,以便其他操作系统的文件系统可以方便的移植到Linux上
- VFS内部则通过一系列高效的管理机制,比如 inode cache, dentry cache 以及文件系统的预读等技术,使得底层文件系统不需沉溺到复杂的内核操作,即可获得高性能
- 此外VFS把一些复杂的操作尽量抽象到VFS内部,使得底层文件系统实现更简单
九、缓冲区溢出
1、什么是缓冲区
因为计算机程序频繁地需要操作从文件、网络等各种来源读入的一段数据,因此程序经常需要分配一段有限大小的内存空间,以便将数据存储在其中。这段内存空间便成为缓冲区。缓冲区溢出就是写入到缓冲区或者从缓冲区读取的数据超出了缓冲区可以容纳的范围。
缓冲区溢出包括各种类型,如栈溢出、堆溢出等。我们主要关注的类型是栈缓冲区溢出。
2、什么是返回地址
当在一个函数中调用另一个函数,被调用的函数结束时需要返回原函数,接着执行调用语句的下一条指令,那么下一条指令的地址就是被调用函数的返回地址
3、汇编语言中,call指令的作用是什么?
通过修改指令指针寄存器eip实现跳转,用于实现子程序,具体来说,调用 call 时:
- 将当前 eip(注意eip中存的是下一条要执行指令的地址)压入栈中
- 跳转到 call 后面指定的地址执行
与之相配合的还有一个 ret 指令,用于在子程序中返回,调用时:
- 出栈,赋给 eip,回到原来的程序继续执行
4、请描述当函数调用发生时,进程地址空间中栈帧的变化
首先,把函数调用的参数压栈,然后eip(返回地址)压栈,ebp(栈底)压栈。接下来,更新ebp的值为esp的值(栈对齐),将esp减少一个特定的值(与调用函数内部申请空间相关),为调用函数获取一定的栈空间。
5、如何防止缓冲区溢出攻击
字符串存储时是从低地址向高地址增长,那么缓冲区溢出攻击的主要思路就是:将shellcode(生成shell的代码,执行它可以得到一个shell)置于内存的某处,然后通过缓冲区溢出覆盖将函数的返回地址指向shellcode,防范方法有:
- Stack canary保护:在函数入口处从gs(32位)或fs(64位)段内获取一个随机值,如果攻击者利用栈溢出修改到了这个值,导致该值与存入的值不一致,函数将抛出异常并退出程序
- 防止栈运行
- 栈起始地址随机化