白帽子讲Web安全

来源:互联网 发布:淘宝店铺怎么查网址 编辑:程序博客网 时间:2024/04/20 11:38

第一篇:世界观安全

第一章:我的安全世界观

一个网站的数据库,在没有任何保护的情况下,数据库服务端口是允许任何人随意连接的;在有了防火墙的保护后,通过ACL可以控制只允许信任来源的访问。这些措施在很大程度上保证了系统软件处于信任边界之内,从而杜绝了绝大部分的攻击来源。

1.1.3Web安全的兴起

常见攻击:SQL注入,XSS(跨站脚本攻击)

“破坏往往比建设容易”,但凡事都不是绝对的。一般来说,白帽子选择的方法,是克服某种攻击方法,而并非抵御单次的攻击。比如设计一个解决方案,在特定环境下能够抵御所有已知的和未知的SQL Injection问题。假设这个方案的实施周期是3个月,那么执行3个月之后,所有的SQL Injection问题都得到了解决,也就意味着黑客再也无法利用SQL Injection这一可能存在的弱点入侵网站了。如果做到了这一点,那么白帽子们就在SQL Injection的局部对抗中化被动为主动了。

跟机场安全检查进行类比。通过一个安全检查(过滤,净化)的过程,可以梳理未知的人或物,使其变得可信任。被划分出来的具有不同信任级别的区域,我们成为信任域,划分两个不同信任域之间的边界,我们称之为信任边界

数据从高等级的信任域流向低等级的信任域,是不需要经过安全检查的;数据从低等级的信任域流向高等级的信任域,是需要经过信任边界的安全检查。

安全问题的本质是信任的问题

一切的安全方案设计的基础,都是建立在信任关系上的。我们必须相信一些东西,必须要有一些最基本的假设,安全方案才能得以建立

1.5安全的三要素

安全的三要素是安全的基本组成元素,分别为机密性(Confidentiality)完整性(Integrity)可用性(Availability)

机密性要求数据内容不能泄露,加密是实现机密性要求的常见手段。如果不将文件存在抽屉里,而是放在透明的盒子里,那么虽然无法得到这个文件,但是文件的内容将会被泄露。

完整性则要求保护数据内容是完整,没有被篡改的。常见的保证一致性的技术手段是数字签名。

可用性要求保护资源是“随需而得”。

举例来说,假如有100个车位,有一天一个坏人搬了100块大石头将车位全占了,那么停车场无法再提供正常服务。在安全领域中叫做拒绝服务攻击,简称DoS(Denial of Service)。拒绝服务攻击破坏的是安全的可用性。

1.6如何实施安全评估

一个安全评估的过程,可以简单地分为4个阶段:1.资产等级划分2.威胁分析3.风险分析4.确认解决方案

1.6.1资产等级划分

资产等级划分是所有工作的基础,这项工作能够帮助我们明确目标是什么,要保护什么。

互联网安全的核心问题,就是数据安全的问题

1.6.2威胁分析

在安全领域,我们把可能造成危害的来源成为威胁(Threat),而把可能会出现的额损失称为风险(Risk)。

威胁分析:
1.头脑风暴
2.STRIDE模型

1.6.2风险分析

风险是由以下因素组成:
Risk=Probability * Damage Potential

衡量风险:
1.DREAD模型

1.7白帽子兵法

1.7.1Secure By Default原则

白名单,黑名单

实际上,Secure By Default原则,也可以归纳为白名单,黑名单的思想如果更多地使用白名单,那么系统就会变得更安全

最小权限原则

最小原则要求系统只授予主体必要的权限,而不要过度授权,这样能有效地减少系统,网络,应用,数据库出错的机会。

纵深防御原则

纵深防御原则包含两层含义:1.要在各个不同层面,不同方面实施安全方案,避免出现疏漏,不同安全方案之间需要相互配合,构成一个整体;2.要在正确的地方做正确的事情,即:在解决根本问题的地方实施针对性的安全方案。

1.7.3数据与代码分离原则

这一原则适用于各种由于“注入”而引发安全问题的场景

实际上,缓冲区溢出,也可以认为是程序违背了这一原则的后果——程序在栈或者堆中,将用户数据当做代码执行,混淆了代码与数据的边界,从而导致安全问题的发生。

1.7.4不可预测性原则

微软使用的ASLR技术,在较新版本的Linux内核中也支持。在ASLR的控制下,一个程序每次启动时,其进程的栈基址都不相同,具有一定的随机性,对于攻击者来说,这就是“不可预测性”。

不可预测性,能有效地对抗基于篡改,伪造的攻击。

不可预测性的实现往往需要用到加密算法,随机数算法,哈希算法,好好利用这条规则,在设计安全方案时往往会事半功倍。

1.8小结

第二篇:客户端脚本安全

第二章:浏览器安全

一些主要浏览器的安全功能

2.1同源策略

这一策略极其重要,如果没有同源策略,可能a.com的一段JS脚本,在b.com未曾加载此脚本时,也可以随意修改b.com的页面(在浏览器显示中)。为了不发生混乱,浏览器提出“Origin”(源)的概念。来自不同Origin的对象无法相互干扰。

从上表可以看出,影响”源”的因素有:

1.host(域名或IP地址)
2.子域名
3.端口
4.协议

需要注意的是,对于当前页面来说,页面内存放JS文件的域并不重要,重要的是加载JS的页面所在的域是什么。举例说明:
a.com通过代码<script src=http://b.com/b.js ></script>加载了b.com上的b.js。因为b.js是运行在a.com上的,所以b.js的域就是a.com。

在浏览器中,<script>,<img>,<iframe>,<link>等标签都可以跨域加载资源,而不受同源策略的限制。这些带”src”属性的标签每次加载时,实际上是由浏览器发起了一次GET请求。不同于XMLHttpRequest的是,通过src属性加载的资源,浏览器限制了JS的权限,使其不能读,写返回的内容。

对于XMLHttpRequest,它收到同源策略的约束,不能跨域访问资源,在AJAX应用的开发中尤其需要注意到这一点。

2.2浏览器沙箱

2.3恶意网站拦截

2.4高速发展的浏览器安全

第三章:跨站脚本攻击(XSS)

3.1XSS简介

跨站脚本攻击,英文全称为Cross Site Script,在安全领域叫做”XSS”。XSS攻击,通常指黑客通过”HTML注入”篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。

XSS根据效果的不同可以分为如下几类。

一:反射型XSS

反射型XSS只是简单地把用户输入的数据“反射”给浏览器。也就是说,黑客往往需要诱使用户“点击”一个恶意链接,才能攻击成功。反射型XSS也叫做“非持久型XSS”(Non-persistent XSS)。

二:存储型XSS

存储型XSS会把用户输入的数据“存储”在服务器端。这种XSS具有很强的稳定性。也叫做“持久型XSS”(Persistent XSS)。

三:DOM Based XSS

通过修改页面的DOM节点形成的XSS,称之为DOM Based XSS。

3.2XSS攻击进阶

可以利用XSS payload来窃取Cookie。但”Cookie劫持”并非所有的时候都会有效,有的网站可能会在Set-Cookie时给关键的Cookie**植入HttpOnly标识;有的网站会把Cookie与客户端IP绑定**。

3.3XSS的防御

1.四两拨千斤:HttpOnly

浏览器将禁止页面的JS访问带有HttpOnly属性的Cookie。只能防止XSS后的Cookie劫持攻击。

一个Cookie的使用过程如下:

STEP1.浏览器向服务器发起请求,这个时候没有Cookie
STEP2.服务器返回时发送Set-Cookie头,向客户端浏览器写入Cookie
STEP3.在该Cookie到期前,浏览器访问该域下的所有页面,都将发送该Cookie

在java EE中,给Cookie设置HttpOnly代码如下:

response.setHeader("Set-Cookie","cookieName=value;path=/;Domain=domainValue;Max-Age=seconds;HTTPOnly");

但是HttpOnly不是万能的,添加了HttpOnly不等于解决了XSS问题。

XSS攻击带来的不光是Cookie劫持的问题,还有窃取用户信息,模拟用户身份执行操作等诸多严重的后果。如前文所述,攻击者利用AJAX构造HTTP请求,以用户身份完成的操作,就是在不知道用户Cookie的情况下进行的。

使用HttpOnly有助于缓解XSS攻击,但仍然需要其他能够解决XSS漏洞的方案。

2.输入检查

常见的Web漏洞如XSS,SQL Injection等,都要求攻击者构造一些特殊字符,这些特殊字符可能是正常用户用不到的,所以输入检查就有必要了。

格式检查,有点像一种”白名单”,也可以让一些基于特殊字符的攻击失效。

输入检查的逻辑,必须放在服务器端代码中实现。如果只是在客户端使用JS进行输入检查,是很容易被攻击者绕过的。

目前Web开发的普遍做法,是同时在客户端JS中和服务器端代码中实现相同的输入检查。客户端JS的输入检查,可以阻挡大部分误操作的正常用户,从而节约服务器资源。

比较智能的”输入检查”,会匹配XSS的特征。这种输入检查的方式,可以称为”XSS Filter”。有很多”XSS Filter”的实现。

XSS Filter在用户提交数据时获取变量,并进行XSS检查;但此时用户数据并没有结合渲染页面的HTML代码,因此XSS Filter对语境的理解并不完整

XSS攻击主要发生在MVC架构中的View层。大部分的XSS漏洞可以在模板系统中解决。比如Python的开发框架Django自带的模板系统”Django Templates”,或者其他的”Thymeleaf Templates”。

3.正确地防御XSS

为了更好设计XSS防御方案,需要了解其本质。

XSS的本质还是一种“HTML注入”用户的数据被当成了HTML代码一部分来执行,从而混淆了原本的语义,产生了新的语义

如果网站使用了MVC架构,那么XSS就发生在View层——在应用拼接变量到HTML页面时产生。所以在用户提交数据处进行输入检查的方案,其实并不是在真正发生攻击的地方做防御。

3.3.7换个角度看XSS的风险

一般来说,存储型XSS的风险会高于反射型XSS。因为存储型XSS会保存在服务器上,有可能会跨页面存在。

从攻击过程来说,反射型XSS,一般要求攻击者诱使用户点击一个包含XSS代码的URL链接;而存储型XSS,则只需要让用户查看一个正常的URL链接,比如一个Web邮箱的邮件正文页面存在一个存储型的XSS漏洞,当页面打开一封新邮件时,XSS Payload会被执行。这样的漏洞极其隐蔽,且埋伏在用户的正常业务中,风险颇高。

第四章:跨站请求伪造(CSRF)

CSRF的全名是Cross Site Request Forgery,翻译成中文就是跨站点请求伪造。

4.2CSRF进阶

在上节提到的例子里,攻击者伪造的请求之所以能够被搜狐服务器验证通过,是因为用户的浏览器成功发送了Cookie的缘故。

浏览器所持有的Cookie分为两种:一种是“Session Cookie”,又称”临时Cookie”;另一种是”Third-party Cookie”,也称为“本地Cookie”

两者的区别在于:

Third-party Cookie是服务器在Set-Cookie时指定了Expire时间,只有到了Expire时间后Cookie才会失效,所以这种Cookie会保存在本地,而Session Cookie则没有指定Expire时间,所以浏览器关闭后,Session Cookie就失效了

在浏览网站的过程中,若是一个网站设置了Session Cookie,那么在浏览器进程的生命周期内,即使浏览器新打开了Tab页,Session Cookie也都是有效的。Session Cookie保存在浏览器进程的内存空间中,而Third-party Cookie则保存在本地。

如果浏览器从一个域的页面中,要加载另一个域的资源,由于安全的原因,某些浏览器会阻止Third-party Cookie的发送

举例说明:

在http://www.a.com/cookie.php中,会给浏览器写入两个Cookie,一个为Session Cookie,一个为Third-party Cookie。

<?phpheader("Set-Cookie:cookie1=123;");header("Set-Cookie:cookie2=456;expires=Thu,01-Jan-2030 00:00:01 GMT;",false); ?>

访问该页面,发现浏览器同时接收了这两个Cookie。

这时再打开一个新的浏览器Tab页,访问同一个域中的不同页面。因为新Tab页在同一个浏览器进程中,因此Session Cookie将被发送

此时在另外一个域中,有一个页面http://www.b.csrf-test.html,此页面构造了CSRF以访问www.a.com。<iframe src="http://www.a.com"></iframe>,这时会发现,只能发送出Session Cookie,而Third-party Cookie被禁止了。

对于第三方Cookie的默认拦截策略,不同浏览器的策略不一样,不能一概而论。

若CSRF攻击的目标并不需要使用Cookie,那也不必顾虑浏览器的Cookie策略了。

4.3CSRF的防御

1.验证码

验证码被认为是对抗CSRF攻击最简洁而有效的防御方法。

CSRF攻击的过程,往往是在用户不知情的情况下构造了网络请求。而验证码,则强制用户必须与应用进行交互,才能完成最终请求,因此在通常情况下,验证码能够很好地遏制CSRF攻击。
出于用户体验考虑,网站不能给所有的操作都加上验证码。因此,验证码只能作为防御CSRF的一种辅助手段。

2.Referer Check

3.Anti CSRF Token

业界针对CSRF的防御,一致的做法是使用一个Token。

CSRF的本质:

CSRF为什么能够攻击成功?其本质原因是重要操作的所有参数都是可以被攻击者猜测到的

攻击者只有预测出URL的所有参数与参数值,才能成功地构造一个伪造的请求;反之,攻击者将无法攻击成功。

出于这个原因,可以想到一个解决方案:把参数加密,或者使用一些随机数,从而让攻击者无法猜测到参数值,这是”不可预测性原则”的一种应用。

举例说明,一个删除操作的URL是:

http://host/path/delete?username=abc&item=123

把其中的username参数改成哈希值:

http://host/path/delete?username=md5(salt+abc)&item=123

这样在攻击者不知道salt的情况下,是无法构造出这个URL的。

但是!这个方法存在一些问题。

1.加密或混淆后的URL变得非常难读,对普通用户非常不友好;
2.如果加密的参数每次都改变,则某些URL无法被用户收藏;
3.普通的参数如果也被加密或者哈希,会给数据分析工作带来很大的困扰。

更常用的方案就是要讲的Anti CSRF Token

会上面的URL中,新增加一个参数Token。这个Token的值是随机的,不可预测:

http://host/path/delete?username=md5(salt+abc)&item=123&token=[random(seed)]

Token需要足够随机,必须使用安全的随机数生成算法,或者采用真随机数生成器(物理随机)。Token应该作为一个”秘密”,为用户与服务器所共同持有,不能被第三者知晓。在实际应用中,Token可以放在用户的Session中,或者浏览器的Cookie中

Token需要同时放在表单和Session中。这提交请求时,服务器只需验证表单中的Token,与用户Session(或Cookie)中的Token是否一致。

在使用Token时,应该尽量把Token放在表单中。把敏感操作由GET改为POST,以form表单(或者AJAX)的形式提交,可以避免Token泄露。

4.4总结

CSRF攻击是攻击者利用用户的身份操作用户账户的一种攻击方式。

第五章:点击劫持(clickjacking)

点击劫持

点击劫持是一种视觉上的欺骗手段。攻击者使用一个透明的,不可见的iframe,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户在不知情的情况下点击透明的iframe页面。恰好在功能性按钮上,进而欺骗。

第六章:HTML5安全

第三篇:服务器端应用安全

第七章:注入攻击

注入攻击的本质,是把用户输入的数据当做代码执行。这里有两个关键条件

1.用户能够控制输入
2.原本程序要执行的代码,拼接了用户输入的数据

7.1SQL注入

在SQL注入的过程中,如果网站的Web服务器开启了错误回显,则会为攻击者提供极大的便利。

7.1.1盲注(Blind Injection)

没有错误回显的情况,实行盲注

举例说明:
一个应用的URL如下:

http://newspaper/items.php?id=2

执行的SQL语句为:

SELECT title,body FROM items WHERE ID=2

如果攻击者构造如下的条件语句:

http://newspaper/items.php?id=2 and 1=2

实际执行的SQL语句为:

SELECT title,body FROM items WHERE ID=2 and 1=2

“and 1=2”永远是一个假命题,攻击者将看到一个空的结果或者出错页面。
为了进一步确认注入是否存在,还要构造”and 1=1”,如果能够返回,说明该参数存在SQL注入漏洞!

怎样防御SQL注入呢?

一般来说,防御SQL注入的最佳方式,就是使用预编译语句,绑定变量。也就是常用的用?代替将要填充的值。

还可以使用常用的手段来加固,比如检查数据类型使用安全函数等。

在对抗注入攻击时,只需要牢记”数据与代码分离原则”,在”拼凑”发生的地方进行安全检查,就能避免这方面的问题。

第八章:文件上传漏洞

文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。

“文件上传”功能本身没有问题,但有问题的是文件上传后,服务器怎么处理,解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。

大多数情况下,文件上传漏洞一般都是指“上传Web脚本能够被服务器解析”的问题,也就是通常说的webshell的问题。要完成这个攻击,要满足几个条件:

1.上传的文件能够被Web容器解释执行。所以文件上传后所在目录要是Web容器所覆盖到的路径
2.用户能够从Web上访问这个文件。如果文件上传了,但用户无法通过Web访问,或者无法使得Web容器解释这个脚本,就不能称之为漏洞。
3.用户上传的文件若被安全检查,格式化,图片压缩等功能改变了内容,则可能导致攻击不成功。

Apache文件解析问题

Apache对于文件名的解析是从后往前解析的,直到遇见一个Apache认识的文件类型为止。比如: phpShell.php.rar.rar.rar。
如果Apache不认识.rar这个文件类型,所以一直遍历后缀到.php,然后认为这时一个PHP类型的文件。如果不考虑这些因素,写出的安全检查功能可能会存在缺陷。比如.rar是一个合法的上传需求,在应用里只判断文件的后缀是否是.rar,最终用户上传的是phpShell.php.rar.rar.rar,从而导致脚本被执行。

Apache默认的定义哪些文件是能够被认识的,是在/conf/web.xml中。

<!-- ===================== Default MIME Type Mappings =================== -->  <!-- When serving static resources, Tomcat will automatically generate    -->  <!-- a "Content-Type" header based on the resource's filename extension,  -->  <!-- based on these mappings.  Additional mappings can be added here (to  -->  <!-- apply to all web applications), or in your own application's web.xml -->  <!-- deployment descriptor.                                               -->  <!-- Note: Extensions are always matched in a case-insensitive manner.    -->  //如果想添加自定义的mapping,可以在这里添加或者在自己项目中的web.xml中<mime-mapping>        <extension>rar</extension>        <mime-type>application/x-rar-compressed</mime-type>    </mime-mapping><mime-mapping>        <extension>mp3</extension>        <mime-type>audio/mpeg</mime-type>    </mime-mapping>

利用上传文件钓鱼

钓鱼网站在传播时,会通过利用XSS,服务器端302跳转等功能,从正常的网站跳转到钓鱼网站。在一开始,看到的是正常的域名,但这种钓鱼,仍然会在URL中暴露真实的钓鱼网站地址,细心点的用户可能不会上当,这是一般的钓鱼做法

而利用文件上传功能,钓鱼者可以先将包含了HTML的文件(比如一张图片)上传到目标网站,然后通过传播这个文件的URL进行钓鱼,则URL中不会出现钓鱼地址,更具有欺骗性

8.3设计安全的文件上传功能

总结为3点:

1.文件上传的目录设置为不可执行
只要Web容器无法解析该目录下的文件,即使攻击者上传了脚本文件,服务器本省也不会收到影响。

在实际应用中,很多大型网站的上传应用,文件上传后会放到独立的存储上,做静态文件处理,一方面方便使用缓存加速,降低性能损耗;另一方面也杜绝了脚本执行的可能

2.判断文件类型

强烈推荐白名单的方式,不再使用黑名单。此外,对于图片的处理,可以使用压缩函数或者resize函数,在处理图片的同时破坏图片中可能包含的HTML代码。

3.使用随机数改写文件名和文件路径

文件上传如果要执行代码,则需要用户能够访问到这个文件。在某些情况中,用户能上传,但不能访问。如果应用使用随机数改写文件名和文件路径,将极大地增加攻击的成本。

4.单独设置文件服务器的域名

由于浏览器同源策略的关系,一系列客户端攻击将失效,比如上传crossdomain.xml,上传包含JS的XSS利用等问题将得到解决。但能否如此设置,还需要看具体的业务环境。

第九章:认证与会话管理

“认证”是最容易理解的一种安全。最常见的认证方式就是用户名和密码,但认证的手段远远不止于此。

9.1Who am I?

认证的目的是为了认出用户是谁,而授权的目的是为了决定用户能够做什么

钥匙在认证的过程中,被称为“凭证”(Credential),开门的过程,对应的是登录(Login)

可是开门之后,什么事情能做,什么事情不能做,就是“授权”的管理范围了。

开门之后,“能否进入卧室”这个权限被授予的前提,是需要识别出来的人到底是主人还是客人,所以如何授权是取决于认证的

持有主人钥匙的人一定是主人吗?钥匙仅仅是一个很脆弱的凭证,其他的有诸如指纹,人脸,声音等生物特征来识别一个人的凭证。

认证实际上就是一个验证凭证的过程

9.2密码那些事儿

密码的保存:

密码必须以不可逆的加密算法,或者是单向散列函数算法,加密后存储在数据库中。这样做是为了尽最大可能保证密码的私密性。即使是网站的管理人员,也不能够看到用户的密码。这种情况下,即使黑客入侵了网站,导出了数据库中的数据,也无法获取到密码的明文。

因为MD5是不可逆加密算法,一般采用彩虹表进行破解。彩虹表的思路是收集尽可能多的密码明文和明文对应的MD5值。这样只需要查询MD5值,就能找到该MD5值对应的明文。

为了避免密码哈希值泄露后,黑客能够直接通过彩虹表查询出密码明文,在计算密码明文的哈希值时,增加一个“Salt”。“Salt”是一个字符串,它的作用是增加明文的复杂度,并使得彩虹表一类的攻击失效

Salt的使用如下:

MD5(Username+Password+Salt)

其中,Salt=acjjfdk…(随机字符串)

Salt应该保存在服务器端的配置文件中,并妥善保管

9.3多因素认证

9.4Session与认证

密码与证书等认证手段,一般仅仅用于登录(Login)的过程。当登录完成后,用户访问网站的页面,不可能每次浏览器请求时都再使用密码认证一次。因此,当认证成功后,就需要替换一个对用户透明的凭证,这就是SessionID

当用户登录完成后,在服务器端就会创建一个新的会话(Session),会话会保存用户的状态和相关信息。服务器端维护所有用户的Session,此时的认证,只需要知道是哪个用户在浏览当前的页面即可。

为了告诉服务器应该使用哪一个Session,浏览器需要把当前用户持有的SessionID告知服务器

最常见的做法就是把SessionID加密后保存在Cookie中,因为Cookie会随着HTTP请求头发送,且受到浏览器同源策略的保护。

SessionID一旦在生命周期内被窃取,等同于账户失窃。同时由于SessionID是用户登录之后才持有的认证凭证,因此黑客不需要再攻击登录过程,在设计安全方案时需要意识到这一点。

SessionID劫持就是一种通过窃取用户SessionID后,使用该SessionID登录进目标账户的攻击方法,此时攻击者实际上是使用了目标账户的有效Session。如果SessionID是保存在Cookie中的,则这种攻击可以成为Cookie劫持。

SessionID除了可以保存在Cookie中外,还可以保存在URL中,作为请求的一个参数。但这种方式的安全性难以经受考验

9.5Session Fixation攻击

什么是Session Fixation呢?举个例子,如果A将汽车买个了B,但是A并没有把所有的车钥匙都交给B,自己私藏了一把。这时候如果B没有给车换锁的话,A仍然可能用私藏的钥匙使用汽车。

这个没有换“锁”而导致的安全问题,就是Session Fixation问题。对比到网站当中,如果登录前后用户的SessionID没有发生改变,则会存在Session Fixation问题

具体攻击的过程是,用户X(攻击者)先获取到一个未经认证的SessionID,然后将这个SessionID交给用户Y去认证,Y完成认证后,服务器并未更新此SessionID的值(注意是未改变SessionID,而不是未改变Session,未改变SessionID是最大的错误啊),所以X可以直接凭借此SessionID登录进Y的账户。

X如果才能让Y使用这个SessionID呢?如果SessionID保存在Cookie中,比较难做到这一点。但若SessionID保存在URL中,则X只需要诱使Y打开这个URL即可

解决Session Fixation的正确做法当然是,登录完成后,重写SessionID

值得庆幸的是,在今天使用Cookie才是互联网的主流,sid的方式逐渐被淘汰。而由于网站想保存到Cookie中的东西越来越多,因此用户登录后,网站将一些数据保存到关键的Cookie中,已经成为一种普遍的做法。

9.6Session保持攻击

一般来说,Session是由生命周期的,当用户长时间未活动后,或者用户点击退出后,服务器将销毁Session。

一般的应用都会给Session设置一个失效时间,当到达失效时间后,Session将会被销毁。

但有一些系统,处于用户体验的考虑,只要这个用户还”活着“,就不会让这个用户的Session失效。从而攻击者可以通过不停地发起访问请求,让Session一直“活”下去

在Web开发中,网站访问量如果比较大,维护Session可能会给网站带来巨大的负担。因此,有一种做法,就是服务器端不维护Session,而把Session放在Cookie中加密保存。当浏览器访问网站时,会自动带上Cookie,服务器端只需要解密Cookie即可得到当前用户的Session了。这样的Session如何使其过期呢?很多应用都是利用Cookie的Expire标签来控制Session的失效时间,这就给了攻击者可乘之机

Cookie的Expire时间是完全可以由客户端控制的。篡改这个时间,并使之永久有效,就有可能获得一个永久有效的Session,而服务器端是完全无法察觉的

9.7单点登录(SSO)

单点登录的全称是Single Sign On,简称SSO。它希望用户只需要登录一次,就可以访问所有的系统。

第十章:访问控制

10.1What Can I Do?

上一章”认证”解决了“Who am I”的问题,这一章“授权”则解决了“Who can I do”的问题。

权限控制,抽象地说,都是某个主体(subject)对某个客体(object)需要实施某种操作(operation),而系统对这种操作的限制就是权限控制。

在一个安全系统中,确定主体的身份是“认证”解决的问题;而客体是一种资源,是主体发起的请求的对象。在主体对客体进行操作的过程中,系统控制主体不能“无限制”地对客体进行操作,这个过程就是“访问控制”。

在Web应用中,根据访问客体的不同,常见的访问控制可以分为:
1.“基于URL的访问控制”
2.“基于方法的访问控制”
3.“基于数据的访问控制”

10.2垂直权限管理

访问控制实际上是建立用户与权限之间的对应关系。现在广泛的做法是,“基于角色的访问控制(Role-Based Access Control)”,简称RBAC

Spring Security提供了一系列的“Filter Chain”,每个安全检查的功能都会插入在这个链条中。在与Web系统集成时,开发者只需要将所有用户请求的URL都引入到Filter Chain中即可

10.3水平权限管理

但是“垂直权限管理”是否够用呢?不是。

比如优酷网发生的用户越权访问问题
用户登录后,可以通过以下方式查看他人的来往邮件(只需要改变下面地址的数值id即可),查看和修改他人的专辑信息。

http://u.youku.com/my_mail/inbox_id123456

漏洞分析:
用户访问了原本不属于他的数据
用户A与用户B可能属于同一个角色RoleX,但是用户A与用户B都各自拥有一些私有数据,在正常情况下,应该只有用户自己才能访问自己的私有数据。

但是在上面的RBAC模型下,系统只会验证用户A是否属于角色RoleX,而不会判断用户A是否能访问只属于用户B的数据dataB,因此,发生了越权访问。这种问题,我们称之为“水平权限管理问题”。

相对于垂直权限管理来说,水平权限问题出在同一个角色上。系统只验证了能访问数据的角色,既没有对角色内的用户做细分,也没有对数据的子集做细分,因此缺乏一个用户到数据之间的对应关系。由于水平权限管理是系统缺乏一个数据级的访问控制所造成的,因此水平权限管理又可以称之为”基于数据的访问控制“

10.4OAuth简介

OAuth是一个在不提供用户名和密码的情况下,授权第三方应用访问Web资源的安全协议

OAuth与OpenID都致力于让互联网变得更加的开放。OpenID解决的是认证问题,OAuth则更注重授权。认证和授权的关系其实是一脉相承的,后来人们发现,其实更多的时候真正需要的是对资源的授权

第十一章:加密算法与随机数

11.6密钥管理

密码学里的基本原则:

密码系统的安全性应该依赖于密钥的复杂性,而不应该依赖于算法的保密性

在安全领域里,选择一个足够安全的加密算法不是困难的事情,难的是密钥管理

最常见的错误,就是将密钥硬编码在代码里

对于Web应用来说,常见的做法是将密钥(包括密码)保存在配置文件或者数据库中。密钥所在的配置文件或数据库需要严格的控制访问权限。同时也要确保运维或DBA中具有访问权限的人越少越好。

一个比较安全的密钥管理系统,可以将所有的密钥(包括一些敏感配置文件)都集中保存在一个服务器(集群)上,并通过Web Service的方式提供获取密钥的API。每个Web应用在需要使用密钥时,通过带认证信息的API请求密钥管理系统,动态获取密钥。Web应用不能把密钥写入本地文件中,值加载到内存,这样动态获取密钥最大程度地保护了密钥的私密性。密钥集中管理,降低了系统对于密钥的耦合性,也有利于定期更换密钥。

11.7.4使用安全的随机数

在重要或者敏感的系统中,一定要使用足够强壮的随机数生成算法。在Java中,可以使用java.security.SecureRandom

在算法上还可以通过多个随机数的组合,以增加随机数的复杂性。比如通过给随机数使用MD5算法后,再连接一个随机字符,然后再使用一个MD5算法一次。这些方法,都可以极大地增加攻击的难度。

第十二章:Web框架安全

在现代Web开发中,使用MVC架构是一种流行的做法。MVC是Model-View-Controller的缩写,它将Web应用分为三层,View成负责用户视图、页面展示等工作;Controller负责应用的逻辑实现,接受View层传入的用户请求,并转发给对应的Model做处理;Model层则负责实现模型,完成数据的处理

从数据的流入来看,用户提交的数据先后流经了View层,Controller层,Model层,数据的流出则反过来

第十三章:应用层拒绝服务攻击

13.1网络层DDOS

在正常情况下,TCP**三次握手过程**如下:

1.客户端向服务器端发送一个SYN包,包含客户端使用的端口号和初始序列号x;

2.服务器端收到客户端发送来的SYN包后,向客户端发送一个SYN和ACK都置位的TCP报文,包含确认号x+1和服务器端的初始序列号y;

3.客户端收到服务器端返回的SYN+ACK报文后,向服务器端返回一个确认号为y+1,序号为x+1的ACK报文,一个标准的TCP连接完成。

而SYN flood在攻击时,首先伪造大量的源IP地址,分别向服务器端发送大量的SYN包,此时服务器端会返回SYN/ACK包,因为源地址是伪造的,所以伪造的IP并不会回答,服务器端没有收到伪造IP的回应,会重试3到5次并且等待一个SYN Time(一般为30秒到2分钟),如果超时则丢弃这个连接。攻击者大量使用这种伪造源地址的SYN请求,服务器端将会消耗非常多的资源(CPU和内存)来处理这种半连接,同时还要不断对这些IP进行SYN+ACK重试。最后的结果是服务器无暇理睬正常的连接请求,导致拒绝服务。

对抗SYN flood的一种方法:SYN Cookie

SYN Cookie的主要思想是为每一个IP地址分配一个“Cookie”,并统计每个IP地址的访问频率。如果在短时间内收到大量的来自同一个IP地址的数据包,则认为受到攻击,之后来自这个IP地址的包将被丢弃。

13.2应用层DDOS

应用层DDOS,不同于网络层DDOS,由于发生在应用层,因此TCP三次握手已经完成,连接已经建立,所以发起的攻击IP都是真实的。但应用层DDOS有时甚至比网络层DDOS攻击更为可怕

说明应用层DDOS是怎么回事,需要先说”CC攻击”。

13.2.1CC攻击

CC攻击的原理非常简单,就是对一些消耗资源比较大的应用不断发起正常的请求,以达到消耗服务器资源的目的。在Web应用中,查询数据库,读/写硬盘文件等操作,相对都会消耗比较多的资源。比如下面的这段PHP代码:

$sql = "select * from post where tagid='$tagid' order by postid desc limit $start,30";

当post表数据庞大,翻页频繁,$start数字急剧增加时,查询结果集=$start+30。该查询效率呈现明显下降趋势,而多并发频繁调用,因查询无法立即完成,资源无法立即释放,会导致数据库请求连接过多,数据库阻塞,网站无法正常打开。

应用层DDOS攻击说白了,是针对服务器性能的一种攻击,那么许多优化服务器性能的方法,都或多或少地能缓解这种攻击。比如将使用频率高的数据放在memcache中,相对于查询数据库所消耗的资源来说,查询memcache所消耗的资源可以忽略不计。

13.2.2限制请求频率

最常见的针对应用层DDOS攻击的防御手段,是在应用中针对每个“客户端”做一个请求频率的限制

但道高一尺,魔高一丈。基于IP地址和Cookie的防御机制可能会随着IP的改变而失效。比如使用“代理服务器”,联想到了之前写爬虫是用的同样的IP轮换策略。

13.5资源耗尽攻击

几种攻击策略:

1.以极低的速度往服务器发送HTTP请求。由于Web Server对于并发的连接数都有一定的上限,因此若是恶意地占用住这些连接不释放,那么Web Server的所有连接都被恶意连接占用,从而无法接受新的请求,导致拒绝服务。要保持住这个连接,要构造一个畸形的HTTP请求,准确地说,是不完整的HTTP请求,让服务器以为后面还有数据没有传输完成,从而一直保持住连接。

从这里,可以看出所有拒绝服务供给的本质实际上是对有限资源的无限制滥用

比如,上面的“有限”的资源是Web Server的连接数。这是一个有上限的值,比如在Apache中这个值是由MaxClinets定义。如果恶意客户端可以无限制地将连接数占满,就完成了对有限资源的恶意消耗,导致拒绝服务。

所以拒绝应用层DDOS的核心思路是,限制住每个不可信任的资源使用者的配额

等等。

第十五章:Web Server配置安全

15.1Apache安全

需要注意的是,Apache以root身份或者admin身份运行是一个非常糟糕的决定

使用高权限身份来运行Apache的结果可能是灾难性的,它会带来两个可怕的后果:

1.当黑客入侵Web成功时,将直接获得一个高权限(比如root或admin)的shell

2.应用程序本身具备比较高权限,当出现bug时,可能会带来较高风险,比如删除本地重要文件,杀死进程等不可预知的结果。

比较好的做法是使用专用的用户身份运行Apache,这个用户身份不应该具备shell,它唯一的作用就是用来运行Web应用。

Apache还提供了一些配置参数,可以用来优化服务器的性能:

TimeOutKeepAliveLimitRequestBodyLimitRequestFieldsLimitRequestFieldSizeLimitRequestLineLimitXMLRequestBodyAcceptFilterMaxRequestWokers

在Apache官方文档中,对如何使用这些参数给出了指导。

15.2Nginx安全

第四篇:互联网公司安全运营

第十六章:互联网业务安全

第十七章:安全开发流程(SDL)

安全开发流程,能够帮助企业以最小的成本提高产品的安全性,它符合“Secure at the source”的战略思想。实施好安全开发流程,对企业安全的发展来说,可以起到事半功倍的效果。

第十八章:安全运营

0 0
原创粉丝点击