• 数据包伪造替换、会话劫持、https劫持之探索和测试


    (一)数据包替换攻击

    该攻击过程如下:伪造服务器响应客户端的数据包。监听客户端的数据包,用预先伪造的数据包,伪装成服务器返回的数据发送给客户端。

    因为攻击者跟目标在同一个局域网,所以攻击者发送的数据包肯定比服务器的响应数据要快很多,只要数据包构造正确,就一定可以被客户端按正常的数据处理。

    这部分的重点和难点在于,要构造正确的数据包,需要根据攻击者的目的,修改数据包中的数据、MAC、IP、TCP(UDP)层的长度、校验值等多个字段的值,还要兼容多种网络协议,另外还需要高效的处理数据包。

    这部分内容对于熟悉tcp/ip协议栈的程序员来讲非常容易,唯一需要注意的坑就是,udp和tcp封包中的checksum字段的计算,其格式不是简单的tcp和udp包头字节的crc校验,而是:

    1. 先将checksum字段清零
    2. 再将ip数据包中的 原ip(dword)、目的ip(dword)、包含tcp或者udp包头在内的数据长度值(short)、ip包中的协议字段(short)这4个字段加上tcp或者udp的包头加上数据部分之和(该长度还要2字节对齐,假如长度是奇数的话还要再补一个0)计算出来的校验和值。
    3. 将计算的校验值写入包头。
      其结构体如下:
    typedef struct
    {
    	unsigned char SrcIP[IPV6_IP_SIZE];
    	unsigned char DstIP[IPV6_IP_SIZE];
    	unsigned short Protocol;
    	unsigned short PackLen;
    }IPV6FAKEHEADER, *LPIPV6FAKEHEADER;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    计算tcp和udp中校验和的代码大体如下所示:

    WORD Checksum::checksum(WORD *buffer,int size)
    {
    	unsigned long cksum = 0;
    	while(1>16) + (cksum&0xffff);
    	cksum += (cksum>>16);
    	return(unsigned short)(~cksum);
    }
    
    
    USHORT Checksum::subPackChecksum(char * lpCheckSumData,WORD wCheckSumSize,DWORD dwSrcIP,DWORD dwDstIP,unsigned int wProtocol)
    {
    	char szCheckSumBuf[MAX_SINGLE_PACKET_SIZE];
    	LPCHECKSUMFAKEHEADER lpFakeHdr = (LPCHECKSUMFAKEHEADER)szCheckSumBuf;
    	lpFakeHdr->dwSrcIP = dwSrcIP;
    	lpFakeHdr->dwDstIP = dwDstIP;
    	lpFakeHdr->Protocol = ntohs(wProtocol);
    	lpFakeHdr->usLen = ntohs(wCheckSumSize);
    
    	memcpy(szCheckSumBuf + sizeof(CHECKSUMFAKEHEADER),(char*)lpCheckSumData,wCheckSumSize);
    
    	*(DWORD*)(szCheckSumBuf + sizeof(CHECKSUMFAKEHEADER) + wCheckSumSize) = 0;
    
    	unsigned short nCheckSum = checksum((WORD*)szCheckSumBuf,wCheckSumSize + sizeof(CHECKSUMFAKEHEADER));
    	return nCheckSum;
    }
    
    • 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

    该模块基于winpcap开发。网络攻击的先决条件是能监听到目标的数据包,这是必须的前提条件。在Windows平台网络数据包开发包是winpcap,在linux上是libcap。

    各层封包的包头处理有很多细节需要注意。在实际场景中,抓到的数据包并不是mac层,而是大多是pppoe或者wlan格式,其包头格式如下:

    typedef struct {
    	char version : 4;
    	char type : 4;
    	unsigned char code;
    	unsigned short sessionid;
    	unsigned short len;
    	unsigned short protocol;
    }PPPOEHEADER, *LPPPPOEHEADER;
    
    
    typedef struct
    {
    	
    	unsigned char idhigh : 4;
    	unsigned char canonical : 1;
    	unsigned char priority : 3;
    	unsigned char id : 8;
    
    	unsigned short type;
    }HEADER8021Q, *LPHEADER8021Q;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    具体处理流程更多是包头协议格式的解析,在此按下不表。

    本程序支持tcp和udp数据包的伪造、欺骗攻击,其代码主要位于ReplacePacket.cpp中。其中,dns劫持就是一种较为简单的数据包替换攻击,其代码位于 PacketProc.cpp中,要实现攻击需要了解dns数据包的格式,读者请自行百度。其主要数据结构如下:

    typedef struct  
    {
    	unsigned short TransactionID;		//交易ID,发出和接收必须相同
    	unsigned short Flags;				//标志字段,发出和接收都应该修改该字段
    	unsigned short Questions;			//问题格式
    	unsigned short AnswerRRS;			//回答资源记录个数
    	unsigned short AuthorityRRS;		//认证资源记录个数
    	unsigned short AdditionalRRS;		//附加资源记录个数
    }DNSHEADER,*LPDNSHEADER;
    
    //中间的要解析的名称以一个非可打印字符开头,以0结尾,后面紧跟着解析的类型要求,和CLASS要求
    typedef struct  
    {
    	unsigned short	Name;				//名称,低字节为从开头的偏移地址,只想要解析的内容
    	unsigned short	Type;				//类型,0005为解析字符串,0001为解析IP地址
    	unsigned short 	Class;				//输入
    	unsigned short	HighTTL;			//生存周期
    	unsigned short	LowTTL;
    	unsigned short	AddrLen;			//解析的长度
    	unsigned int	Address;			//解析的内容
    }DNSANSWER,*LPDNSANSWER;
    
    
    typedef struct
    {
    	unsigned short	Name;				//名称,低字节为从开头的偏移地址,只想要解析的内容
    	unsigned short	Type;				//类型,0005为解析字符串,0001为解析IP地址
    	unsigned short 	Class;				//输入
    	unsigned short	HighTTL;			//生存周期
    	unsigned short	LowTTL;
    	unsigned short	AddrLen;			//解析的长度
    	unsigned char	Address[16];			//解析的内容
    }DNSANSWERIPV6, *LPDNSANSWERIPV6;
    
    
    typedef struct {
    	unsigned short dnstype;
    	unsigned short dnsclass;
    }DNSTYPECLASS,*LPDNSTYPECLASS;
    
    typedef struct {
    	unsigned short	Name;
    	unsigned short	Type;
    	unsigned short 	Class;
    	unsigned int	TTL;
    	unsigned short	AddrLen;
    }DNSANSWERHEADER, *LPDNSANSWERHEADER;
    
    • 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
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    如下以下视频中,当dns欺骗未开启时,在nslookup中查询到的www.baidu.com的IP地址是182.61.200.7,而当dns攻击开启时,www.baiducom的ip地址被替换为192.168.101.122,这个地址正好是本机的ip地址,本机上有一个服务器程序,监听443或者80端口的数据,这样就可以当作下一步https攻击的服务器。

    从wireshark可以清晰看到网卡发出的dns伪造数据包。
    在这里插入图片描述

    在这里插入图片描述

    (二)https劫持

    https劫持有多种方式可以实现,比如dns劫持方式和数据包转发。

    数据包转发方式较为复杂,各有各的实现方法。一般原理是:

    1. 在数据包监听处,有一链路层处理程序S,识别并修改ssl数据包,将目的mac和目的ip地址改为解析程序的mac和ip、并重新校验之后,从链路层发送。
    2. 解析程序在recv函数之后,会收到目的地址是自己的数据包,然后调用openssl接口,进入openssl接口处理部分,其返回结果是将https脱去后的明文数据。此时,解析程序可以当作中间人,将客户端数据发送给服务器的数据,从host取出真正的服务器地址,数据部分根据需要加工处理后发送给真正的服务器。对于服务器返回的数据,根据攻击者的目的,处理之后发送给真正的客户端。
    3. 最后,S需要将链路层监听到的、跟发送给解析程序相匹配的、返回数据包,在链路层修改原mac和ip地址,并重新校验之后,从链路层上放回原来的数据流中。

    另一种方式较为简单,其过程如下:

    1. 预先获取客户端要访问的域名,对其进行dns数据包替换攻击,将客户端对域名M的访问,定向到特定的主机H上
    2. 客户端想要访问M域名时,由于伪造的dns数据包中返回的地址指向H,故此时客户端程序会误以为H就是M.
    3. 在H主机上有一特定程序,采用中间人方式,对客户端的数据访问伪装成服务器,将客户端数据再次转发给真正的服务器,对于服务务器返回的数据,再次转发给真正的客户端。

    本程序采用第二种方法,主要的https中间人代码在sslEntry.cpp,sslProxyListener.cpp,sslProxy.cpp,makeCert.cpp,sslPublic.cpp等几个文件中,搬砖的工作暂且不表:)。

    在https劫持中一个重要问题就是证书问题。这里采取的方式是,将生成次级证书的根证书导入到本机的根证书授信中心,接下来利用此证书签名的二级证书和三级证书在chrome和edge中的访问都是没问题的,但是firefox有单独的证书认证体系,windows等操作系统认可的证书、包括我们我们导入的证书不在其认可范围之内。

    程序中实现了域名证书证书自动生成功能,可以根据客户端的clienthello数据包中的域名,动态生成域名证书。另外还支持自动检测和生成、导入根证书。

    程序运行需要预先安装openssl。

    在实际测试中,国内大厂包括阿里系,腾讯系的软件大都采用了https传输方式,但是也有极个别软件的服务器域名的ssl流量可以劫持成功,特别是某些Android移动端软件,ios端也发现过此种情况。当然,现在的趋势是验证机制越来越严格,难度越来越大。

    本实例程序运行时,会将ssl数据存放在output目录下的ssl.dat文件中,如下截图所示,当未开启ssl攻击时,浏览器访问正常;当开启ssl劫持后,浏览器依然正常,此时ouput目录下的ssl.dat中存放着https中的明文数据。从host或者域名可以验证我们刚才点击访问的网址,证明ssl劫持成功。

    在这里插入图片描述

    本次测试的具体代码下载地址:点击下载

    该项目具有tcp和udp数据包伪造替换、dns欺骗劫持、https中间人(mid in man)劫持攻击等多种功能。

  • 相关阅读:
    〖Python 数据库开发实战 - Python与Redis交互篇④〗- 利用 redis-py 实现集合与有序集合的常用指令操作
    安装sql server2019时报错,提示没有安装Visual C++ 2017 Redistributable,但是我已经下载好了,不知道为什么sql server会提示这个
    java并发编程:LinkedBlockingQueue详解
    Uservue 中 keep-alive 组件的作用
    行业应用之无限可能,就在亚马逊云科技re:Invent
    分布式执行引擎ray入门--(1)简介
    【大数据趋势】12月3日纳指大概率反弹到黄金分割附近,然后下跌,之后进入趋势选择期,恒指会跟随。感觉或许有什么大事情要发生,瞎猜中。
    端口映射的几种常见应用场景
    NLP(3)--利用nn反向计算参数
    2022年都在说软件测试饱和了,是真的吗?
  • 原文地址:https://blog.csdn.net/m0_37567738/article/details/130872460