一、 Web平台的安全审计
评审方法分别从黑盒和白盒两方面考虑。黑盒着重从几种常用的攻击手段入手谈谈如何防御。白盒方面,谈谈从代码级做好防御,这方面的攻击往往不太容易,但也要防范于未然。
1)黑盒攻击及防御
Web入侵分为两个步骤,首先是前期的渗透工作,而后是提权工作。渗透程度有深浅,要看Web服务器的安全程度。浅则窃取一些用户账号相关信息,深则获得管理员账号。
最常用的渗透手段是SQL注入、XSS(跨站)、上传漏洞。这里只从防御的角度阐述。
SQL注入:SQL注入成功后危害很大,因为这是获取数据信息的最直接入口。危害如下:
1.泄露敏感信息
— 攻击者可以获取后台数据库的种类、版本,操作系统信息,数据库名、表名、字段名以及数据库中的数据信息。
2.绕过认证机制
— 无需知道口令就能以某些用户身份登陆应用系统。
3.篡改敏感数据
— 对数据库进行增加、删除、篡改的操作。
4.执行任意系统命令
— 利用数据库支持的特定功能(例如存储过程)在数据库所在操作系统中执行任意命令。
不同的数据库,不同的数据库配置,危害程度不一样
— SQL Server默认配置并且使用sa帐号。
— MySQL版本、数据库root帐号、系统root用户启动服务。
防御方法为:
(1) 过滤拼接字符串中的用户数据,尤其不能忽视间接输入数据的SQL语句拼接。
数字型的注入漏洞防护:
使用is_numeric(),ctype_digit()判断,使用intval()转换,使用str_length()限制输入的字符长度。
字符型的注入漏洞防护:
使用mysql_real_escape_string()过滤,使用str_length()限制输入的字符长度。
(2)如果可能,使用占位符、预编译的方法代替SQL语句拼接。
(占位符参考:http://wyllife.blog.163.com/blog/static/411639012011413111235998/)
(3)使用WEB应用扫描器检测程序相对比较明显的SQL注入问题。
(4)php.ini文件中设置display_errors = Off,数据库查询函数前面加一个@字符。因为通过构造一些恶意的SQL语句造成网页显示错误信息,而错误信息又包括一些敏感的信息,比如数据库表名、字段名等就不好了。
XSS( 跨站脚本):也是高危漏洞之一,获得管理员Cookie、用户Cookie、挂马。
防御方法为:
显示用户数据时对 “<>&”等HTML符号进行编码转换—htmlspecialchars。
(2) 过滤必要的XHTML属性及各种编码,尤其在WEB提供样式功能的时候。
(3) 设计时要考虑到关键内容不能由用户的直接数据显示,要有转换或后台间接审核的过程。
(4) 用WEB应用扫描器对程序进行检测。
上传漏洞:主要分为两大类,一类是没有对上传格式做很好的限制,比如linux环境下上传个php的木马,过滤方法不能使用排除法,因为有些扩展名是不能预料到的。比如.php3,.php4也可以当做php网页来执行。要限制住只能使用某某扩展名,比如".JPG"、".BMP"、".GIF"。而且要再服务端做校验,不要紧紧用客户端脚本,因为可以修改发送的封包的,把封包中的muma.php.JPG修改为muma.php。
一类是网页嵌入图片时,没有使用<IMG>标签链接图像地址,而是把图片内容包含在网页中,这样就可以构造恶意的图片内容来搞破坏了,比如:
GIF89a <head> <meta http-equiv = "refresh" content = "1; url=http://www.hacker.com/" />. </head> |
访问这个网页会加载图片,就跳到挂有木马的http://www.hacker.com/
网站了。
使用你们一律把文件生成缩略图快照的方法,两类上传漏洞都防住了。
DDOS攻击:由于错误配置或者软件漏洞而导致,这类攻击可以通过开发商发布补丁来解决;
由于协议考虑不足而导致,例如smurf攻击
利用大量请求来占用过多的服务资源,致使服务超载,无法响应其他的请求。这些服务资源包括网络带宽、文件系统空间容量、CPU时间等。
DDoS攻击利用因特网中的成百上千台计算机向一个目标服务器发起DoS攻击。当黑客攻占了因特网中某些计算机后,他在被攻占的系统中安装攻击软件,然后远程遥控进行攻击。
攻击包类型包括:TCP/SYN、Teardrop 攻击、Ping of
Death、ICMP Echo Request、UDP Flood、HTTP Flood等多种方式。
TCP/SYN:利用TCP三次握手,不发送ACK包,造成协议栈中有限长度的连接队列被占满,无法响应接下来的连接请求。
Teardrop 攻击:利用错误的IP数据包分片。例如:一共要发送40个字节,第一段数据的数据包发送了数据的0-36字节,但是第二段的4个字节却是数据的24-27字节,这样就会使一些操作系统迷惑。在系统进行的内存拷贝操作中出现负数(数据越界),从而使系统崩溃。
Ping of Death:根据数据分段的执行方式,可以发送非法的数据包,包含多于65535个字节的数据。由于各个分段是依赖于分段偏移量进行组装的,因此在最后一个分段,就可能用适合的分段尺寸结合偏移量使得组装好的数据包长度使16位的变量溢出,导致系统崩溃。
除了单纯的直接的攻击方式,采用攻击放大更有效。
例如Smurf 攻击:
攻击者伪装成受害主机地址,向广播地址(如192.168.1.255)发送echo
request。
192.168.1.0/24内的所有主机并非真正的攻击目标。
受害主机(即真正的攻击目标)将会接收到来自192.168.1.*的ICMP
Echo reply。
如下图:
攻击放大的另一个例子:
利用DNS服务器可以放大50倍。
全世界有580,000个开放的DNS解析服务器。
DoS攻击的解决方法:
a) 防火墙和路由器过滤。
b) 操作系统的改进
c) 退让策略
增加资源
负载均衡,服务器集群
d) 协议修订
SYN Cache
SYN Cookie
在防火墙收到来自外网的SYN包时,它并不直接进行转发,而是缓存在本地,再按照原来SYN
Cookie的机制制作好一个针对这个SYN包的SYN+ACK包,注意,这个SYN+ACK包中的ack顺序号为特制的cookie值c,更重要的是这个包的的源地址被伪造成了S的地址(为了描述方便,我们这里暂时不考虑NAT等其他因素)。这样C会接收到这个SYN+ACK包,并认为是从S反馈回来的。于是C再响应一个ACK包,并认为与S的TCP连接已经建立起来。这时防火墙F收到这个ACK包,按照前面的描述的SYN
Cookie原理来检查这个ACK中的ack顺序号。如果认为合法,F将本地缓存的来自C的SYN包发送给S,这时S会响应一个SYN+ACK包到C,其中也携带一个seq号,
我们设为c`。当然这个包不会到达C,而是由防火墙F截取,F根据这个包中的序列号等信息,造一个ACK包响应到S。这时的情况是:C认为自己已经与S建立了TCP连接;S认为自己与C建立了TCP连接。以后的TCP数据内容可以直接穿过防火墙F,在S和C之间交互。
以上SYN Cookie可以有效防止TCP/SYN Flood,但对于其它基于纯粹流量的攻击,只能使用负载均衡,服务器集群退让策略,或者方汉提出的IDC流量清洗。
2)、白盒代码审计及安全配置
(1) 信息泄露:
— 服务器版本信息泄露: 若hack得知操作系统版本、网站架构、数据库类型,会使后面的攻击顺利得多。
— 运行环境遗留测试文件
phpinfo.php
conn.asp.bak
— 程序出错泄露物理路径: 若得知服务器上文件存放路径,可以使用WebShell、可以操作的组件对其进行读取、下载、修改。
— 程序查询出错返回SQL语句
— 过于详细的用户验证返回信息:这不是一个好习惯。
减少信息泄露:
1)服务器的配置尽可能去掉版本信息。
2)程序出错信息定向输出到日志服务器或指定的日志文件。
3)保持运营环境干净,不要在服务器上直接修改或测试程序。
(2) Cookie的欺骗:
Cookie是纯客户端数据,非常容易伪造。
文件型的Cookie可以直接改浏览器的Cookie文件。
通过curl或firefox的LiveHTTPHeaders插件可以轻松伪造各种类型的Cookie数据。
使用Cookie时应注意的问题:
尽量不要用Cookie明文存储敏感信息。
数据加密后保存到客户端的Cookie。
为Cookie设置适当的有效时间。
(3) 服务端的安全配置:
网络安全不是单一程序员或单一网络管理员的事情。
安装最新的版本和最新的安全补丁。
删除不必要的功能和服务。
启用服务端的安全特性。
合理的权限配置。
(4) PHP安全编程:
PHP编程安全问题。
a) 变量初始化。
b) 文件操作。
c) 文件包含。
d) 文件上传。
e) 调用系统命令。
f) 正则表达式的陷阱。
g) 变量类型的陷阱。
h) PHP+MySQL注入问题。
i) 服务端的安全配置。
(5) 变量初始化问题:
原因:大部分web程序员习惯直接使用变量,这也是web语言的一个重要特性。
早期版本PHP默认设置register_globals = On,客户端传递的数据直接注册为程序内变量。
没有对变量进行初始化而做逻辑比较等操作容易导致安全问题。
解决:
a) web程序员也要养成对程序变量进行初始化的习惯。
b) 配置php.ini,设置register_globals = Off,这使得程序使用PHP自身初始化的默认值,一般为0或空,避免了攻击者控制判断变量。
(6) 文件操作问题
原因:PHP提供了不少文件操作相关的函数,对文件名参数检查不严就容易导致系统信息泄露的安全问题。
解决:
a) 尽量减少系统文件操作。
b) 严格检查用户输入变量。
c) 设置open_basedir选项,把程序能够操作的文件限制在某个目录下。
(7) 文件包含问题
PHP的包含函数有include(), include_once(),
require(), require_once。为程序模块化设计提供了基础。
函数区别:
reqiure(可N次包含),require_once(只包含一次,默认第一次)和include(可N次包含),include_once(只包含一次,默认第一次).。
require在被包含的文件有错误发生时代码将不再往下执行(主文件)。
include在被包含的文件有错误发生时代码将仍然往下执行(主文件)。
详解区别见:
http://php.chinaunix.net/manual/zh/function.require.php
http://php.chinaunix.net/manual/zh/function.include.php
例如如下代码:
<?php
$file=$_GET[‘page’];
?>
Include($file); |
访问http://127.0.0.1/dvwa/vulnerabilities/fi/?page=1.txt
即可显示1.txt文件内容。
利用方法为:使用copy /b 1.gif+s.php 2.gif生成gif文件,然后上传到网站,记录下上传后的地址。把1.txt替换成这个地址,之后访问这个地址就是WebShell了。
防御方法为:
1. 关闭allow_url_fopen 、allow_url_include。
2. 进行验证。
3. 设置open_basedir选项,把程序能够操作的文件限制在某个目录下面。
(8)规避文件上传风险:
限制上传文件类型:注意Apache的Multiple Extensions功能:evil.php.xxx。
使用is_uploaded_file和move_uploaded_file函数,从而避免拷贝系统文件。
使用$_FILES专用数组变量:$_FILES['file']['name']和$_FILES['file']['type']用户可控。
nobody可写的WEB目录去掉PHP解释功能 -php_flag engine
off。
(9)调用系统命令问题
原因: PHP支持多种方法调用系统命令,一般用来简化程序设计。
和SQL注入类似,命令字符串由用户可控数据拼接而成,那么很可能存在严重的安全问题。
解决: 使用escapeshellcmd()函数过滤用户输入的shell命令。
(10)变量类型的陷阱
原因: 脚本程序员基本上不关注变量类型,但是实际上PHP的变量是有类型概念的。
1.1.serialize字串可以定义各种类型的变量。
编程的疏忽导致漏洞的产生。
案例:phpBB 2.0.12非法获取管理员权限及路径泄露漏洞。
解决: a) 逻辑比较时注意变量类型。
b) 必要的时候使用"===",那么连变量类型一起比较。
(11) PHP5对$_SERVER变量不做处理
即使magic_quotes_gpc启用,但是PHP5对$_SERVER变量不做处理。
很多$_SERVER变量是用户可以伪造的,比如HTTP_USER_AGENT。
容易导致SQL注入等问题。
(12) PHP的安全配置
a) register_globals = Off
b) safe_mode = On
c) allow_url_fopen = Off
d) 有文件操作的地方设置必要的open_basedir选项
e) 关闭警告及错误信息,定向输出到日志文件或日志服务器
f) 使用disable_functions禁用无用函数 eval。
(13) 服务端的安全配置
a) 合理的文件权限设置
b) 取消WEB用户对apache日志的读权限
c) nobody有写权限的WEB目录取消PHP解释权限
d) 有可能的话编译PHP脚本
e) Zend SafeGuard Suite
f) Turck MMCache
g)eAccelerator
h) 保持运行环境干净--不要在WEB目录放测试文件,不要直接在服务器编辑、测试程序。
(14) WEB应用扫描器
1.AppScan
— 非常专业的商业WEB应用扫描器
— 功能强大,准确率高,尤其是跨站脚本和SQL注入的检测
— 扫描速度较慢
2.WebInspect
— 相比AppScan,功能毫不逊色,抓URL的能力更强
— 安装需要SQL Server,比较麻烦
3.Acunetix.Web.Vulerability.Scanner
— 相比AppScan和WebInspect ,纯属友情客串
4.绿盟科技极光扫描器
— 能够扫描一些SQL注入的问题
|