第八章 文件上传漏洞
文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力
文件上传后导致的常见安全问题一般有:
❍ 上传文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本,导致代码执行;
❍ 上传文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在该域下的行为(其他通过类似方式控制策略文件的情况类似);
❍ 上传文件是病毒、木马文件,黑客用以诱骗用户或者管理员下载执行;
❍ 上传文件是钓鱼图片或为包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈。
在大多数情况下,文件上传漏洞一般都是指“上传Web脚本能够被服务器解析”的问题,也就是通常所说的webshell的问题
要完成攻击,需要满足的条件
1、上传文件能被web容器解析执行,所以文件上传后所在目录要是web容器覆盖到的路径。
2、用户能从web上访问这个文件。
3、最后,用户上传的文件若被安全检查、格式化、图片压缩等功能改变了内容,则也可能导致攻击不成功
绕过文件上传
检查文件名后缀,如何绕过?
绕过检查,针对后缀名验证,可以使用%00字节 在C、PHP等语言的常用字符串处理函数中,0x00被认为是终止符。受此影响的环境有Web应用和一些服务器。比如应用原本只允许上传JPG图片,那么可以构造文件名(需要修改POST包)为xxx.php[\0].JPG,其中[\0]为十六进制的0x00字符,.JPG绕过了应用的上传文件类型判断;但对于服务器端来说,此文件因为0字节截断的关系,最终却会变成xxx.php
检查文件头:为了绕过应用中类似MIME Sniff的功能,常见的攻击技巧是伪造一个合法的文件头,而将真实的PHP等脚本代码附在合法的文件头
Web Server的一些“功能”可能会被攻击者利用,绕过文件上传功能的一些安全检查。如nginx,apache,IIS都曾出现过文件解析漏洞。
利用上传文件钓鱼,利用文件上传功能,钓鱼者可以先将包含了HTML的文件(比如一张图片)上传到目标网站,然后通过传播这个文件的URL进行钓鱼
设计安全的文件上传功能
1、文件上传的目录设置为不可执行 主要web容器无法解析该目录下文件,即使攻击者上传脚本文件,服务器本身也不会受到影响
2、判断文件类型在判断文件类型时,可以结合使用MIME Type、后缀检查等方式。在文件类型检查中,强烈推荐白名单的方式,黑名单的方式已经无数次被证明是不可靠的。此外,对于图片的处理,可以使用压缩函数或者resize函数,在处理图片的同时破坏图片中可能包含的HTML代码。
3、使用随机数改写文件名和文件路径文件上传如果要执行代码,则需要用户能够访问到这个文件。在某些环境中,用户能上传,但不能访问。如果应用使用随机数改写了文件名和路径,将极大地增加攻击的成本。与此同时,像shell.php.rar.rar这种文件,或者是crossdomain.xml这种文件,都将因为文件名被改写而无法成功实施攻击
4、单独设置文件服务器的域名由于浏览器同源策略的关系,一系列客户端攻击将失效,比如上传crossdomain.xml、上传包含JavaScript的XSS利用等问题将得到解决。但能否如此设置,还需要看具体的业务环境。文件上传问题,看似简单,但要实现一个安全的上传功能,殊为不易。如果还要考虑到病毒、木马、色情图片与视频、反动政治文件等与具体业务结合更紧密的问题,则需要做的工作就更多了。不断地发现问题,结合业务需求,才能设计出最合理、最安全的上传功能。
第九章 认证与会话管理
认证解决的是“Who Am I? ”的问题,它就像一个房间的大门一样,是非常关键的一个环节
认证的英文是Authentication,授权则是Authorization。
认证的目的是为了认出用户是谁,而授权的目的是为了决定用户能够做什么。
认证实际上就是一个验证凭证的过程。(凭证credential)
如果只有一个凭证被用于认证,则称为“单因素认证”;如果有两个或多个凭证被用于认证,则称为“双因素(Two Factors)认证”或“多因素认证”。一般来说,多因素认证的强度要高于单因素认证,但是在用户体验上,多因素认证或多或少都会带来一些不方便的地方。
密码的使用
密码的优点是使用成本低,认证过程实现起来很简单;缺点是密码认证是一种比较弱的安全方案,可能会被猜解,要实现一个足够安全的密码认证方案,也不是一件轻松的事情。
目前并没有一个标准的密码策略,但是根据OWASP推荐的一些最佳实践,我们可以对密码策略稍作总结。密码长度方面:
❍ 普通应用要求长度为6位以上;
❍ 重要应用要求长度为8位以上,并考虑双因素认证。密码复杂度方面:
❍ 密码区分大小写字母;
❍ 密码为大写字母、小写字母、数字、特殊符号中两种以上的组合;
❍ 不要有连续性的字符,比如1234abcd,这种字符顺着人的思路,所以很容易猜解;
❍ 尽量避免出现重复的字符,比如1111。
除了OWASP推荐的策略外,还需要注意,不要使用用户的公开数据,或者是与个人隐私相关的数据作为密码。比如不要使用QQ号、身份证号码、昵称、电话号码(含手机号码)、生日、英文名、公司名等作为密码,这些资料往往可以从互联网上获得,并不是那么保密。
目前黑客们常用的一种暴力破解手段,不是破解密码,而是选择一些弱口令,比如123456,然后猜解用户名,直到发现一个使用弱口令的账户为止
密码的保存也有一些需要注意的地方。一般来说,密码必须以不可逆的加密算法,或者是单向散列函数算法,加密后存储在数据库中
2011年CSDN数据库被黑客公布,用户密码被发现明文存储。将明文密码经过哈希后(比如MD5或者SHA-1)再保存到数据库中,是目前业界比较普遍的做法—
目前黑客们广泛使用的一种破解MD5后密码的方法是“彩虹表(Rainbow Table)
为了避免密码哈希值泄露后,黑客能够直接通过彩虹表查询出密码明文,在计算密码明文的哈希值时,增加一个“Salt”。“Salt”是一个字符串,它的作用是为了增加明文的复杂度,并能使得彩虹表一类的攻击失效
salt使用方法: MD5(Username+Password+Salt)
Salt应该保存在服务器端的配置文件中,并妥善保管。
多因素认证
如支付宝除了支付密码外,手机动态口令、数字证书、宝令、支付盾、第三方证书等都可用于用户认证
session与认证
密码与证书等认证手段,一般仅仅用于登录(Login)的过程。当登录完成后,用户访问网站的页面,不可能每次浏览器请求页面时都再使用密码认证一次。因此,当认证成功后,就需要替换一个对用户透明的凭证。这个凭证,就是SessionID
SessionID一旦在生命周期内被窃取,就等同于账户失窃
Session劫持就是一种通过窃取用户SessionID后,使用该SessionID登录进目标账户的攻击方法,此时攻击者实际上是使用了目标账户的有效Session。如果SessionID是保存在Cookie中的,则这种攻击可以称为Cookie劫持。
Cookie泄露的途径有很多,最常见的有XSS攻击、网络Sniff,以及本地木马窃取。对于通过XSS漏洞窃取Cookie的攻击,通过给Cookie标记httponly,可以有效地缓解XSS窃取Cookie的问题。但是其他的泄露途径,比如网络被嗅探,或者Cookie文件被窃取,则会涉及客户端的环境安全,需要从客户端着手解决
SessionID除了可以保存在Cookie中外,还可以保存在URL中,作为请求的一个参数。但是这种方式的安全性难以经受考验。
在生成SessionID时,需要保证足够的随机性,比如采用足够强的伪随机数生成算法。现在的网站开发中,都有很多成熟的开发框架可以使用。这些成熟的开发框架一般都会提供Cookie管理、Session管理的函数,可以善用这些函数和功能
Session Fixation攻击
没有换“锁”而导致的安全问题
解决Session Fixation的正确做法是,在登录完成后,重写SessionID。
Session保持攻击
如果session有保持功能,可以不断刷新页面,使session不过期
session在cookie中,cookie过期时间由客户端控制,可能成为永久cookie。
如何对抗这种Session保持攻击呢?常见的做法是在一定时间后,强制销毁Session。这个时间可以是从用户登录的时间算起,设定一个阈值,比如3天后就强制Session过期。但强制销毁Session可能会影响到一些正常的用户,还可以选择的方法是当用户客户端发生变化时,要求用户重新登录。比如用户的IP、UserAgent等信息发生了变化,就可以强制销毁当前的Session,并要求用户重新登录。最后,还需要考虑的是同一用户可以同时拥有几个有效Session。若每个用户只允许拥有一个Session,则攻击者想要一直保持一个Session也是不太可能的。当用户再次登录时,攻击者所保持的Session将被“踢出”
单点登录SSO
单点登录的英文全称是Single Sign On,简称SSO。它希望用户只需要登录一次,就可以访问所有的系统。从用户体验的角度看,SSO无疑让用户的使用更加的方便;从安全的角度看,SSO把风险集中在单点上,这样做是有利有弊的
降低这种风险的办法是在一些敏感的系统里,再单独实现一些额外的认证机制。比如网上支付平台,在付款前要求用户再输入一次密码,或者通过手机短信验证用户身份
目前互联网上最为开放和流行的单点登录系统是OpenID
总结
认证的手段是丰富多彩的。在互联网中,除了密码可以用于认证外,还有很多新的认证方式可供使用。我们也可以组合使用各种认证手段,以双因素认证或多因素认证的方式,提高系统的安全强度。
在Web应用中,用户登录之后,服务器端通常会建立一个新的Session以跟踪用户的状态。每个Session对应一个标识符SessionID, SessionID用来标识用户身份,一般是加密保存在Cookie中。有的网站也会将Session保存在Cookie中,以减轻服务器端维护Session的压力。围绕着Session可能会产生很多安全问题,这些问题都是在设计安全方案时需要考虑到的。
最后介绍了单点登录,以及最大的单点登录实现:OpenID。单点登录有利有弊,但只要能够合理地运用这些技术,对网站的安全就都是有益处的
第十章 访问控制
“权限”实际上是一种“能力”,“权限控制”的问题都可以归结为“访问控制”的问题
“授权”则解决了“What can I do? ”的问题。权限控制,或者说访问控制,广泛应用于各个系统中。抽象地说,都是某个主体(subject)对某个客体(object)需要实施某种操作(operation),而系统对这种操作的限制就是权限控制。
在网络中,为了保护网络资源的安全,一般是通过路由设备或者防火墙建立基于IP的访问控制。
在操作系统中,对文件的访问也有访问控制。此时“主体”是系统的用户,“客体”是被访问的文件,能否访问成功,将由操作系统给文件设置的ACL(访问控制列表)决定
主体不能无限制对客体进行操作,这个过程就是访问控制
主体“能够做什么”,就是权限。权限可以细分成不同的能力(capability)。在Linux的文件系统中,将权限分成了“读”、“写”、“执行”三种能力
访问控制分类
在Web应用中,根据访问客体的不同,常见的访问控制可以分为“基于URL的访问控制”、“基于方法(method)的访问控制”和“基于数据的访问控制
“基于URL的访问控制”如果存在缺陷,则用户可以未经授权,访问不该访问的页面,如审核,审批,数据修改页面,随机篡改数据。有的页面只能管理员访问,但未做访问控制,
人以用户构造正确URL就能访问,把需要保护的页面藏起来,并不是解决问题的办法。
垂直权限管理
访问控制实际上是建立用户与权限之间的对应关系,现在应用广泛的一种方法,就是“基于角色的访问控制(Role-Based Access Control)”,简称RBAC
RBAC 事先会在系统中定义出不同的角色,不同的角色拥有不同的权限,一个角色实际上就是一个权限的集合。而系统的所有用户都会被分配到不同的角色中,一个用户可能拥有多个角色,角色之间有高低之分(权限高低)。在系统验证权限时,只需要验证用户所属的角色,然后就可以根据该角色所拥有的权限进行授权了
Spring Security中的权限管理,就是RBAC模型的一个实现
Spring Security提供两种权限管理方式,一种是“基于URL的访问控制”,一种是“基于method的访问控制”。这两种访问控制都是RBAC模型的实现。不同的URL对于能访问其的角色有着不同的要求
基于角色的权限管理(RBAC模型),我们可以称之为“垂直权限管理”。
不同角色的权限有高低之分。高权限角色访问低权限角色的资源往往是被允许的,而低权限角色访问高权限角色的资源往往则被禁止。如果一个本属于低权限角色的用户通过一些方法能够获得高权限角色的能力,则发生了“越权访问”。
在配置权限时,应当使用“最小权限原则”,并使用“默认拒绝”的策略,只对有需要的主体单独配置“允许”的策略。这在很多时候能够避免发生“越权访问”
水平权限管理
通过篡改id,访问其他用户资源。网站后台应用并未判断资源是否属于当前用户。在RBAC这种“基于角色的访问控制”模型下,系统只会验证用户A是否属于角色RoleX,而不会判断用户A是否能访问只属于用户B的数据DataB,因此,发生了越权访问。这种问题,我们就称之为“水平权限管理问题
由于水平权限管理是系统缺乏一个数据级的访问控制所造成的,因此水平权限管理又可以称之为“基于数据的访问控制"
数据级权限管理并没有很通用的解决方案,因为1)基于业务 2)难以通过自动化方式扫描出来 3)设计的时候没有考虑清楚,后续修改大动干戈。
一般是具体问题具体解决。一个简单的数据级访问控制,可以考虑使用“用户组(Group)”的概念。比如一个用户组的数据只属于该组内的成员,只有同一用户组的成员才能实现对这些数据的操作。此外,还可以考虑实现一个规则引擎,将访问控制的规则写在配置文件中,通过规则引擎对数据的访问进行控制。
OAuth是一个在不提供用户名和密码的情况下,授权第三方应用访问Web资源的安全协议
总结
访问控制解决了“What Can I Do? ”的问题。
还分别介绍了“垂直权限管理”,它是一种“基于角色的访问控制”;
以及“水平权限管理”,它是一种“基于数据的访问控制”。
这两种访问控制方式,在进行安全设计时会经常用到。访问控制与业务需求息息相关,并非一个单纯的安全问题。
因此在解决此类问题或者设计权限控制方案时,要重视业务的意见。最后,无论选择哪种访问控制方式,在设计方案时都应该满足“最小权限原则”,这是权限管理的黄金法则。
第十一章 加密算法和伪随机数
加密算法
密码学基本原则:密码系统的安全性应该依赖于密钥的复杂性,而不应该依赖算法的保密性。
选择安全的加密算法不困难,难的是密钥管理。
密钥管理常见的错误,就是将密钥硬编码在代码里。同样的,将加密密钥、签名的salt等“key”硬编码在代码中,是非常不好的习惯。
对于Web应用来说,常见的做法是将密钥(包括密码)保存在配置文件或者数据库中,在使用时由程序读出密钥并加载进内存。密钥所在的配置文件或数据库需要严格的控制访问权限,同时也要确保运维或DBA中具有访问权限的人越少越好。在应用发布到生产环境时,需要重新生成新的密钥或密码,以免与测试环境中使用的密钥相同。
密钥管理的主要目的,还是为了防止密钥从非正常的渠道泄露。定期更换密钥也是一种有效的做法。一个比较安全的密钥管理系统,可以将所有的密钥(包括一些敏感配置文件)都集中保存在一个服务器(集群)上,并通过Web Service的方式提供获取密钥的API。
伪随机数
伪随机数的问题在于不够随机,如Sun Java 6 Update 11之前的createTempFile()方法中生成的临时文件顺序递增,范围很小。
密码、key、SessionID、token等许多非常关键的“secret”往往都是通过伪随机数算法生成的。如果使用了弱伪随机数算法,则可能会导致非常严重的安全问题。
时间函数生成的随机数,并不随机,可预测,不要把时间函数当成随机数使用!
在重要或敏感的系统中,一定要使用足够强壮的随机数生成算法。在Java中,可以使用java.security.SecureRandom
而在Linux中,可以使用/dev/random或者 /dev/urandom来生成随机数
从算法上还可以通过多个随机数的组合,以增加随机数的复杂性。比如通过给随机数使用MD5算法后,再连接一个随机字符,然后再使用MD5算法一次。这些方法,也将极大地增加攻击的难度
总结
在Web安全中,我们更关心的是怎样用好加密算法,做好密钥管理,以及生成强壮的随机数。
在加密算法的选择和使用上,有以下最佳实践:(1)不要使用ECB模式;(2)不要使用流密码(比如RC4);(3)使用HMAC-SHA1代替MD5(甚至是代替SHA1);(4)不要使用相同的key做不同的事情;(5)salts与IV需要随机产生;(6)不要自己实现加密算法,尽量使用安全专家已经实现好的库;(7)不要依赖系统的保密性。
当你不知道该如何选择时,有以下建议:
(1)使用CBC模式的AES256用于加密;
(2)使用HMAC-SHA512用于完整性检查;
(3)使用带salt的SHA-256或SHA-512用于Hashing。
第十三章 应用层拒绝服务攻击
DDOS又称为分布式拒绝服务,全称是Distributed Denial of Service。DDOS本是利用合理的请求造成资源过载,导致服务不可用
常见的DDOS攻击有SYN flood、UDP flood、ICMP flood等。
网络层DDOS攻击,SYN flood,利用TCP利用设计的缺陷。其中SYN flood是一种最为经典的DDOS攻击,伪造IP地址向服务器发包,占用服务器资源
对抗SYN flood的主要措施有SYN Cookie/SYN Proxy、safereset等算法。
应用层DOS攻击:IP地址是真实的,如爬虫可以把小网站爬死,应用层DDOS攻击是针对服务器性能的一种攻击,许多优化服务器性能的方法,都或多或少地能缓解此种攻击。
比如将使用频率高的数据放在memcache中,相对于查询数据库所消耗的资源来说,查询memcache所消耗的资源可以忽略不计。但很多性能优化的方案并非是为了对抗应用层DDOS攻击而设计的,因此攻击者想要找到一个资源消耗大的页面并不困难。比如当memcache查询没有命中时,服务器必然会查询数据库,从而增大服务器资源的消耗,攻击者只需要找到这样的页面即可。同时攻击者除了触发“读”数据操作外,还可以触发“写”数据操作,“写”数据的行为一般都会导致服务器操作数据库。
最常见的针对应用层DDOS攻击的防御措施,是在应用中针对每个“客户端”做一个请求频率的限制
应用层DDOS攻击并非一个无法解决的难题,一般来说,我们可以从以下几个方面着手。
首先,应用代码要做好性能优化。合理地使用memcache就是一个很好的优化方案,将数据库的压力尽可能转移到内存中。
此外还需要及时地释放资源,比如及时关闭数据库连接,减少空连接等消耗。其次,在网络架构上做好优化。善于利用负载均衡分流,避免用户流量集中在单台服务器上。同时可以充分利用好CDN和镜像站点的分流作用,缓解主站的压力。
最后,也是最重要的一点,实现一些对抗手段,比如限制每个IP地址的请求频率
CC攻击的原理非常简单,就是对一些消耗资源较大的应用页面不断发起正常的请求,以达到消耗服务端资源的目的。在Web应用中,查询数据库、读/写硬盘文件等操作,相对都会消耗比较多的资源
防御应用层DDOS
1、验证码,但验证码不宜使用频繁
2、通过判断|HHTP头中的User-Agent来是被客户端,但可以篡改,不能信任。
3、让客户端解析js或者flash,但是有的自动化脚本内嵌在浏览器无法检测该种攻击
4、webserver层,如apache配置文件一些参数可以缓解DDOS攻击
资源耗尽攻击
SIowIoris攻击极低速度往服务器发送HTTP请求,占用webserver并发连接数至上限,导致DOS。此类拒绝服务攻击的本质,实际上是对有限资源的无限制滥用。
有限”的资源是Web Server的连接数。这是一个有上限的值,比如在Apache中这个值由MaxClients定义。如果恶意客户端可以无限制地将连接数占满,就完成了对有限资源的恶意消耗,导致拒绝服务
HTTP POST DOS类似SIowIoris攻击
凡是资源有“限制”的地方,都可能发生资源滥用,从而导致拒绝服务,也就是一种“资源耗尽攻击”。
出于可用性和物理条件的限制,内存、进程数、存储空间等资源都不可能无限制地增长,因此如果未对不可信任的资源使用者进行配额的限制,就有可能造成拒绝服务。内存泄漏是程序员经常需要解决的一种bug,而在安全领域中,内存泄漏则被认为是一种能够造成拒绝服务攻击的方式。
Server Limit DOS 利用webserver对HTTP包长度限制进行攻击
拒绝服务攻击”的本质实际上就是一种“资源耗尽攻击”,因此在设计系统时,需要考虑到各种可能出现的场景,避免出现“有限资源”被恶意滥用的情况
正则表达式写的不对也会引起的DOS ,ReDOS 构造输入消耗正则引擎解析数据,