Xss跨站脚本攻击(Cross Site Scripting)
- 原理: HTML是一种超文本标记语言,通过将一些字符特殊地对待来区别文本和标记,例如,小于符号(<)被看作是HTML标签的开始,
与 之间的字符是页面的标题等等。 - 当动态页面中插入的内容含有这些特殊字符(如<)时,用户浏览器会将其误认为是插入了HTML标签,当这些HTML标签引入了一段JavaScript脚本时,这些脚本程序就将会在用户浏览器中执行
- 所以,当这些特殊字符不能被动态页面检查或检查出现失误时,就将会产生XSS漏洞。
案例: 1 反射型,比如路径输入一个type值,服务器就响应那个值。
//express
app.get('/welcome',(req,res)=>{
res.send(req.query.type)
})
那么当我们输入的是脚本呢?
http://localhost:3000/welcome?type=<script>alert(123)</script>
那么它会被执行。
那么他就可以获取当前环境的cookie。
一般情况下都会设置让cookie在前端不可获取,但不是解决xss的方案。
这种属于反射型,会引诱用户自己点开,(一次性的)
xss其实就是因为写的东西没有过滤,混进去了一些脚本。这种问题一般是没有验证文本的安全性。可以通过一些方法解决。比如过滤文本
app.get('/welcome',(req,res)=>{
res.send(encodeURIComponent(req.query.type))
})
转化文本。
2 xss-payload
不基于后端的攻击,DOM-Based
如修改dom属性,插入内容,document.write,改变结构后,就会造成攻击.
<body>
<input id="input" type="text">
<button id="button">插入图片</button>
<div id="box"></div>
<script>
const input = document.getElementById('input')
const box = document.getElementById('box')
const button = document.getElementById('button')
button.onclick = () => {
box.innerHTML = `<img src="${input.value}" />`
}
</script>
</body>
input输入的值会作为html解析插入到dom中。如下:
如果故意执行一些错误语句呢?
如
xxx" οnerrοr="alert(document.cookie)
那么它就会执行,从而获取用户一些隐秘的信息。
<img src="xxx" onerror="alert(dockment.cookie)"/>
所以在用户输入这些值的时候,要记得转义一下。
box.innerHTML = `<img src="${encodeURI(input.value)}" />`
3 xss 存储型,恶意的脚本存储到了服务器上,所有人访问的时候都会造成攻击。
微博 访问时就会以自己身份发一条恶意微博 x
前情提要:评论页面有公共的数据。
如这个,一旦我们输入的言论
比如输入了这个
<img src='xxx' onerror='alert(document.cookie)'/>
那么在执行的时候,
就会导致这种结果,因为这是公共的内容,当很多人访问的时候,就都会遇到这个问题,如开启一个新的页面
范围更大,危害更多。
同样也是因为没有转义输入的content。
总结: 所有xss攻击都是因为输入的内容没有转义没有验证,导致有些危险脚本被浏览器执行。
CSRF 跨站请求伪造
常说的钓鱼网站
原理:
-
攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)
-
由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行
-
利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
例子:
- 假如一家银行用以运行转账操作的URL地址如下:http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName
- 那么,一个恶意攻击者可以在另一个网站上放置如下代码:
- 如果有账户名为Alice的用户访问了恶意站点,而她之前刚访问过银行不久,登录信息尚未过期,那么她就会损失1000资金。
- 攻击者并不能通过CSRF攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义运行操作。
模拟
准备一个钓鱼网站
<body> 找女朋友点这里。 <iframe src="http://localhost:3001/bad.html" style="display: none;" frameborder="0"></iframe></body>
可以看到这个钓鱼网站内嵌了一个网页并且不可见。
// bad.html内容<body> <form action="POST"> // ... </form> <script> document.form.submit() </script></body>
我们假设bad.html发送了一个请求,银行转账的请求。利用抓包获取到了网址,信息等等。
假设如果我们没登陆银行,首次打开bad.html,那么因为没有cookie,所以bad.html不会成功。
但是如果我们登录了银行,有了一个cookie之后(第三方网站拿不到cookie的,只不过当往3000端口提交内容的时候,会自动携带cookie。因为表单是没有跨域问题的),那么再点击这个钓鱼网站的时候,他就会成功发送请求,将你的钱转走。
解决办法
-
验证码(体验不好)
-
判断来源 refer 301 032
HTTP头中有一个Referer字段,这个字段用以标明请求来源于哪个地址(不靠谱,可以自己通过node发送请求)
-
token; 由于CSRF的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在cookie中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再运行CSRF攻击。
XSRF
在同源下直接输入脚本,发送请求。
还是以xss的案例,如果插入的脚本是
地址输入什么返回什么。
输入http://localhost:3000/test.js
//test.jsconst div = document.createElement("div");div.innerText = 123;box.appendChild(div)console.log(123123);
test是我们写的第三方脚本,点击之后,
这时候我们是同源的,都不需要跨域。所以这种也是比较危险的。