CSRF防御及模拟CSRF攻击
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种攻击方式,攻击者可以诱使用户在已登录的应用中执行非本意的操作。为了防御这种攻击,许多Web应用会使用CSRF Token来验证请求的合法性。
0.csrf 攻击原理
2. 后端服务app.js 使用nodemon插件启动服务需全局安装nodemon app.js
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser'); // 用于解析请求体
// const cookies = require('koa-cookies');
const app = new Koa();
const router = new Router();
// 使用中间件解析请求体
app.use(bodyParser());
var listLog = []
let username = ''
router.get('/login', (ctx, next) => {
// 获取 url
let url = ctx.url;
// 从上下文中获取get请求参数
// 获取GET请求参数
const queryParams = ctx.query;
console.log(`GET请求参数: ${JSON.stringify(queryParams)}`)
console.log(queryParams.username)
if (queryParams.username == 'admin') {
username = 'admin'
ctx.cookies.set('myCookie', queryParams.username, {
maxAge: 1000 * 60 * 60, // 1小时过期
httpOnly: true, // 仅在http请求中可用,不允许js访问
overwrite: true, // 覆盖已有的cookie
SameSite: "strict" //更严格的安全模式,cookie永远不会附带于跨站点的请求上,即使是在顶级导航的情况下也不会发送cookie
});
}
// next()
});
router.get('/getMsg', (ctx, next) => {
ctx.body = {
data: listLog
};
});
router.post('/setMsg', async (ctx) => {
console.log(ctx.request)
const queryParams = ctx.request.body.msg; // 获取请求体
// 处理body中的数据...
listLog.push({ msg: queryParams, username: username || '匿名用户' })
ctx.body = {
data: listLog
};
})
router.get('/setMsg', (ctx, next) => {
const queryParams = ctx.query.msg;
listLog.push({ msg: queryParams, username: username || '匿名用户' })
ctx.body = {
data: listLog
};
});
router.get('/clearmsg', (ctx, next) => {
listLog = []
ctx.body = {
data: listLog
};
});
app.use(router.routes()); // 匹配路由并调用相应的处理函数
app.use(router.allowedMethods());
app.listen(9000);
console.log('Server is running on port 9000');
3. 前端服务
登录
清空评论
添加评论
export default {
name: "HelloWorld",
data() {
return {
msg: "",
from: {
username: "admin",
password: "123",
},
tableData: [],
};
},
mounted() {
this.getmsg();
},
methods: {
login() {
this.$axios
.get("/app/login", { params: { ...this.from } })
.then((res) => {
console.log(res.data.data);
});
},
getmsg() {
this.$axios.get("/app/getMsg", {}).then((res) => {
this.tableData = res.data.data;
console.log(res.data.data);
});
},
setmsg() {
/* this.$axios
.get("/app/setMsg", { params: { msg: this.msg } })
.then((res) => {
this.msg = "";
console.log(res.data.data);
this.getmsg();
}); */
this.$axios.post("/app/setMsg", { msg: this.msg }).then((res) => {
this.msg = "";
console.log(res.data.data);
this.getmsg();
});
},
clearmsg() {
this.$axios.get("/app/clearmsg", {}).then(() => {
this.getmsg();
});
},
},
};
h1,
h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
4. csrf跨站攻击脚本
csrf demo
hello,这里什么也没有。
document.write(`
来自CSRF攻击!
`
);
var iframe = document.createElement('iframe');
iframe.name = 'csrf';
iframe.style.display = 'none';
document.body.appendChild(iframe);
setTimeout(function () {
document.querySelector('[name=commentForm]').submit();
}, 1000);
5.攻击详情部署
1:首先不登录的情况添加评论1,刷新前端页面。
2:点击登录按钮添加评论123,刷新前端页面。
3:打开csrf跨站攻击脚本页面,刷新前端页面。
6.防御csrf攻击方式
1.CSRF Token
CSRF Token(跨站请求伪造令牌)并不是指登录成功后返回的用于身份验证的token,尽管它们可能看起来相似并且都涉及到了“token”这个词,但它们有着不同的目的和机制。
登录返回的Token(Session Token 或 Access Token)
当你登录到一个网站或应用时,服务器可能会生成一个token,通常是session token或者access token,然后返回给客户端。这个token会存储在客户端(比如浏览器的cookie中),并在后续的每个请求中附带,以便服务器可以验证请求的来源。这个token的作用是证明用户已经通过了身份验证,是用户与服务器之间会话状态的一部分。
CSRF Token
CSRF Token则是为了防止跨站请求伪造攻击而设计的。在CSRF攻击中,攻击者试图诱使已登录的用户在不知情的情况下执行恶意操作,例如转账或改变账户设置。CSRF Token是一种额外的安全措施,用来确认发起请求的页面是可信任的源。
CSRF Token的机制是这样的:
- 用户登录后,服务器会生成一个随机的CSRF Token,并将其存储在服务器端,同时也会将这个Token以某种形式(如隐藏的表单字段、HTTP header或cookie)发送给客户端。
- 当客户端发起敏感请求时,必须包含这个CSRF Token。
- 服务器接收到请求后,会验证请求中的CSRF Token是否与服务器上存储的Token相匹配。如果不匹配,则拒绝请求。
因为CSRF Token是在用户登录后由服务器独立生成的,且每个会话或每个请求都可能是不同的,所以即使攻击者能够控制用户点击链接或按钮,他们也无法预测或复制正确的CSRF Token,因此无法成功伪造请求。
总之,登录返回的token主要用于身份验证和授权,而CSRF Token则专门用于保护应用程序免受跨站请求伪造攻击。两者虽然都是token,但在功能和使用场景上是不同的。
2.登录验证码或者是token





