伪随机数,是通过一些数学算法生成的随机数,并非真正的随机数。密码学上的安全伪随机数应该是不可压缩的。对应的“真随机数”,则是通过一些物理系统生成的随机数,比如电压的波动、硬盘磁头读/写时的寻道时间、空中电磁波的噪声等。
在Web应用中,使用伪随机数的地方非常广泛。密码、key、SessionID、token等许多非常关键的“secret”往往都是通过伪随机数算法生成的。
很多伪随机数算法与系统时间有关,而有的程序员甚至就直接使用系统时间代替随机数的生成。这样生成的随机数,是根据时间顺序增长的,可以从时间上进行预测,从而存在安全隐患。
伪随机数是由数学算法实现的,它真正随机的地方在于“种子(seed)”。种子一旦确定后,再通过同一伪随机数算法计算出来的随机数,其值是固定的,多次计算所得值的顺序也是固定的。
建立在这个基础上,就可以得到一种可行的攻击方式:
(1)通过一些方法猜解出种子的值;
(2)通过mt_srand()对猜解出的种子值进行播种;
(3)通过还原程序逻辑,计算出对应的mt_rand()产生的伪随机数的值。
在一个Web应用中,有很多地方都可以获取到随机数,从而提供猜解种子的可能。Stefan Esser提供了一种“CrossApplication Attacks”的思路,即通过前一个应用在页面上返回的随机数值,猜解出其他应用生成的随机数值。
Stefan Esser描述这个攻击过程如下:
(1)使用Keep-Alive HTTP请求在phpBB2论坛中搜索字符串‘a’;
(2)搜索必然会出来很多结果,同时也泄露了search_id;
(3)很容易通过该值猜解出随机数的种子;
(4)攻击者仍然使用Keep-AliveHTTP头发送一个重置admin密码的请求给WordPressblog;
(5)WordPress mt_rand()生成确认链接,并发送到管理员邮箱;
(6)攻击者根据已算出的种子,可以构造出此确认链接;
(7)攻击者确认此链接(仍然使用Keep-Alive头),WordPress将向管理员邮箱发送新生成的密码;
(8)因为新密码也是由mt_rand()生成的,攻击者仍然可以计算出来;
(9)从而攻击者最终获取了新的管理员密码。
在重要或敏感的系统中,一定要使用足够强壮的随机数生成算法。在Java中,可以使用java.security.SecureRandom;而在Linux中,可以使用/dev/random或者/dev/urandom来生成随机数,只需要读取即可;而在PHP 5.3.0及其之后的版本中,若是支持openSSL扩展,也可以直接使用函数来生成随机数。
除了以上方法外,从算法上还可以通过多个随机数的组合,以增加随机数的复杂性。比如通过给随机数使用MD5算法后,再连接一个随机字符,然后再使用MD5算法一次。这些方法,也将极大地增加攻击的难度。
MVC框架安全
在现代Web开发中,使用MVC架构是一种流行的做法。MVC是Model-View-Controller的缩写,它将Web应用分为三层,View层负责用户视图、页面展示等工作;Controller负责应用的逻辑实现,接收View层传入的用户请求,并转发给对应的Model做处理;Model层则负责实现模型,完成数据的处理。
从数据的流入来看,用户提交的数据先后流经了View层、Controller、Model层,数据的流出则反过来。在设计安全方案时,要牢牢把握住数据这个关键因素。在MVC框架中,通过切片、过滤器等方式,往往能对数据进行全局处理,这为设计安全方案提供了极大的便利。
一些主要的Web安全威胁,如XSS、CSRF、SQL注入、访问控制、认证、URL跳转等不涉及业务逻辑的安全问题,都可以集中放在MVC框架中解决。
在框架中实施安全方案,比由程序员在业务中修复一个个具体的bug,有着更多的优势。
首先,有些安全问题可以在框架中统一解决,能够大大节省程序员的工作量,节约人力成本。当代码的规模大到一定程度时,在业务的压力下,专门花时间去一个个修补漏洞几乎成为不可能完成的任务。
其次,对于一些常见的漏洞来说,由程序员一个个修补可能会出现遗漏,而在框架中统一解决,有可能解决“遗漏”的问题。这需要制定相关的代码规范和工具配合。
最后,在每个业务里修补安全漏洞,补丁的标准难以统一,而在框架中集中实施的安全方案,可以使所有基于框架开发的业务都能受益,从安全方案的有效性来说,更容易把握。
Struts2命令执行漏洞
springMVC命令执行漏洞
Django命令执行漏洞
常见的DDOS攻击有SYN flood、UDP flood、ICMP flood等。其中SYNflood是一种最为经典的DDOS攻击,其发现于1996年,但至今仍然保持着非常强大的生命力。SYN flood如此猖獗是因为它利用了TCP协议设计中的缺陷,而TCP/IP协议是整个互联网的基础,牵一发而动全身,如今想要修复这样的缺陷几乎成为不可能的事情。
在正常情况下,TCP三次握手过程如下:
(1)客户端向服务器端发送一个SYN包,包含客户端使用的端口号和初始序列号x;
(2)服务器端收到客户端发送来的SYN包后,向客户端发送一个SYN和ACK都置位的TCP报文,包含确认号xx1和服务器端的初始序列号y;
(3)客户端收到服务器端返回的SYNSACK报文后,向服务器端返回一个确认号为yy1、序号为xx1的ACK报文,一个标准的TCP连接完成。
而SYN flood在攻击时,首先伪造大量的源IP地址,分别向服务器端发送大量的SYN包,此时服务器端会返回SYN/ACK包,因为源地址是伪造的,所以伪造的IP并不会应答,服务器端没有收到伪造IP的回应,会重试3~5次并且等待一个SYNTime(一般为30秒至2分钟),如果超时则丢弃这个连接。攻击者大量发送这种伪造源地址的SYN请求,服务器端将会消耗非常多的资源(CPU和内存)来处理这种半连接,同时还要不断地对这些IP进行SYN+ACK重试。最后的结果是服务器无暇理睬正常的连接请求,导致拒绝服务。
对抗SYN flood的主要措施有SYNCookie/SYN Proxy、safereset等算法。SYN Cookie的主要思想是为每一个IP地址分配一个“Cookie”,并统计每个IP地址的访问频率。如果在短时间内收到大量的来自同一个IP地址的数据包,则认为受到攻击,之后来自这个IP地址的包将被丢弃。
应用层DDOS,不同于网络层DDOS,由于发生在应用层,因此TCP三次握手已经完成,连接已经建立,所以发起攻击的IP地址也都是真实的。但应用层DDOS有时甚至比网络层DDOS攻击更为可怕,因为今天几乎所有的商业Anti-DDOS设备,只在对抗网络层DDOS时效果较好,而对应用层DDOS攻击却缺乏有效的对抗手段。
CC攻击的原理:对一些消耗资源较大的应用页面不断发起正常的请求,以达到消耗服务端资源的目的。在Web应用中,查询数据库、读/写硬盘文件等操作,相对都会消耗比较多的资源。
应用层DDOS攻击还可以通过以下方式完成:在黑客入侵了一个流量很大的网站后,通过篡改页面,将巨大的用户流量分流到目标网站。
应用层DDOS攻击是针对服务器性能的一种攻击,那么许多优化服务器性能的方法,都或多或少地能缓解此种攻击。比如将使用频率高的数据放在memcache中,相对于查询数据库所消耗的资源来说,查询memcache所消耗的资源可以忽略不计。但很多性能优化的方案并非是为了对抗应用层DDOS攻击而设计的,因此攻击者想要找到一个资源消耗大的页面并不困难。比如当memcache查询没有命中时,服务器必然会查询数据库,从而增大服务器资源的消耗,攻击者只需要找到这样的页面即可。同时攻击者除了触发“读”数据操作外,还可以触发“写”数据操作,“写”数据的行为一般都会导致服务器操作数据库。
最常见的针对应用层DDOS攻击的防御措施,是在应用中针对每个“客户端”做一个请求频率的限制。
通过IP地址与Cookie 定位一个客户端,如果客户端的请求在一定时间内过于频繁,则对之后来自该客户端的所有请求都重定向到一个出错页面。
从架构上看,这段代码需要放在业务逻辑之前,才能起到保护后端应用的目的,可以看做是一个“基层”的安全模块。
然而这种防御方法并不完美,因为它在客户端的判断依据上并不是永远可靠的。这个方案中有两个因素用以定位一个客户端:一个是IP地址,另一个是Cookie。但用户的IP地址可能会发生改变,而Cookie又可能会被清空,如果IP地址和Cookie同时都发生了变化,那么就无法再定位到同一个客户端了。
如何让IP地址发生变化呢?使用“代理服务器”是一个常见的做法。在实际的攻击中,大量使用代理服务器或傀儡机来隐藏攻击者的真实IP地址,已经成为一种成熟的攻击模式。攻击者使用这些方法可不断地变换IP地址,就可以绕过服务器对单个IP地址请求频率的限制了。
防御首先,应用代码要做好性能优化。合理地使用memcache,将数据库的压力尽可能转移到内存中。此外还需要及时地释放资源,比如及时关闭数据库连接,减少空连接等消耗。
其次,在网络架构上做好优化。善于利用负载均衡分流,避免用户流量集中在单台服务器上。同时可以充分利用好CDN和镜像站点的分流作用,缓解主站的压力。
最后,也是最重要的一点,实现一些对抗手段,比如限制每个IP地址的请求频率。