想当黑客?是的,基本每个程序员都有一颗相当黑客的心。从【黑客帝国】再到【欧洲攻略】,Hackers总是在黑暗中微笑,慢慢的侵蚀着互联网,侵蚀着他想要去的地方,获取别人的数据库,获取自己想要的信息,是不是帅到不讲武德。
但是,我们身为公司的员工,我们有义务和责任保护公司的信息安全,这时候,我们可能有需要和黑客作斗争,化身为正义的天神,与黑暗中那个微笑的男人征战。
所以说,这篇文章我想告诉大家前端黑客是如何操作的以及在公司我们如何保护好项目不受侵犯。
全称:Cross Site Script(跨站脚本)
为了与层叠样式表css区分,将跨站脚本简写为XSS
危害:盗取用户信息、钓鱼、制造蠕虫等。
概念:黑客通过“HTML注入”篡改了网页,插入了恶意脚本,从而在用户在浏览网页时,实现控制用户浏览器行为的一种攻击方式。
黑客可以利用xss盗取用户的cookie,有了用户的cookie,可以以用户的身份来正常访问站点。
XSS属于客户端代码注入,通常注入代码是JavaScript。区别于命令注入,SQL注入属于服务端代码注入。
简单的来说,就是在网页提供给用户输入的地方写入代码。
XSS分为三种类型:反射型,存储型,Dom型。
反射型: 一般来说这种类型的XSS,需要攻击者提前构造一个恶意链接,来诱使客户点击,比如这样的一段链接:
www.abc.com/?params=
存储型: 这种类型的XSS,危害比前一种大得多。比如一个攻击者在论坛的楼层中包含了一段JavaScript代码,并且服务器没有正确进行过滤输出,那就会造成浏览这个页面的用户执行这段JavaScript代码。
DOM XSS: 这种类型则是利用非法输入来闭合对应的html标签。 比如,有这样的一个a标签:
乍看问题不大,可是当$var的内容变为 ’ οnclick=’alert(/xss/) //,这段代码就会被执行。
实战:
这里我们讲的是Dom XSS,这是一个网页源码:
XSS原理分析
界面是这样的:
我们首先输入123,看看能得到什么结果:
去看看源码:
我们输入的字符串被原封不动输出了,这样的话,如果我们将123替换成bird 也会被原封不动的输出,由于alert()函数的功能是弹出对话框,那么也就是说我们输入上面的语句就会弹框,现在来看看
下面是输入bird 得到的页面:
再去看看源码:
对用户的输入进行转义,即可解决XSS。
但是我们现在都是用框架进行开发,例如Vue,React,angular,而XSS常是基于DOM的,而框架很少去操作Dom,并且框架底层也对XSS做了一些防范。
全称:Cross-site request forgery(跨站请求伪造)
危害:个人隐私泄露以及财产安全。
概念:攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
实战:
这里有一个网站,自带账号和密码,点击登录即可,你可以在文章下面发表一条评论并且记住自己的用户名。
当你点击这个链接,你会发现刚才的网站你的账户名又发表了一个新的留言,这个就是CSRF。
用户在网站登录后,这个网站服务端会在 Cookie 中会放一个凭证,这个凭证是后端用来验证用户身份的。 在发评论的时候,提交评论的请求会带上这个凭证,后端通过判断这个凭证,来确认是哪个用户。
登录时,设置 Cookie:
提交评论时,携带 Cookie:
我们再来看看,发起攻击的页面里的内容。
这些代码的意思就是,当用户点击这个链接,会自动提交 form 表单,而这个表单就是用来提交评论的,提交评论请求需要的参数,在 form 表单中也都已经准备好了,如果用户登录过网站,Cookie 中存储的用户的凭证,会随着请求一起传到服务器端。所以服务器端就会认为这是用户要提交一条评论。
请求来源限制——验证 HTTP Referer 字段
方法:在HTTP请求头中有一个字段叫Referer,它记录了请求的来源地址。 服务器需要做的是验证这个来源地址是否合法,如果是来自一些不受信任的网站,则拒绝响应。
额外验证机制——token的使用
方法:使用tocken
来代替验证码验证。由于黑客并不能拿到和看到cookie
里的内容,所以无法伪造一个完整的请求。基本思路如下:
服务器随机产生token
(比如把cookie
hash化生成),存在session
中,放在cookie
中或者以ajax
的形式交给前端。
前端发请求的时候,解析cookie
中的token
,放到请求url
里或者请求头中。
服务器验证token
,由于黑客无法得到或者伪造token
,所以能防范csrf
更进一步的加强手段(不需要session):
服务器随机产生token
,然后以token
为密钥散列生成一段密文
把token
和密文都随cookie
交给前端
前端发起请求时把密文和token
都交给后端
后端对token
和密文进行正向散列验证,看token
能不能生成同样的密文
这样即使黑客拿到了token
也无法拿到密文。
概念:界面劫持,分为点击劫持、拖放劫持、触屏劫持。就是我们的点击,拖放,触屏操作被劫持了,而去操作了其它的透明隐藏的界面。其原理是利用透明层+iframe,使用了css中的opacity和z-index等属性,来到达透明和位于其它界面的上方,然后使用iframe来嵌入劫持页面。到达了用户操作的不是它看到的,不是他以为的那个界面,而是那个透明的位于上层的界面。
简单的来说,就是在百度贴吧页面上覆盖了一层页面,在百度贴吧关注按钮上面,覆盖的页面在相同的位置放一个按钮欺骗人点击,点击这个按钮相当去点击了百度贴吧的关注按钮。
我们准备一个透明层页面:
点击劫持 那些不能说的秘密
2. 网址传播出去后,用户手击了查看详情后,其实就会点到关注按钮。
3. 这样贴吧就多了一个粉丝了。
使用一个HTTP头——X-Frame-Options。
X-Frame-Options可以说是为了解决ClickJacking而生的,它有三个可选的值:
DENY:浏览器会拒绝当前页面加载任何frame页面。
SAMEORIGIN:frame页面的地址只能为同源域名下的页面。
ALLOW-FROM origin:允许frame加载的页面地址。
JS层面:使用iframe的sandbox属性,判断当前页面是否被其他页面嵌套。
建议HTTP头+JS结合防御。
web前端黑客中的漏洞挖掘重点就是XSS漏洞挖掘,至于CSRF漏洞挖掘和页面操作劫持漏洞挖掘本质上就决定了这些漏洞挖掘起来就很简单。
CSRF的漏洞挖掘只要确认以下内容即可:
1.目标表单是否有有效的token随机串。
2.目标表单是否有验证码。
3.目标是否判断了Referer来源。
4.网站根目录下crossdomain.xml的"allow—access—fromdomain“是否是通配符。
5.目标JSON数据似乎可以自定义callback函数等。
页面操作劫持的漏洞挖掘只要确认以下内容即可:
1.目标的HTTP响应头是否设置了X-Frame-Options字段。
2.目标是否有JavaScript的FrameBusting机制。
3.更简单的就是用iframe嵌入目标网站试试,若成功,则说明漏洞存在。
XSS的漏洞就多了太多的可操作性:
下面假设服务端不对用户输入有任何编码或者过滤。
4.1、html内容中
4.1.1 大小写不敏感
4.1.2 嵌套绕过
ipt>alert(1) Ipt>
4.1.3 svg 注入(HTML5 支持内联 SVG)
4.1.4 执行代码转换成unicode编码,再通过eval执行
4.2. HTML标签属性中
很多时候输出发生在HTML属性, 例如
、 ,再比如
等
4.2.1 自行闭合双引号构造闭合标签:
" οnclick="alert(1) "> ">
构造on事件:
" οnmοuseοver=alert(document.domain)>
增加注释符//:
" οnmοuseοver=alert(document.domain)> //
利用html5 autofocus功能进行XSS:
aaaaa" name="javasCript:alert()" autofocus οnfοcus="location=this.name" aaa">
很多时候遇到的场景并不会这么简单, 程序员会将双引号 " 过滤为实体 例如
Form标签闭合引号:
4.2.2 两个常见的输出例子
xxxx
实际上, onxxxx="[输出]" 和 href="javascript:[输出]" 与 没有太大区别。因为[输出]所在的地方,都是javascript脚本。
但是 如果被过滤,往往没有太好的办法。而上面这2种情况,则有一个很好的办法绕过过滤。
由于单引号'被过滤,我们可以将'写为'
location.href='........&key=aaaaaa' location.href='........&key=aaaaaa'+alert(1)+'' location.href='........&key=aaaaaa'+alert(1)+'‘
接着我们把代码转换为 url 的编码。 &-> %26, # -> %23最后
key=%26%23x27;%2balert(1)%2b%26%2aaaaaaa3x27;
缺陷点是发生在 onkeydown 或 a 标签的 href 属性中,无法自动触发,因而使得威胁减小,如果是发生在 img 的 onload 属性,则非常可能导致自动触发
用户输入内容直接显示在代码执行上下文中,我们可以 首先判断,是否过滤了
* < , > , /
* 等特殊符号,如果没有被过滤可以XSS可能性就很高
尽量不要在JS的注释里输出内容, 还挺危险的。
防御方式:将一下特殊字符进行转义 防御方式: 对这些输出的特殊字符进行编码
**概念:**网络蠕虫是一种智能化、自动化,综合网络攻击、密码学和计算机病毒技术,无须计算机使用者干预即可运行的攻击程序或代码,它会扫描和攻击网络上存在系统漏洞的节点主机,通过局域网或者国际互联网从一个节点传播到另外一个节点”。
和漏洞挖掘一样,WEB蠕虫也分为XSS蠕虫,CSRF蠕虫,页面操作劫持蠕虫。这次我们要说的是页面操作劫持蠕虫。
页面操作劫持蠕虫的由来
这要从2009年初Twitter上发生的“Don'tCIick”蠕虫事件说起。在2009年初,Twitter 上的很多用户都发现自己的Twitter上莫名其妙地出现了下面这条广播:
Don'tC1ick:~http://tinyurl.com/amgzs6
用户实际上根本就没有广播过这条消息。这次Twitter的蠕虫事件就是使用页面操作劫持技术进行传播的。这也是蠕虫首次使用页面操作劫持技术手段进行传播的案例。
技术分析
下面就对Twitter的这次Don'tClick蠕虫做技术分析。
首先,攻击者使用页面操作劫持技术制作蠕虫页面,该页面的URL地址使用TINYURL短地址转tinyurl.com/amgzs6 页面源代码的设计要点如下。
对iframe和button标签进行CSS样式设定,设置iframe标签所在层为透明层、使iframe 标签所在层位于button标签所在层的正上方。
透明层下方的迷惑按钮和twitter中发送广播的按钮重合。
透明层的内容中,status参数后的内容即为发送广播的内容:
页面虽然简陋,但上面介绍的这个正是iframe蠕虫最核心的框架。至此,蠕虫页面己经做好,可以开始源头的传播。攻击者首先在自己的Twitter上发一条广播:
"Don'tClick:tinyurl.com/amgzs6”
当攻击者的其他好友收听到这条广播后,好奇心促使他们去单击http://tinyurLcom/amgzs6链接,进而去单击链接页面中的"Don't Click”按钮。当单击该按钮后,其实单击的是Twitter中发送广播的按钮,于是在用户 不知情的情况下,用户的Twitter中发送一条广播,内容为“Don'tCIick:tinyurl.com/ amgzs6”。然后,其他看到这条消息的人重复以上操作,如此循环,蠕虫就这样传播。
1.开发需尽量避免Web客户端文档重写、重定向或其他敏感操作,同时要避免使用客户端数据,这些操作需尽量在服务器端使用动态页面来实现。
2.HttpOnly Cookie。预防XSS攻击窃取用户cookie最有效的防御手段。Web应用程序在设置cookie时,将其属性设为HttpOnly,就可以避免该网页的cookie被客户端恶意JavaScript窃取,保护用户cookie信息。
3.WAF(Web Application Firewall),Web应用防火墙,主要的功能是防范诸如网页木马、XSS以及CSRF等常见的Web漏洞攻击。由第三方公司开发,在企业环境中深受欢迎。
天猫官网的控制台是有警告信息,这是为什么呢?因为有的黑客会诱骗用户去往控制台里面粘贴东西(欺负大部分人不懂代码),比如可以在朋友圈贴个什么文章,说:"只要访问天猫,按下F12并且粘贴以下内容,则可以获得xx元礼品"之类的,那么有的用户真的会去操作,并且自己隐私被暴露了也不知道。
天猫这种做法,也是在警告用户不要这么做,看来天猫的前端安全做的也是很到位的。不过,这种攻击毕竟是少数,所以各位看官看一眼就行,如果真的发现有的用户会被这样攻击的话,记得想起天猫的这种解决方案。
钓鱼也是一种非常古老的攻击方式了,其实并不太算前端攻击。可毕竟是页面级别的攻击,我们也来一起聊一聊。我相信很多人会有这样的经历,QQ群里面有人发什么兼职啦、什么自己要去国外了房子车子甩卖了,详情在我QQ空间里啦,之类的连接。打开之后发现一个QQ登录框,其实一看域名就知道不是QQ,不过做得非常像QQ登录,不明就里的用户们,就真的把用户名和密码输入了进去,结果没登录到QQ,用户名和密码却给人发过去了。
1 首先,我们在xx空间里分享一篇文章,然后吸引别人去点击。
2 接着,我们在cheat.php这个网站上面,将跳转过来的源网页地址悄悄的进行修改。
于是,在用户访问了我们的欺骗网站后,之前的tab已经悄然发生了变化,我们将其悄悄的替换为了钓鱼的网站,欺骗用户输入用户名、密码等。
3 我们的钓鱼网站,伪装成XX空间,让用户输入用户名与密码
这种钓鱼方式比较有意思,重点在于我们比较难防住这种攻击,我们并不能将所有的页面链接都使用js打开。所以,要么就将外链跳转的连接改为当前页面跳转,要么就在页面unload的时候给用户加以提示,要么就将页面所有的跳转均改为window.open。