一文带你快速了解会话固定攻击
什么是会话固定攻击
之间我写文章专门讲过xss攻击,csrf攻击,发现还挺受读者朋友们欢迎。今天就网络攻击的话题再讲一种网络攻击方式,那就是会话固定攻击。这种攻击和csrf攻击非常类似,都是在用户的cookie上做文章,想办法冒充用户,然后做一些只对自己有好处的事情。
简单说下会话攻击的流程,这样大家会对这种攻击有一个完整的认识:
- 黑客进入目标系统,但是并没有登录,只是为了拿到目标系统给自己的sessionID.
- 黑客将这个sessionID拼接到目标系统的登录接口(我们假设目标系统是银行系统)。拼接后的url长这个样子
https://bank.com/login?sessionID=目标系统给黑客的sessionID
- 黑客将上面的链接包装成一个【xx银行发福利了,点击登录即可领取新年多重好礼】的超链接文本,通过短信发送给很多很多人。有些用户为了拿到银行的免费大礼包点击了陌生短信中的链接,然后登录银行app
- 银行app将链接中的sessionID作为用户登录后的sessionID,用户登录成功后,也就意味着黑客也可以使用这个sessionID冒充用户查看用户的一些私人信息,比如账户余额等。但黑客的野心显然不止这点,他们还会将用户的钱转到自己的钱包中,能转多少是多少…
代码演示
下面我用代码演示一下上述的过程:
下面是银行服务器的代码
const express = require('express');
const session = require('express-session');
const MemoryStore = require('memorystore')(session); // 使用内存存储会话
const app = express();
// 配置会话
const store = new MemoryStore({
checkPeriod: 86400000 // 清理过期会话的时间间隔
});
// 配置会话
app.use(session({
secret: '7b09c869cf04011d6af56827bf1d916890f30caf52ff631113bfeb8c5d129b459ec258e1a6642d640e7725d0282305c8fc941bdca15d2e719f6bdc938de232e3',
resave: false, // 只有会话修改了,才保存会话
saveUninitialized: false, // 即使会话初始化后,才保存会话
cookie: {
maxAge: 3600000 // 会话有效期为 1 小时
},
store: store
}));
// 存储会话信息的对象
const sessionStorage = {};
// 生成一个会话 ID 供黑客使用
app.get('/generateId', (req, res) => {
req.session.isLoggedIn = false;
sessionStorage[req.session.id] = req.session; // 括号类是属性,右边是值
res.send(`可用于攻击的会话 ID: ${req.session.id}`);
});
// 登录接口
app.get('/login', (req, res) => {
// 校验用户的账号密码是否正确
// 将用户信息保存到会话中
// 拿到登录地址的url中的sessionID参数,找到对应的session
const sessionId = req.query.sessionID;
if (sessionId) {
// 模拟用户使用攻击者提供的会话 ID 登录
const storedSession = sessionStorage[sessionId];
// 从sessionStorage中取出session,如果取到了,就登录成功
if (storedSession) {
req.session = storedSession;
req.session.isLoggedIn = true;
sessionStorage[sessionId] = req.session;
res.send(`登录成功!用户的sessionID为:${sessionId}`);
return;
}
}
res.send('登录失败!');
});
// 转账接口
app.get('/transfer', (req, res) => {
console.log(`当前用户的sessionID为:${req.session.id}`);
if (req.session.isLoggedIn) {
res.send('转账成功!');
} else {
res.send('您还未登录,请先登录');
}
});
// 启动服务器
const port = 3000;
app.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});
这段代码中一共提供了三个接口:
- 黑客获取sessionID的接口。这个接口模拟的是黑客进入了银行的登录页面,但是他假装登录失败了,然后黑客拿到此次登录的sessionID, 用于拼接会话固定攻击所需要的url
- 登录接口
- 转账接口
我们先使用google浏览器模拟黑客假装登录失败,然后获取到此次会话的sessionID
然后拿着这个sessionID制作用于攻击的url,最终得到的url是:http://localhost:3000/login?sessionID=b_ShJNH6BReBXpBighhsATDldXinumyG
接下来我们使用edge浏览器模拟用户点击黑客通过短信发给自己的这个链接,登录银行的网站
现在我们继续模拟一下黑客,看看他是否可以调用转账接口,将用户的钱转到自己的账户中
通过页面我们得知黑客成功了
会话固定攻击的原理
下面我们通过代码分析一下黑客为什么能够成功冒充用户,这主要还是因为银行服务器的代码中直接使用了登录链接中的sessionID, 当用户通过账号密码登录成功后,使用的还是黑客之前的会话,所以黑客才可以通过这个会话冒充用户。
整个过程就好像用户将自己的密码设置成黑客预先提供的密码,那么黑客自然能够这个密码自由进入这个系统,冒充用户做各种操作。
防御会话固定攻击
前面知道了会话固定攻击的原理,主要还是因为银行使用了url上的sessionID,所以防御措施就是:
- 在代码中不要使用url上的sessionID,这是一种设计上的缺陷。
- 即使多个客户端之间要通过传递sessionID实现单点登录,也不要通过url参数的形式去传递sessionID,而是通过请求头去传递sessionID,因为黑客不可能通过一个url链接去设置用户向服务器发送请求的请求头。
- 使用https。因为http是明文传输,一旦发生会话劫持,用户很容易知道用户的明文账号密码或者会话信息,这是十分危险的。
- 在拿到用户的cookie信息后,对请求的来源做判断,判断当前请求的IP是不是和用户最初登录的IP保持一致,如果不是,那么就是黑客在冒充用户,这个方法可以同时防止会话固定攻击和csrf攻击。
案例中的示例代码
最后的总结
这篇文章讲了会话固定攻击的流程,以及为什么这种攻击能够得手的原理(也就是前提条件),并且使用代码演示了整个攻击过程,最后也提供了一些防御会话固定攻击的手段。
觉得有收获的朋友可以点个赞,您的鼓励就是我最大的动力!