web前端安全

    前端安全一直是一个蛮严苛的问题,特别如果设计到money更是如此。了解前端安全,在平时的coding中主动考虑,防范于未然,是一个有追求的程序猿应该做的。

未登录

    我们从弱弱的基本开始,第一步当然是登录鉴权了,如果一个需要用户身份鉴权的应用系统没有登录过滤那简直是没法想像的,方案基本都是用户输入用户名密码、或是三方 openID 授权后在 session 里保存用户此次登录的凭证来确保每次请求的合法性。
    由于 session有时效限制,所以若用户一段时间未与服务器交互则会过期重登,当然我们也可以通过把登录凭证存在 cookie 里来自由控制用户登录的有效时间。这个是最基本的鉴权我们就不深入细节。

登录了,但被CSRF

    虽然有了登录验证后,我们可以挡掉其他非登录用户的骚扰了,但悲剧的是坏人们还是可以欺骗我们善良的用户,借已登录用户的手来搞破坏。即 CSRF(Cross-site request forgery)跨站请求伪造。

举个例子:

    有个黑客的网站 h.com,我们的网站 a.com。用户登录了a.com,但被诱点进入h.com(如收到 QQ 消息或邮件传播的h.com 的链接),当用户访问这个链接时,h.com 上自动发送一个请求到 a.com,由于用户已登录a.com,浏览器根据同源策略,会在该请求上自动附带了 cookie,而前面我们提到了鉴权是通过 cookie 里的某个 key 值凭证的,所以如若没有判断该请求的来源合法性,我们则通过了该伪造的请求,执行了相应的操作。比如这个请求是让该用户发一篇日志,或是发微博,或是严重的发起一笔转账。

常见的诸如放一张看不见的图片发起get请求

<img src=http://www.a.com/Transfer.phptoUserId=999&money=1000000>

    post 请求会稍微麻烦些,但同样很好实现,可以构造一个表诱导用户点击,也可以直接利用ajax发送post请求。
    要防住此类伪造请求我们第一反应都是检查这个请求的来源,确实,在上述的情形下发来的请求报文里referer字段的网址不是我们的自己站点,
而会是一个三方的,如上假设的 h.com。但是很多情况下,referer并不完全靠谱,比如如果众多二级域名之间需要通信,那么referer可能会
设得比较泛,如*.a.com。或是历史原因一些 referer 为空的请求会漏过校验等。所以这种方式只是提高了破解成本,并不能完全杜绝。

    现在业界比较通用的解决方案还是在每个请求上附带一个anti-CSRF token。
    将sessionid加盐再散列处理。然后一起发送给后端。服务器端拿到 token 后用相同的算法对 sid 运算后匹对,相同则为已登录用户发出请求,没有或不对等则说明该请求是伪造的。

token = MD5( sid * salt )

    其实这个算法的精髓在于使用了 cookie 中的 sid(用户登录后我们服务器种的 cookie 凭证),因为前端的代码对用户而言都是没有秘密的,只要花点时
间即可推算出我们的算法,但由于攻击者无法登录,又拿不到 cookie 里的 sid(根据浏览器的同源策略,在 h.com 上无法获取属于 a.com 的 cookie),所以无法构造出 token。
    至于加 MD5当然是因为我们不会傻的把登录凭证 sid 放到 url 上给人直接拿了登录- -(以前还真有人干过),为什么要加 盐 salt 则是怕简单的一层 MD5还是有可能被通过撞库的方式解出 sid,当然加了 salt 也不意味着100%防住,只是大大提高了破解的成本而已。

有防 CSRF了,但被 XSS

从上面我们知道防住 CSRF 最关键的是要守住 cookie,如果用户的 cookie 被人窃取了,那上面的防护就形同虚设了。而 XSS 就可以很轻易的获取用户的 cookie,
所以有句话叫Buy one XSS, get a CSRF for free。

用户输入的内容原封不动的通过服务器程序渲染在页面上 。

反射型

举个栗子

前端get一个请求:

www.a.com/xss.php?name=userA

后台处理:

<?php echo 'Hello' . $_GET['name'];

代码本意是根据queryString 的 name 来动态展示用户名,但由于未对 name 做编码校验,当链接为:

www.a.com?xss.php?name=<script>alert(document.cookie);</script>

这时访问这个链接则会弹出我们的 cookie 内容,如果这时候再把 alert 改为一个发送函数,则可把 cookie 偷走。

前端DOM-Based XSS

<script>
document.getElementById('intro-div').innerHTML = document.location.href.substring(document.location.href.indexOf("intro=")+6);
</script>

如上,直接将用户的输出输出到页面标签中。但是如果将链接中的内容设置为

http://www.a.com/index.html?intro=<script>alert(document.cookie)</script>

那我们的 cookie 又没了。

持久型XSS

也称为存储型 XSS,注入脚本跟 XSS 大同小异,只是脚本不是通过浏览器->服务器->浏览器这样的反射方式,而是多发生在富文本编辑器、日志、留言、配置系统等数据库保存用户输入内容的业务场景。即用户的注入脚本保存到了数据库里,其他用户只要一访问到都会中招。

前端get一个请求:

www.a.com/xss.php?name=<script>alert(document.cookie);</script>

后台处理:

<?php $db.set("name", $_GET["name"]);

前端请求的页面:

<?php echo 'Hello' . $db.get['name'];

这样但凡请求了该页面的都会被XSS攻击到。

解决XSS

    从上面我们可以看出各种攻击手段很重要的一点就是要获取 cookie,有了 cookie 就相当于获取了我们用户的身份信息,所以自然的我们要保护我们的 cookie。在 cookie 里有个 HttpOnly 属性可以让页面无法通过 JS 来读写 cookie。

res.cookie('a', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });

    开启这个属性后 document 将无法获取 cookie。当然这个方法也不是万能的,我们的 cookie 还是会在 header 中,还是有其他手段去获取 header 中的 cookie,
不过使用后我们还是提高了攻击的成本。关键还是我们要不相信用户的一切输入,对编码输出在页面中会破坏原有代码(HTML、JavaScript甚至WML等)规则的特殊字符以及对某些标签的某些属性进行白名单检查。

XSS防护也做了,被用户SQL注入

举个例子:

请求:www.a.com/query?userId=123

功能是查询userId为123的用户出来,这个请求到我们服务端最后sql语句是这样:

select * from users where userid=123

如果不做任何校验,如果用户输入如下

123; DROP TABLE users;

嘎嘎,整个表就没有了。
所以同样的,还是那个原则,我们不能相信用户的任何输入,如果一个sql语句里包含了用户输入的内容,那我们要对内容做sql安全相关的过滤检查。
同时,使用一些ORM工具,不使用拼凑字符串型的语句执行方式。

总结

    总的来说,前端最重要的就是一个sessionId这个代表用户身份的凭证,保护好这个凭证,同时利用同源策略以及自己加密token来识别用户,最后以最恶意的眼光对待用户的输入,不要相信用户的输入。这样就能屏蔽绝大部分常见的安全问题了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • XSS(cross-site scripting跨域脚本攻击)攻击是最常见的Web攻击,其重点是“跨域”和“客户端...
    一只大橘阅读 720评论 0 6
  • 相信每一个前端er对于跨域这两个字都不会陌生,在实际项目中应用也是比较多的。但跨域方法的多种多样实在让人目不暇接。...
    Rubin666阅读 892评论 0 2
  • http://www.91ri.org/tag/fuzz-bug 通常情况下,有三种方法被广泛用来防御CSRF攻击...
    jdyzm阅读 4,161评论 0 5
  • 前言 对于一个影子杀手而言,总能杀人于无形。前端也有影子杀手,它总是防不胜防地危害着你的网站 本篇打算介绍一些前端...
    Layzimo阅读 655评论 0 1
  • 有的时候诚实比谎言更能打动人。错了就是错了,知错就改还是好同志。老板最不能容忍的是员工的吃里扒外。而且任何一个企业...
    都市外乡人阅读 264评论 0 0