主动信息收集

主动信息收集

  • 直接与目标系统交互通信
  • 无法避免留下访问的痕迹
  • 使用受控的第三方电脑进行探测
    • 使用代理或已被控制的主机
    • 做好被封杀的准备
    • 使用噪声迷惑目标,淹没真实的探测流量
  • 扫描
    • 发送不同的探测,根据返回结果判断目标状态
  • 识别活着的主机
    • 潜在的被攻击目标
  • 输出一个 IP 地址列表

osi model

有些网络设备(路由器/防火墙等等)会过滤不规则数据包,使探测失效

1. 二层发现

  • 概览

    • 优点:扫描速度块、可靠
    • 缺点:不可路由,只能发现本网段内
    • 协议:ARP
  • arping

    1
    2
    3
    $ arping 1.1.1.1 -c 1
    $ arping 1.1.1.1 -d
    $ ping 1.1.1.1 -c 1 | grep "bytes from" | cut -d " " -f 4 | cut -d ":" -f 1
    • -c 发送数据包的数量,1 表示只发一个报文
    • -d 发现重复IP。即不同 MAC地址 有同样 IP。(ARP地址欺骗)
    • grep “bytes from” 筛选结果行
    • cut -d “ “ -f 4 以空格分隔,筛选出第4段

    arping 只能对某个IP探测,无法对网段探测,如需对整个网段探测,需要脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
    if [ "$#" -ne 1 ]; then
    echo "Usage - ./arping.sh [interface]"
    echo "Example - ./arping.sh eth0"
    echo "Example will perform an ARP scan of the local subnet to which eth0 is assigner"
    exit
    fi

    interface = $1
    prefix=$(ifconfig $interface | grep 'inet addr' | cut -d ':' -f 2 | cut - d ' ' -f 1 | cut -d '.' -f 1-3 )
    for addr in $(seq 1 254); do
    arping -c 1 $prefix.$addr | grep "bytes from" | cut -d ' ' -f 5 | cut -d '[' -f 2 | cut -d ']' -f 1
    done
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 网段探测脚本
    # 版本不同代码会有所不一样,此脚本在 kali 2021.1 上测试通过
    #!/bin/bash
    if [ "$#" -ne 1 ]
    # "$#" 表示参数个数, -ne = not equal
    # if 后要有空格,[]内与表达式间也要有空格
    # if [ "$#" != 1 ] 也可以
    then
    echo "Usage - ./arping.sh [interface]"
    echo "Example - ./arping.sh eth0"
    echo "Example will perform an ARP scan of the local subnet to which eth0 is assigner"
    exit
    fi

    interface=$1
    prefix=$(ifconfig $interface | grep 'inet ' | cut -d ' ' -f 10 | cut -d '.' -f 1-3 )
    for addr in $(seq 1 254); do
    arping -c 1 $prefix.$addr | grep "bytes from" | cut -d ' ' -f 5 | cut -d '(' -f 2 | cut -d ')' -f 1
    done
  • nmap 二层发现

    nmap 二层发现用的参数 -sn

    1
    2
    3
    4
    5
    6
    # 扫描网段下主机
    $ nmap -sn 192.168.1.0/24
    $ nmap -sn 192.168.1.1-254

    # 根据 ip list 扫描,一行一个地址
    $ namp -iL iplist.txt -sn
  • Netdiscover

    • 专用于二层发现
    • 可用于无线和交换网络环境
    • 主动
      • netdiscover -i eth0 -r 1.1.1.0/24
      • netdiscover -l iplist.txt
    • 被动
      • netdiscover -p
        • 原理:将网卡置成混杂模式,收取给本网卡 ip/mac 地址的数据包
      • 主动 arp 容易出发报警
  • Scapy

    • pyhon 库、也可作为单独的工具使用:抓包、分析、创建包、修改、注入网路流量
    • ARP().display(),显示 ARP 包
    • ARP() 可以对包的各字段丢该,如 ARP().pdst = “192.168.1.1”
    • sr1(), 发送包:ar1(arp=ARP())

2. 三层发现

IP、icmp 协议
优点:可路由、速度比较快
缺点:速度比二层慢,被边界防火墙过滤

  • ping

    • ping 1.1.1.1 -c 2 # 发2个包
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      #!/bin/bash
      if[ "$#" -ne 1 ]; then
      echo "Usage - ./pinger.sh [/24 network address]"
      echo "Example - ./pinger.sh 1.1.1.0"
      echo "Example will perform an ICMP ping sweep of the 1.1.1.0/24 range"
      exit
      fi
      prefix=$(echo $1 | cut -d '.' -f 1-3)
      for addr in $(seq 1 254); do
      ping -c 1 $prefix.$addr | grep "bytes from" | cut -d '' -f 4 | cut -d '.' -f 1 &
      done
  • traceroute 路由追踪

    • 通过 ttl 值实现,ttl 先设为1,第一跳会反馈一个包,再发一个包,ttl = 2
      • traceroute 返回路由器离主机较近的那个网卡的 ip
      • ping -R 返回路由器离主机较远的那个网卡的 ip
  • scapy

    1
    2
    3
    4
    5
    6
    7
    $ ip = IP()
    ip.dst = "1.1.1.1"
    ping = ICMP()
    resp = sr1( ip/ping, timeout=1)
    resp.display()
    # 与上面等价
    sr1(IP(dst="1.1.1.1")/ICMP(), timeout=1)
    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
    26
    27
    28
    # python 脚本
    #!/usr/bin/python

    import logging
    import subprocess
    logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
    from scapy.all import *

    if len(sys.argv) !=2 :
    print "Usage - ./pinger.sh [/24 network address]"
    print "Example - ./pinger.sh 1.1.1.0"
    print "Example will perform an ICMP ping sweep of the 1.1.1.0/24 range"
    sys.exit()

    address=str(sys.argv[1])
    prefix=address.split(".")[0] + "." + address.split(".")[1] + "."+ address.split(".")[2] + "."

    # file : ip_list
    # filename=str(sys.argv[1])
    # file = open(filename, 'r')
    # for addr in file :

    for addr in range(1,254):
    a = sr1(IP(dst=prefix+str(addr)) / ICMP(), timeout=0.1, verbose = 0)
    if a == Node:
    pass
    else :
    print prefix + str(addr)
  • nmap

    1
    2
    3
    # 与二层发现一样用 -sn,如果目标与本主机在同一网段,发 arp 包,不在同一网段则发 ICMP 包
    # nmap 一般会综合各层来实现
    $ nmap -sn 1.1.1.1-255
  • fping

    ping 本身不支持对 ip 段发 ping 包

    1
    2
    3
    4
    $ fping 1.1.1.1 -c 1
    $ fping -g 1.1.1.1 1.1.1.2
    $ fping -g 1.1.1.0/24
    $ fping -f iplist.txt
  • hping

    • 能过发送几乎任意 TCP/IP 包
    • 功能强大但每次只能扫描一个目标
    1
    2
    3
    4
    $ hping3 1.1.1.1 --icmp -c 2

    for addr in $(seq 1 254); do
    hping3 1.1.1.$addr --icmp -c 1 >> handle.txt & done

3. 四层发现

判断 ip 是否在线,不对端口做精确判断

  • 优点
    • 可路由且结果可靠
    • 不太可能被防火墙过滤
    • 甚至可以发现所有端口都被过滤的主机,准确度比3层高
  • 缺点
    • 基于状态过滤的防火墙可能过滤扫描
    • 全端口扫描速度慢
  • TCP
    • TCP未建立连接直接发 ACK,会回复RST
    • SYN——SYN/ACK、RST
  • UDP
    • 端口未开放时,发送UDP,会回复ICMP 端口不可达

1. scapy

  • TCP

    未建立连接,直接发 ACK 包,会回复 RST

    • scapy
      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
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      i=IP()
      i.dst="1.1.1.1"
      t=TCP()
      t.flags='A'
      r=(i/t) # 请求,完成的3层4层包
      a = sr1(r, timeout=1)
      a.display()

      # 等价于
      a = sr1(IP(dst="1.1.1.1")/TCP(dport=80, flags='A'), timeout=1)
      ```
      ```python
      # ACK_Ping
      #!/usr/bin/python
      import logging
      logging.getLogger("scapy.running").setLevel(logging.ERROR)
      from scapy.all import *

      if len(sys.argv) !=2 :
      print "Usage - ./ACK_Ping.py [/24 network address]"
      print "Example - ./ACK_Ping.py 1.1.1.0"
      print "Example will perform a TCP ACK ping scan of the 1.1.1.0/24 range"
      sys.exit()

      address=str(sys.argv[1])
      prefix=address.split(".")[0] + "." + address.split(".")[1] + "."+ address.split(".")[2] + "."

      # file : ip_list
      # filename=str(sys.argv[1])
      # file = open(filename, 'r')
      # for addr in file :

      for addr in range(1,254):
      response = sr1(IP(dst=prefix+str(addr)) / TCP(dport=2222, flags='A'), timeout=0.1, verbose = 0)
      try:
      if int(response[TCP].flags) == 4 :
      print prefix + str(addr)
      except:
      pass
  • UDP

    端口未开放时,发送UDP,会回复ICMP 端口不可达

    • scapy
      1
      a = sr1(IP(dst="1.1.1.1")/UDP(dport=33333), timeout=1)
      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
      26
      27
      # python udp 四层探测
      #!/usr/bin/python
      import logging
      logging.getLogger("scapy.running").setLevel(logging.ERROR)
      from scapy.all import *

      if len(sys.argv) !=2 :
      print "Usage - ./UDP_Ping.py [/24 network address]"
      print "Example - ./UDP_Ping.py 1.1.1.0"
      print "Example will perform a UDP ping scan of the 1.1.1.0/24 range"
      sys.exit()

      address=str(sys.argv[1])
      prefix=address.split(".")[0] + "." + address.split(".")[1] + "."+ address.split(".")[2] + "."

      # file : ip_list
      # filename=str(sys.argv[1])
      # file = open(filename, 'r')
      # for addr in file :

      for addr in range(1,254):
      response = sr1(IP(dst=prefix+str(addr)) / UDP(dport=2222 ), timeout=0.1, verbose = 0)
      try:
      if int(response[IP].proto) == 1 :
      print prefix + str(addr)
      except:
      pass

2. nmap

nmap 在 三、四层扫描很强

1
2
3
4
5
6
7
# -PU53 UDP IMCP 不可达
# 53指端口号
# -sn 不作端口扫描,只作主机发信啊
$ nmap 1.1.1.1-254 -PU53 -sn

# -PA80 TCP ACK RST
$ nmap 1.1.1.1-254 -PA80 -sn

3. hping3

准确性不高

1
2
# 主机在线:ICMP Port Unreachable
$ hping3 --udp 1.1.1.1 -c 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 未验证
#!/bin/bash
if[ "$#" -ne 1 ]; then
echo "Usage - ./udp_hping.sh [/24 network address]"
echo "Example - ./udp_hping.sh 1.1.1.0"
echo "Example will perform an UDP ping sweep of the 1.1.1.0/24 range"
exit
fi
prefix=$(echo $1 | cut -d '.' -f 1-3)
for addr in $(seq 1 254); do
hping3 $prefix.$addr --udp -c 1 >> r.txt;
done
grep Unreachable r.txt | cut -d " " -f 5 | cut -d "=" -f 2 >> output.txt
rm r.txt
1
2
# TCP
$ hping3 1.1.1.1 -c 1
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
if[ "$#" -ne 1 ]; then
echo "Usage - ./tcp_hping.sh [/24 network address]"
echo "Example - ./tcp_hping.sh 1.1.1.0"
echo "Example will perform a TCP ping sweep of the 1.1.1.0/24 range"
exit
fi
prefix=$(echo $1 | cut -d '.' -f 1-3)
for addr in $(seq 1 254); do
hping3 $prefix.$addr -c 1 >> r.txt;
done
grep ^len r.txt | cut -d " " -f 2 | cut -d "=" -f 2 >> output.txt
rm r.txt

hping TCP 使用的是发送一个 flag 位全为0的包,如果返回的包 ACK、RST 为1说明主机在线

4. 端口扫描

4.1 UDP

1. Scapy

  • 端口关闭:ICMP port unreachable
  • 端口开放:没有回包
  • 误判(路由器拦截)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/python
import logging
logging.getLogger("scapy.running").setLevel(logging.ERROR)
from scapy.all import *
import time
import sysy

if len(sys.argv) !=2 :
print "Usage - ./udp_scapy.py [/24 network address]"
print "Example - ./udp_scapy.py 1.1.1.0"
print "Example will scan UDP ports "
sys.exit()

ip=str(sys.argv[1])
start=int(sys.argv[2])
end=int[sys.argv[3]]

for port in range(start, end):
a=sr1(IP(dst=ip)/UPD(dport=port), timeout=5, verbose=0)
time.sleep()
if a==None:
print port
else:
pass

2. Nmap

1
2
3
4
5
6
7
# 扫描默认指定端口
$ nmap -sU 1.1.1.1
# 扫描所有端口
$ nmap 1.1.1.1 -sU -p-
# 扫描指定范围端口
$ nmap 1.1.1.1 -sU -p1-1000

  • 不指定端口,默认使用常见的1000个端口
  • 特征:ICMP host-unreachable

4.2 TCP

TCP 情况比 UDP 复杂很多
所有 TCP 扫描方式都是基于三次握手的变化来判断目标端口状态

  • TCP 端口扫描
    • 基于连接的协议
    • 三次握手
    • 隐蔽扫描
      • 不建立完整连接(三次握手),或者不发 SYN 包
      • 应用日志不记录扫描行为,应用层不会有记录
    • 僵尸扫描(条件苛刻:闲置系统、系统使用递增的IPID)
        1. 扫描者先控制一台僵尸机,这台僵尸机要求足够闲置,很少发生甚至不发生网络行为;
        1. 扫描者向僵尸机发送一个 SYN/ACK 包,这时僵尸机会回复 RST 包,并且 IPID = x;
        1. 扫描者伪装僵尸机的 ip 发送给目标机一个 SYN 包,目标机会回复僵尸机 SYN/ACK 包,此时僵尸机会回复目标机 RST 包,并且 IPID=x+1;
        1. 扫描者向僵尸机发送 SYN/ACK 包,此时如果僵尸机收到过目标机的 SYN/ACK 包,并回复过 RST 包,此时回复扫描机的应该是 IPID=x+2 的 RST 包。
    • 全连接扫描

1. 隐蔽端口扫描

  • scapy:

    sr1(IP( dst=”192.168.60.3”)/TCP(dport=80), timeout=1, verbose=1 )

    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
    26
    #!/usr/bin/python
    import logging
    logging.getLogger("scapy.running").setLevel(logging.ERROR)
    from scapy.all import *
    import sys

    if len(sys.argv) !=4 :
    print "Usage - ./syn_scan.py [Target-IP] [First Port] [Last Port]"
    print "Example - ./syn_scan.py 1.1.1.1 1 100"
    print "Example will TCP SYN scan ports 1 through 100 on 1.1.1.1"
    sys.exit()

    ip=str(sys.argv[1])
    start=int(sys.argv[2])
    end=int[sys.argv[3]]

    for port in range(start, end):
    a=sr1(IP(dst=ip)/TCP(dport=port), timeout=5, verbose=0)
    time.sleep()
    if a==None:
    pass
    else:
    if int(a[TCP].flag)==18:
    print port
    else:
    pass
  • nmap

    1
    2
    3
    4
    $ nmap -sS 1.1.1.1 -p 80,21,25  # nmap 不加 -sS 参数端口扫描默认用的就是此方式
    $ nmap -sS 1.1.1.1 -p -65535 --open
    $ nmap -sS 1.1.1.1 -p- --open
    $ nmap -sS -iL iplist.txt -p 80,21,22
  • hping3

    1
    2
    3
    4
    $ hping3 1.1.1.1 --scan 80 -S  # -S syn包
    $ hping3 1.1.1.1 --scan 80,21 -S
    $ hping3 1.1.1.1 --scan 0-65535 -S
    $ hping3 -c 10 -S --spoof 1.1.1.2 -p ++1 1.1.3 # 伪造源地址,从端口1开始,每次递增1发10个包,且必须能想办法看到被伪装机的结果

2. 全连接端口扫描

很容易出发报警

  • scapy

    全连接扫描对 scapy 比较困难

1
2
3
4
5
6
7
8
#!/usr/bin/python
import logging
logging.getLogger("scapy.running").setLevel(logging.ERROR)
from scapy.all import *

response = sr1( IP(dst="1.1.1.1")/TCP(dport=80, flags='S') )
reply = sr1( IP(dst="1.1.1.1")/TCP(dport=80, flags='A', ack=(response[TCP].seq+1)) )
# 实际上 os 内核会认为 syn/ack 是非法包,直接发 rst 断开连接
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
26
27
28
#!/usr/bin/python
import logging
logging.getLogger("scapy.running").setLevel(logging.ERROR)
from scapy.all import *

SYN = IP(dst='1.1.1.1.')/TCP(dport=25, flags='S')

print "----sent---"
SYN.display() #显示要发的包

print "---RECEIVED---"
response =sr1(SYN,timeout=1, verbose=0) # 发 SYN 包并收 SYN+ACK 包
response.display()

# 实际上在此系统内核会发 RST 包
# 解决办法,使用 iptables 过滤,内核发出去的包也会经过 iptables 过滤掉再发出去
# $ iptables -A OUTPUT -p tcp --tcp-flags RST RST -d 1.1.1.1 -j DROP
# $ iptables -L 查看规则

if int(response[TCP].flags) == 18: # SYN+ACK
print("\n\n---SENT---")
A = IP(dst='1.1.1.1'/TCP(dport=25, flags='A',ack=(response[TCP].seq +1))) # ACK
A.display()
print "\n\n--RECEIVED--"
response2=sr1(A,timeout=1,verbose=0)
response2.display()
else:
print "SYN-ACK not returned"
  • nmap

    1
    2
    3
    4
    5
    # 默认 1000 个常用端口
    $ nmap -sT 1.1.1.1 -p 80
    $ nmap -sT 1.1.1.1 -p 80,21,25
    $ nmap -sT 1.1.1.1 -p 80-2000
    $ nmap -sT -iL iplist.txt -p 80
  • dmitry

    • 功能简单,但是用简便
    • 默认150个常用端口
1
2
$ dmitry -p 1.1.1.1
$ dmitry -p 1.1.1.1 -o output.txt
  • nc
    1
    2
    $ nc -nv -w 1 -z 1.1.1.1 1-100  # -w 1 超时时间    -z 超时尝试下一个端口
    $
1
2
3
4
5
# 重新获得网卡地址
sudo dhclient eth0

# ssh 软件
putty