OWASP TOP 10-2010 web 安全(中文版)

liangbq 贡献于2013-06-10

作者 juyan  创建于2010-09-14 03:05:00   修改者Icey  修改于2011-05-07 13:00:00字数26670

文档摘要: 开放式Web应用程序安全项目(OWASP,Open Web Application Security Project)是一个组织,它提供有关计算机和互联网应用程序的公正、实际、有成本效益的信息。其目的是协助个人、企业和机构来发现和使用可信赖软件。.
关键词:

OWASP TOP 10-2010 开放式Web应用程序安全项目(OWASP,Open Web Application Security Project)是一个组织,它提供有关计算机和互联网应用程序的公正、实际、有成本效益的信息。其目的是协助个人、企业和机构来发现和使用可信赖软件。 OWASP发布了最新的Web应用脆弱性的top 10,这是继2007年OWASP对TOP10进行修订后进行的又一次更改,该版本暂定为OWASP TOP 10 - 2010。新版本的OWASP TOP10中主要有以下变化: 1. Top10的命名发生了变化。 原先的Top10全称为“The top 10 most critical web application security vulnerabilities”,即“Web应用的十大关键脆弱性”,现在Top10的全称为“The top 10 most critical web application security risks”,即“Web应用的十大关键风险”。 2. OWASP Top 10的风险评估方法   此次Top 10的评估是依据OWASP的风险评估方法来对OWASP TOP10排序的。 3. 替换了2个风险   此次Top 10与2007年的Top 10相比, 在内容上去掉了“Malicious File Execution”(恶意文件执行)和“Information leakage and improper error handling”(信息泄露及不恰当的错误处理),增加了“Security misconfiguration”(错误安全配置)和“Unvalidated redirects and forwards”(未验证的重定向和传递)。  OWASP TOP10 2007  OWASP TOP10 2010  A2-注入  A1-注入  A1-跨站脚本(XSS)  A2-跨站脚本(XSS)  A7-错误的认证和会话管理  A3-错误的认证和会话管理  A4-不正确的直接对象引用  A4-不正确的直接对象引用  A5-伪造跨站请求(CSRF)  A5-伪造跨站请求(CSRF)    A6-安全性误配置  A10-限制远程访问失败  A7-限制远程访问失败    A8-未验证的重定向和传递  A8-不安全的加密存储  A9-不安全的加密存储  A9-不足的传输层保护  A10-不足的传输层保护  A3-恶意文件执行    A6-不安全的通讯   / 39 OWASP风险评估方法 OWASP所选取的10大风险是依据OWASP的风险评估方法,我们从标准的风险模型开始,即风险=可能性*后果,下面我们以以下步骤来说明某个风险的严重程度: 第一步:识别风险 识别风险作为评估的第一步,我们必须找到与这个风险相关的威胁、相应的攻击方法、隐含在里面的脆弱性以及最终可能造成的后果,当然可能存在多种攻击方法和多种后果,在评估时我们往往会采用最坏选择,这样就能更客观的反应该风险的最终评级; 第二步:考虑影响可能性的因素 通常,我们不可能很精准的说出某个风险的可能性数值,所以我们一般用高、中、低来表示,而且影响某个风险的可能性的因素有很多,对于每个因素我们用0到9的数值来表示。 类别 因素 分项 分值 威胁 技能要求 无需技能 1 需要一些技术 3 高级的计算机用户 4 需要网络和编程技术 6 安全渗透技术 9 成功攻击后攻击者的益处 很低或无益 1 可能会有回报 4 高回报 9 所需资源或机会 需要很大资源或高权限访问 0 需要特定的访问权限和特定的资源 4 需要一些访问权限和资源 7 无需权限或资源 9 所需的攻击者的角色 开发者 2 系统管理员 2 内部用户 4 合作伙伴 5 / 39 认证用户 6 匿名Internet用户 9 脆弱性 发现该弱点的难易度 技术上不可行 1 困难 3 容易 7 可用自动化工具发现 9 利用该弱点的难易度 只是理论上的 1 困难 3 容易 5 可用自动化工具实现 9 该弱点的流行度 不为人知 1 隐藏 4 明显 6 公众皆知 9 入侵被察觉的可能性 应用程序主动检测 1 记录日志并审核 3 记录日志未审核 8 无日志 9 第三步:考虑影响后果的因素 在考虑攻击后果的时候,我们会考虑两种后果,一种是应用的“技术后果”,它所使用的数据,提供的功能等等,另一种就是它的“商业后果”,显然后者则更为重要,但往往后者难以估量,所以我们需要尽可能从技术上去考虑,进而来估计后者的数据。 类别 因素 分项 分值 技术后果 保密性损失 很少的非敏感的数据泄漏 2 很少的敏感数据泄漏 6 大量的非敏感数据泄漏 6 大量的敏感数据泄漏 9 / 39 A1-注入 注入往往是应用程序缺少对输入进行安全性检查所引起的,攻击者把一些包含指令的数据发送给解释器,解释器会把收到的数据转换成指令执行。常见的注入包括SQL注入,OS Shell,LDAP,XPath,Hibernate等等,其中SQL注入尤为常见。这种攻击所造成的后果往往很大,一般整个数据库的信息都能被读取或篡改,通过SQL注入,攻击者甚至能够获得更多的包括管理员的权限。 防范SQL注入——编程篇 SQL注入往往是在程序员编写包含用户输入的动态数据库查询时产生的,但其实防范SQL注入的方法非常简单。程序员只要a)不再写动态查询,或b)防止用户输入包含能够破坏查询逻辑的恶意SQL语句,就能够防范SQL注入。在这篇文章中,我们将会说明一些非常简单的防止SQL注入的方法。   我们用以下Java代码作为示例: String query ="SELECT account_balance FROM user_data WHERE user_name ="   + request.getParameter("customerName");   try { Statement statement = connection.createStatement( …); ResultSet results = Statement.executeQuery(query); }   在以上代码中,我们可以看到并未对变量customerName做验证,customerName的值可以直接附在query语句的后面传送到数据库执行,则攻击者可以将任意的SQL语句注入。   防范方法1:参数化查询   参数化查询是所有开发人员在做数据库查询时首先需要学习的,参数化查询迫使所有开发者首先要定义好所有的SQL代码,然后再将每个参数逐个传入,这种编码风格就能够让数据库辨明代码和数据。   参数化查询能够确保攻击者无法改变查询的内容,在下面修正过的例子中,如果攻击者输入了UsrID是“’or ‘1 ‘=’1”,参数化查询会去查找一个完全满足名字为‘or ‘1 ‘=’ 1的用户。   对于不同编程语言,有一些不同的建议:   Java EE——使用带绑定变量的PreparedStatement(); / 39   .Net——使用带绑定变量的诸如SqlCommand()或OleDbCommand()的参数化查询;   PHP——使用带强类型的参数化查询PDO(使用bindParam());   Hibernate——使用带绑定变量的createQuery()。   Java示例: String custname = request.getParameter("customerName"); String query ="SELECT account_balance FROM user_data WHERE user_name= ?";   PreparedStatement pstmt = connection.prepareStatement(query); Pstmt.setString(1,custname); ResultSet results = pstmt.executeQuery();   C# .Net示例: String query ="SELECT account_balance FROM user_data WHERE user_name = ?"; Try {        OleDbCommand command = new OleDbCommand(query,connection);    command.Parameters.Add(new OleDbParameter("customerName",CustomerName.Text));    OleDbDataReader reader = command.ExecuteReader();   } catch (OleDbException se){   //error handling } 防范方法2:存储过程   存储过程和参数化查询的作用是一样的,唯一的不同在于存储过程是预先定义并存放在数据库中,从而被应用程序调用的。   Java存储过程示例: String custname = request.getParameter("customerName"); try {       CallableStatement cs = connection.prepareCall("call sp_getAccountBalance(?)}");       cs.setString(1,custname);       Result results = cs.executeQuery(); }catch(SQLException se){ //error handling / 39 }  VB .Net存储过程示例: Try Dim command As SqlCommand = new SqlCommand("sp_getAccountBalance",connection)  command.CommandType = CommandType.StoredProcedure  command.Parameters.Add(new SqlParameter("@CustomerName",CustomerName.Text))  Dim reader As SqlDataReader = command.ExecuteReader()  ‘… Catch se As SqlException  ‘error handling End Try 防范方法3:对所有用户输入进行转义   我们知道每个DBMS都有一个字符转义机制来告知DBMS输入的是数据而不是代码,如果我们将所有用户的输入都进行转义,那么DBMS就不会混淆数据和代码,也就不会出现SQL注入了。   当然,如果要采用这种方法,那么你就需要对所使用的数据库转义机制,也可以使用现存的诸如OWASP ESAPI的escaping routines。ESAPI目前是基于MySQL和Oracle的转义机制的,使用起来也很方便。一个Oracle的ESAPI的使用示例如下: ESAPI.encoder().encodeForSQL(new OracleCodec(),queryparam);   那么,假设你有一个要访问Oracle数据库的动态查询代码如下: String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+req.getParameter("userID")+"’ and user_password = ‘"+req.getParameter("pwd")+"’"; try {       Statement statement = connection.createStatement(…);       ResultSet results = statement.executeQuery(query) ; }  那么,你就必须重写你的动态查询的第一行如下: Codec ORACLE_CODEC = new OracleCodec(); String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+ ESAPI.encoder().encodeForSQL(ORACLE_CODEC,req.getParameter( / 39 "userID"))+"’ and user_password = ‘"+ ESAPI.encoder().encodeForSQL(ORACLE_CODEC,req.getParameter("pwd"))+"’";   当然,为了保证自己代码的可读性,我们也可以构建自己的OracleEncoder: Encoder e = new OracleEncoder(); String query ="SELECT user_id FROM user_data WHERE user_name = ‘"       + oe.encode(req.getParameter("userID")) +"’ and user_password = ‘"       + oe.encode(req.getParameter("pwd"))+"’";   除了上面所说的三种防范方法以外,我们还建议可以用以下两种附加的方法来防范SQL注入:最小权限法、输入验证白名单法。   最小权限法:   为了避免注入攻击对数据库造成的损害,我们可以把每个数据库用户的权限尽可能缩小,不要把DBA或管理员的权限赋予你应用程序账户,在给用户权限时是基于用户需要什么样的权限,而不是用户不需要什么样的权限。当一个用户只需要读的权限时,我们就只给他读的权限,当用户只需要一张表的部分数据时,我们宁愿另建一个视图让他访问。   如果你的策略是都是用存储过程的话,那么仅允许应用程序的账户执行这些查询,而不给他们直接访问数据库表的权限。诸如此类的最小权限法能够在很大程度上保证我们数据库的安全。   输入验证白名单法:   输入验证能够在数据传递到SQL查询前就察觉到输入是否正确合法,采用白名单而不是黑名单则能在更大程度上保证数据的合法性。 防范SQL注入——测试篇 对于测试人员来说,如何测试SQL注入漏洞是否存在呢?   首先,我们将SQL注入攻击能分为以下三种类型:   Inband:数据经由SQL代码注入的通道取出,这是最直接的一种攻击,通过SQL注入获取的信息直接反映到应用程序的Web页面上;   Out-of-band:数据通过不同于SQL代码注入的方式获得(譬如通过邮件等)   推理:这种攻击是说并没有真正的数据传输,但攻击者可以通过发送特定的请求,重组返回的结果从而得到一些信息。   不论是哪种SQL注入,攻击者都需要构造一个语法正确的SQL查询,如果应用程序对一个不正确的查询返回了一个错误消息,那么就和容易重新构造初始的查询语句的逻辑,进而也就能更容易的进行注入;如果应用程序隐藏了错误信息,那么攻击者就必须对查询逻辑进行反向工程,即我们所谓的 / 39 “盲SQL注入”   黑盒测试及示例:   这个测试的第一步是理解我们的应用程序在什么时候需要访问数据库,典型的需要访问数据库的时机是:   认证表单:输入用户名和密码以检查是否有权限   搜索引擎:提交字符串以从数据库中获取相应的记录   电子商务站点:获取某类商品的价格等信息   作为测试人员,我们需要列对所有输入域的值可能用于查询的字段做一个表单,包括那些POST请求的隐含字段,然后截取查询语句并产生错误信息。第一个测试往往是用一个单引号“‘”或是分号“;”,前者在SQL中是字符串终结符,如果应用程序没有过滤,则会产生一条错误信息;后者在SQL中是一条SQL语句的终结符,同样如果没有过滤,也会产生错误信息。在Microsoft SQL Server中,返回的错误信息一般是这样: Microsoft OLE DB Provider for ODBC Drivers error ‘80040e14’ [Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed quotation mark before the character string ‘’. /target/target.asp, line 113   同样可用于测试的还有“--”以及SQL中的一些诸如“AND”的关键字,通常很常见的一种测试是在要求输入为数字的输入框中输入字符串,会返回如下的错误信息: Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’ [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value ‘tester’ to a column of data type int. /target/target.asp, line 113   类似上面这样的出错返回信息能让我们知道很多数据库的信息,通常不会返回那么多信息,会返回诸如“500 Server Error”的信息,那就需要“盲SQL注入”了。注意,我们需要对所有可能存在SQL注入漏洞的输入域进行测试,并且在每个测试用例时只变化一个域的值,从而才能找到真正存在漏洞的输入域。 下面我们看一下标准的SQL注入测试是怎样的。   我们以下面的SQL查询为例: / 39   SELECT * FROM Users WHERE Username='$username' AND Password='$password'   如果我们在页面上输入以下的用户名和密码:   $username = 1' or '1' = '1   $password = 1' or '1' = '1   那么整个查询语句就变为:   SELECT * FROM Users WHERE Username='1' OR '1' = '1' AND Password='1' OR '1' = '1'   假设参数值是通过GET方法传递到服务器的,且域名为www.example.com,那么我们的访问请求就是:   http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1&password=1'%20or%20'1'%20=%20'1   对上面的SQL语句作简单分析后我们就知道由于该语句永远为真,所以肯定会返回一些数据,在这种情况下实际上并未验证用户名和密码,并且在某些系统中,用户表的第一行记录是管理员,那这样造成的后果则更为严重。   另外一个查询的例子如下:   SELECT * FROM Users WHERE ((Username='$username') AND (Password=MD5('$password')))   在这个例子中,存在两个问题,一个是括号的用法,还有一个是MD5哈希函数的用法。对于第一个问题,我们可以很容易找到缺失的右括号解决,对于第二个问题,我们可以想办法使第二个条件失效。我们在查询语句的最后加上一个注释符以表示后面的都是注释,常见的注释起始符是/*(在Oracle中是--),也就是说,我们用如下的用户名和密码:   $username = 1' or '1' = '1'))/*   $password = foo   那么整条SQL语句就变为:   SELECT * FROM Users WHERE ((Username='1' or '1' = '1'))/*') AND (Password=MD5('$password')))   我们的URL请求就变为:   http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))/*&password=foo Union查询SQL注入测试 / 39   还有一种测试是利用Union的,利用Union可以连接查询,从而从其他表中得到信息,假设我们有如下的查询:   SELECT Name, Phone, Address FROM Users WHERE Id=$id   然后我们设置id的值为:   $id=1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCarTable   那么整体的查询就变为:   SELECT Name, Phone, Address FROM Users WHERE Id=1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCarTable   显然这样就能得到所有信用卡用户的信息。   盲SQL注入测试   在上面我们提到过盲SQL注入,即blind SQL injection,它意味着对于某个操作我们得不到任何信息,通常这是由于程序员已经编写了特定的出错返回页面,从而隐藏了数据库结构的信息。   利用推理方法,有时候我们能够恢复特定字段的值。这种方法通常采用一组对服务器的布尔查询,依据返回的结果来推断结果的含义。仍然延续上面的www.example.com,有一个参数名为id,那么我们输入以下url请求:   http://www.example.com/index.php?id=1'   显然由于语法错误,我们会得到一个预先定义好的出错页面,假设服务器上的查询语句为SELECT field1, field2, field3 FROM Users WHERE Id='$Id',假设我们想要得到用户名字段的值,那么通过一些函数,我们就可以逐字符的读取用户名的值。在这里我们使用以下的函数:   SUBSTRING (text, start, length),ASCII (char),LENGTH (text)   我们定义id为:   $Id=1' AND ASCII(SUBSTRING(username,1,1))=97 AND '1'='1   那么最终的SQL查询语句为:   SELECT field1, field2, field3 FROM Users WHERE Id='1' AND ASCII(SUBSTRING(username,1,1))=97 AND '1'='1'   那么,如果在数据库中有用户名的第一个字符的ASCII码为97的话,那么我们就能得到一个真值,那么我们就继续寻找该用户名的下一个字符;如果没有的话,那么我们就递增猜测第一个字符的ASCII码为98的用户名,这样反复下去就能判断出合法的用户名。   那么,什么时候我们可以结束推理呢,我们假设id的值为:   $Id=1' AND LENGTH(username)=N AND '1' = '1 / 39   其中N是我们到目前为止已经分析的字符数目,那么整体的sql查询为:   SELECT field1, field2, field3 FROM Users WHERE Id='1' AND LENGTH(username)=N AND '1' = '1'   这个查询的返回值如果是真,那我们就已经完成了推理并且我们已经得到了想要的数值,如果为假,则表示我们还要继续分析。   这种盲SQL注入会要求我们输入大量的sql尝试,有一些自动化的工具能够帮我们实现,SqlDumper就是这样的一种工具,对MySQL数据库进行GET访问请求。 存储过程注入   在上一篇《如何防范SQL注入—编程篇》中,我们提到使用存储过程是能够防范SQL注入的,但同时也要注意,存储过程如果使用不得当,使用存储过程的动态查询事实上也会造成一定的SQL注入漏洞。   以下面的SQL存储过程为例:   Create procedure user_login @username varchar(20), @passwd varchar(20) As   Declare @sqlstring varchar(250)   Set @sqlstring = ‘   Select 1 from users   Where username = ‘ + @username + ‘ and passwd = ‘ + @passwd   exec(@sqlstring)   Go   用户的输入如下:   anyusername or 1=1'   anypassword   如果我们没有对输入进行验证,那么上面的语句就会返回数据库中的一条记录。   我们再看下面的一条:   Create procedure get_report @columnamelist varchar(7900) As   Declare @sqlstring varchar(8000)   Set @sqlstring = ‘   Select ‘ + @columnamelist + ‘ from ReportTable‘   exec(@sqlstring)   Go / 39   如果用户输入是:   1 from users; update users set password = 'password'; select *   后面则显而易见,用户的所有密码都被更改且得到了报表信息。 A2-跨站脚本(XSS) 排在OWASP TOP10第2位的是Cross Site Scripting(XSS),翻译成中文即“跨站脚本攻击”。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。XSS属于被动式的攻击,因为其被动且不好利用,所以许多人常忽略其危害性。 以下内容转自百度空间的一篇关于OWASP的文章,个人觉得基本已经把跨站脚本攻击的内容阐述的比较清楚。 如何寻找XSS漏洞,XSS攻击分成两类,一类是来自内部的攻击,主要指的是利用程序自身的漏洞,构造跨站语句,如:dvbbs的showerror.asp存在的跨站漏洞。另一类则是来来自外部的攻击,主要指的自己构造XSS跨站漏洞网页或者寻找非目标机以外的有跨站漏洞的网页。如当我们要渗透一个站点,我们自己构造一个有跨站漏洞的网页,然后构造跨站语句,通过结合其它技术,如社会工程学等,欺骗目标服务器的管理员打开,然后利用下面的技术得到一个shell。 如何利用 传统的跨站利用方式一般都是攻击者先构造一个跨站网页,然后在另一空间里放一个收集cookie的页面,接着结合其它技术让用户打开跨站页面以盗取用户的cookie,以便进一步的攻击。这种方式太过于落后,对于弊端大家可能都知道,因为即便你收集到了cookie你也未必能进一步渗透进去,多数的cookie里面的密码都是经过加密的,如果想要cookie欺骗的话,同样也要受到其它的条件的限约。而另一种思路,则从一定程度上解决上述的问题。比较成熟的方法是通过跨站构造一个表单,表单的内容则为利用程序的备份功能或者加管理员等功能得到一个高权限。下面将详细的介绍这种技术。 寻找跨站漏洞 如果有代码的话比较好办,我们主要看代码里对用户输入的地方和变量有没有做长度和对”<”,”>”,”;”,”’”等字符是否做过滤。还有要注意的是对于标签的闭合,像测试QQ群跨站漏洞的时候,你在标题处输入,代码是不会被执行的,因为在源代码里,有其它的标签未闭合,如少了一个,这个时候,你只要闭合一个,代码就会执行,如:你在标题处输入 / 39 ,这样就可以弹出一个test的框。 如何利用  跨站脚本(Cross-site scripting,XSS)漏洞是Web应用程序中最常见的漏洞之一。如果您的站点没有预防XSS漏洞的固定方法,那么就存在XSS漏洞。这个利用XSS漏洞的病毒之所以具有重要意义是因为,通常难以看到XSS漏洞的威胁,而该病毒则将其发挥得淋漓尽致。 这个利用XSS漏洞的蠕虫病毒的特别之处在于它能够自我传播。myspace.com上的一个用户希望自己能够在网站的友人列表上更“受欢迎”。但是该用户不是通过普通的方法来结交新朋友,而是在自己的个人信息中添加了一些代码,导致其他人在访问他的页面时,会不知不觉地利用XSS漏洞将他加为好友。更恶劣的是,它会修改这些人的个人信息,使其他人在访问这些被感染的个人信息时,也会被感染。由于这种呈指数传播的方式,这种病毒才很快就被发现。 很难预防站点中的XSS。因此一定要认真检查您的应用程序是否存在XSS漏洞。此外,WebLogic Server的encodeXSS()也可以有所帮助。可以试着针对所有牵涉到使用encodeXSS()或其他某个筛选方法的输出找出一种编码模式——找出对一种编码模式来说不正确的应用程序往往要比找出XSS漏洞要容易的多。更重要的是,不要认为,就因为XSS漏洞是一个常见问题,所以它危害不大。 之所以出现XSS漏洞有两个原因。首先,HTML没有明确区分代码和数据。无法确定指出“这个字符串表示的是数据”。您可以将其放入引号中,但是数据是否包含引号呢?……其次,程序在将用户数据发送回浏览器时没有进行有效的转义。这导致包含有(例如说)引号的数据被放入页面中,从而引发了问题。而AJAX要提供的好处是,它包含一个专用渠道XML链接,其中全是数据而没有代码。这样,就有可能让客户端AJAX引擎负责对字符串进行转义、检测不正确的值,等等。说是这么说,直到AJAX更为成熟(可能也更为标准化)之前,它只会导致错误的编程和安全漏洞。 XSS漏洞可能造成的后果包括窃取用户会话,窃取敏感信息,重写Web页面,重定向用户到钓鱼网站等,尤为严重的是,XSS漏洞可能使得攻击者能够安装XSS代理,从而攻击者能够观察到该网站上所有用户的行为,并能操控用户访问其他的恶意网站。 对于XSS漏洞,我们有两种常见的措施,第一种就是消除漏洞,简而言之就是在输出页面上不提供任何用户的输入信息;另外一种就是想办法来抵御这种漏洞,可以采用对所有用户的输入编码后再输出(可以用OWASP的ESAPI),也可以对所有用户输入进行“白名单”验证,另外,OWASP还提供了AntiSamy对HTML页面做优化以消除这个漏洞。 / 39 防范XSS跨站脚本攻击——测试篇 XSS也是一种对浏览器的解释器的代码注入攻击,这些攻击能够通过HTML,JavaScript,VBScript,ActiveX,Flash等其他客户端语言执行,同时,这些攻击也可能造成用户信息泄露,配置更改,cookie窃取等造成危害,甚至能够用于对Web服务器进行DOS攻击。   与大部分攻击不同的是,大部分攻击往往只涉及2方(攻击者和网站,攻击者和受害者),而XSS则涉及3方,攻击者、客户端、网站,XSS的目的就是窃取客户端的cookie或是其他信息以冒充客户在网站上进行认证,进而在网站上操作任何想进行的操作。   下面我们看看到底有哪些类型的XSS攻击:   Stored XSS(存储式跨站脚本攻击)   这是最强大的一种XSS攻击,所谓存储跨站攻击是指用户提交给Web应用程序的数据首先就被永久的保存在服务器的数据库,文件系统或其他地方,后面且未做任何编码就能显示到Web页面,最典型的就是2005年在MySpace发现的XSS漏洞以及利用该漏洞的Samy MySpace Worm。   举例,假设我们的网站允许我们给其他用户留言,但事实上我们没有留言而是写入了一段代码:   那么服务器将会存储这些信息,当用户点击我们伪造的留言时,他的浏览器就会执行我们的脚本。 / 39 Reflected XSS(反射跨站脚本攻击)   这是最常见也是最知名的XSS攻击,当Web客户端提交数据后,服务器端立刻为这个客户生成结果页面,如果结果页面中包含未验证的客户端输入数据,那么就会允许客户端的脚本直接注入到动态页面中。传统的例子是站点搜索引擎,如果我们搜索一个包含特殊HTML字符的字符串时,通常在返回页面上仍然会有这个字符串来告知我们搜索的是什么,如果这些返回的字符串未被编码,那么,就会存在XSS漏洞了。   初看上去,由于用户只能在自己的页面上注入代码,所以似乎这个漏洞并不严重,但是,只需一点点社会工程的方法,攻击者就能诱使用户访问一个在结果页面中注入了代码的URL,这就给了攻击者整个页面的权限。由于这种攻击往往会需要一些社会工程方法,所以研发人员往往不会太过看重,但是我们看如下的例子,在服务器上有如下代码:   article.php?title=   这就使得浏览器每3秒就刷新一次页面,而且是一个死循环的状态,这就形成了DOS攻击,导致Web服务器挂掉。   DOM-Based XSS(基于DOM的XSS)   这个漏洞往往存在于客户端脚本,如果一个Javascript脚本访问需要参数的URL,且需要将该信息用于写入自己的页面,且信息未被编码,那么就有可能存在这个漏洞。   黑盒测试和示例:   比较简单的测试是否存在XSS漏洞的方法是验证Web应用是否会对一个包含了HTTP响应的简单脚本的访问请求,例如, / 39 Sambar服务器(5.3)包含一个众所周知的XSS漏洞,我们向服务器发送如下的请求,从服务器端能够产生一个响应从而在Web浏览器中执行   http://server/cgi-bin/testcgi.exe?   这个脚本会在客户浏览器端被执行。   我们再举个例子:   由于Javascript是区分大小写的,有些人会尝试将所有字符转换为大写字符来避免XSS漏洞,在这时,我们最好还是使用VBScript,因为它是大小写不区分的:   JavaScript.      VBScript.   alert(DOCUMENT.COOKIE)   如果我们已经过滤了”<”,或者是,那么我们就需要尝试各种编码方法了      %3cscript. src=http://www.example.com/malicious-code.js%3e%3c/script%3e   \x3cscript. src=http://www.example.com/malicious-code.js\x3e\x3c/script\x3e A3-错误的认证和会话管理 OWASP TOP10排名第3的威胁“遭破坏的认证和会话管理”,简而言之,就是攻击者窃听了我们访问HTTP时的用户名和密码,或者是我们的会话,从而得到sessionID,进而冒充用户进行Http访问的过程。 由于HTTP本身是无状态的,也就是说HTTP的每次访问请求都是带有个人凭证的,而SessionID就是为了跟踪状态的,而sessionID本身是很容易在网络上被监听的到,所以攻击者往往通过监听sessionID来达到进一步攻击的目的。 这些漏洞往往会存在于Web页面的“更改我的密码”、“记住我的密码”、“忘记密码”、“安全提问”、“注销登录”、“邮件地址”等环节上。 那么,一般来说,如何来防范这种漏洞呢? 第一,  我们要整体审视我们的架构 l        认证机制本身必须是简单、集中和标准化的; / 39 l        使用容器提供给我们的标准session id; l        确保在任何时候用SSL来保护我们的密码和session id 第二,  验证认证的实现机制 l        检查SSL的实现方法 l        验证所有与认证相关的函数 l        确保“注销登录”的动作能够关闭所有的会话 l        使用OWASP的WebScrab来测试你的应用 如何进行验证测试 所谓认证,就是建立确信某物或某人是真实的这么一个过程,authentication来自于希腊语αυθεντικός,即真实的,可信的。认证本身依赖于多个认证因子,在计算机安全领域,认证意味着验证通讯发起者的数字身份,常见的认证过程就是用户登录认证,所谓认证测试就是理解系统中的认证机制并找到方法绕过该认证机制。 认证测试需要考虑的点有很多,下面我们逐一来进行解释说明 l        在加密通道上传递密码 原则上,用户的认证必须通过加密信道进行传输,我们在这里的目的不是要验证诸如HTTPS是否安全,我们要验证的仅仅是用户的认证信息是否已经被加密了。 在用户登录时,最常见的方式是用户输入用户名和密码后,通过POST方法传输,一般来说,认证信息或者是通过不安全的HTTP传递,或者是通过加密的HTTPS传递。我们注意到,甚至有些网站在登录页面显示给我们的是HTTPS,但事实上却仍然是用HTTP的,最简单的方法就是用网络监听工具,如SnifferPro或Ethereal来判断是否是真实加密了。 下面,我们用OWASP的WebScrab截取一些信息来做个例子 假设,登录页面要求用户输入用户名和密码,然后有一个“提交”按钮,那么在WebScrab中我们得到如下的请求数据: POST http://www.example.com/AuthenticationServlet HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.14) Gecko/20080404 Accept: text/xml,application/xml,application/xhtml+xml Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 / 39 Keep-Alive: 300 Connection: keep-alive Referer: http://www.example.com/index.jsp Cookie: JSESSIONID=LVrRRQQXgwyWpW7QMnS49vtW1yBdqn98CGlkP4jTvVCGdyPkmn3S! Content-Type: application/x-www-form-urlencoded Content-length: 64 delegated_service=218&User=test&Pass=test&Submit=SUBMIT 在上面的数据中,我们可以看到,POST方法通过HTTP协议把数据发送到http://www.example.com/AuthenticationServlet,那么显然在这时,传送的数据没有进行加密,恶意用户通过监听网络就很容易得到用户名和密码。 再看下一个例子,假设是用HTTPS协议,那么请求的头数据如下: POST https://www.example.com:443/cgi-bin/login.cgi HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.14) Gecko/20080404 Accept: text/xml,application/xml,application/xhtml+xml,text/html Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: https://www.example.com/cgi-bin/login.cgi Cookie: language=English; Content-Type: application/x-www-form-urlencoded Content-length: 50 Command=Login&User=test&Pass=test 可见,上述例子中的数据经加密后被传送到https://www.example.com:443/cgi-bin/login.cgi,这就确保了数据是加密的而不被其他人所窃取。 再看下面的一个例子,我们在一个可以通过HTTP协议访问到的页面上通过HTTPS协议来发送数据 POST https://www.example.com:443/login.do HTTP/1.1 / 39 Host: www.example.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.14) Gecko/20080404 Accept: text/xml,application/xml,application/xhtml+xml,text/html Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://www.example.com/homepage.do Cookie: SERVTIMSESSIONID=s2JyLkvDJ9ZhX3yr5BJ3DFLkdphH0QNSJ3VQB6pLhjkW6F Content-Type: application/x-www-form-urlencoded Content-length: 45 User=test&Pass=test&portal=ExamplePortal 如上,我们看到,我们的请求通过HTTPS引向了https://www.example.com:443/login.do,但如果我们再看Referer的值,就发现我们是从HTTP页http://www.example.com/homepage.do过来的。在这种情况下,我们的浏览器窗口中并不会告诉我们现在使用的安全连接,而事实上我们却正在使用安全连接。 在上面的例子中,如果我们用Get方法,那么所输入的用户名和密码将会以明文的方式显示在URL中,这显然是不可取的。那么,如果我们经由Get方法通过HTTPS来传递数据是否可行呢,看下面的数据 GET https://www.example.com/success.html?user=test&pass=test HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.14) Gecko/20080404 Accept: text/xml,application/xml,application/xhtml+xml,text/html Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: https://www.example.com/form.html If-Modified-Since: Mon, 30 Jun 2008 07:55:11 GMT If-None-Match: "43a01-5b-4868915f" / 39 从上面的例子可以看到,用户名和密码都以明文的方式在URL里存在,而不像上面的几个例子中都在消息体中,但并不是说攻击者就可以很容易看到这些信息,TLS/SSL毕竟是安全性很高的协议,整个HTTP数据包是加密的,但仍然要注意的是这些用户名和密码在传输过程中会被存储在代理和服务器上,这也就有可能会泄露用户信息。 l        用户列举测试法 这种测试,简而言之是通过与应用的认证机制的交互,尝试能否获得一些正确的用户名,这对后面我们会讲到的暴力破解很有效,确认了正确的用户名就能用暴力破解去尝试密码了。 通常,WEB应用对于用户名正确的输入会有一些信息反馈,例如,如果我们输错了密码,那么有时会反馈告知我们系统存在该用户,或密码错误。所以,作为测试人员,就要尝试不同的请求来判断系统是否会有不同的返回。 对于HTTP的响应消息测试: n        输入正确的用户名和密码 期望结果:使用WebScrab抓取服务器的返回信息(HTTP 200 Response,消息的长度) n        输入正确的用户名/错误的密码 期望结果:从浏览器我们往往会得到如下的返回 或者是如下返回 甚至是如下的返回 Login for User foo: invalid password n        输入不存在的用户名 期望结果:返回可能如下 或者是如下的消息 Login failed for User foo: invalid Account 通常情况下,对于不同的出错信息,服务器往往返回的消息是一样的,但如果不同,测试人员就要去尝试在什么情况下不同,如下: 客户请求:正确用户/错误密码——>服务器返回:密码错误 客户请求:错误用户/错误密码——>服务器返回:用户不存在。 那么显然第一条就告诉我们我们输入的是正确的用户名,通过这种方式我们就可以获得一些正确的用户名信息。 还有其他一些尝试列举的方法: n        有些应用程序会返回一些特定的出错信息; n        分析URL以及重定向URL 如下面的URL: / 39 http://www.foo.com/err.jsp?User=baduser&Error=0 http://www.foo.com/err.jsp?User=gooduser&Error=2 上面两个URL都告诉我们到了错误页面,但上一条是Error值为0,下一条Error值为2,那么我们可以猜测我们获得了一个正确的用户名。 n        URI探测 有时候,Web服务器在接受一个对目录访问请求时,根据目录是否存在会有不同的返回信息,例如在某些网站会给每个用户设定一个目录,那么我们如果尝试访问某个已存在的目录时,它可能的返回页面如下: 403 Forbidden error code 404 Not found error code 举例: http://www.foo.com/account1-返回的出错信息: 403 Forbidden http://www.foo.com/account2-返回的出错信息: 404 file Not Found 那么显然,account1是现实存在的。 l        探测性用户账户测试法 众所周知,在系统中往往会有默认账户或者很容易被猜到的常用账户,而且往往很多用户会使用默认的密码,同样,有些应用系统的测试账户研发人员有时也会忘记删除。这个问题事实上是一个漏洞,而这种漏洞往往是由于以下原因造成的: n        没有经验的IT工程师,他们往往不会更改安装的架构组件的缺省密码; n        编程人员在应用中留有后门以便测试,但在发布时忘记删除; n        系统的管理员和用户采用了很简单的密码; n        系统有内嵌的,无法删除的内部用户名和密码 n        …… 对于注入Cisco路由器或WebLogic等,他们都有一些默认的用户名和密码,我们可以直接尝试,对于一些我们根本不了解的应用,我们可以做如下尝试: n        尝试以下系统管理员的常用账号——"admin", "administrator", "root", "system", "guest", "operator", "super","qa", "test", "test1", "testing",针对用户名和密码组合尝试,也可以尝试诸如"password", "pass123", "password123", "admin",或guest"这些密码。如果这些都无法成功,我们可以写一些脚本来尝试类似的用户名和密码组合。 n        管理员的密码有时会与系统名字相关,如我们测试的应用系统叫“Obscurity”,那么可以尝试用户名/密码组合Obscurity/obscurity。 n        利用注册页面我们也可以猜测用户名和密码的格式和长度。 / 39 n        尝试上述提到的所有用户名和空密码。 n        查看页面的源文件,尝试找到所有引用到用户名和密码的信息,比如"If username='admin' then starturl=/admin.asp else /index.asp" n        寻找那些源文件中注释中可能含有的用户名和密码信息; n        ……. l        强力测试(暴力测试) 任何一种技术,在不同的人手里运用所达到的效果是不同的,正如暴力测试,也叫暴力破解,安全服务人员和测试人员利用这种技术来验证是否存在漏洞,而攻击者则利用其来寻找漏洞。 Web应用系统通常会有一些用户认证方式,这些方式包括证书、指纹、一次性令牌等等,但更多的,往往是用户名和密码的组合,这就使得暴力破解成为可能。 在对Web应用系统做暴力测试时,首先我们需要了解的是系统的认证机制,通常Web系统会采用以下两种机制: n        HTTP认证——包含基本存取认证和数字存取认证。 n        基于HTML表单的认证。 我们下面对这些认证方式做一下简单介绍: 基本存取认证 基本存取认证假设假定用户会以用户名和密码的组合来表明自己的身份,当用户浏览器使用这种机制访问站点时,web服务器将会返回一个包含“WWW-Authenticate”头的401响应,且包含了一个“Basic”值,以及被保护的域名(例如,WWW-Authenticate: Basic realm=”wwwProtectedSite”)客户端会弹出一个需要用户输入该域用户名和密码的提示框。然后,客户端浏览器返回给服务器一个响应,响应包含“Authorization”头,还包含“Basic”值以及连接了用户名,冒号,密码的基于64位的编码(例如,Authorization: Basic b3dhc3A6cGFzc3dvcmQ=),但可惜的是,这个回复只要被攻击者监听到就很容易被解码。 我们来看一下这个过程: 1.客户端发送一个标准的HTTP请求 GET /members/docs/file.pdf HTTP/1.1 Host: target 2. web服务器定位到访问的这个资源是在一个受保护的目录; 3.服务器发送一个HTTP 401的认证请求; HTTP/1.1 401 Authorization Required / 39 Date: Sat, 04 Nov 2006 12:52:40 GMT WWW-Authenticate: Basic realm="User Realm" Content-Length: 401 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html; charset=iso-8859-1 4.浏览器弹出要求输入用户名和密码的数据窗口; 5.用户输入用户名和密码后,包含以下数据后再次提交; GET /members/docs/file.pdf HTTP/1.1 Host: target Authorization: Basic b3dhc3A6cGFzc3dvcmQ= 6.服务器把客户信息和存储的信息进行比较; 7.如果身份验证正确,服务器发回被请求的内容,如果失败,服务器将会返回HTTP www.owasp.org_Image-basm-sessid.jpg_Basm-sessid / 39 www.owasp.org_Image-basm-sessid2.jpg_Basm-sessid2 A4-不安全的直接对象引用 所谓“不安全的对象直接引用”,即Insecure direct object references,意指一个已经授权的用户,通过更改访问时的一个参数,从而访问到了原本其并没有得到授权的对象。Web应用往往在生成Web页面时会用它的真实名字,且并不会对所有的目标对象访问时来检查用户权限,所以这就造成了不安全的对象直接引用的漏洞。 我们看如下的一个示例,也许这样就更容易理解什么是不安全的对象直接引用。 / 39 1.      攻击者发现他自己的参数是6065,即?acct=6065; 2.      他可以直接更改参数为6066,即?acct=6066; 3.      这样他就可以直接看到6066用户的账户信息了。 一般来说,防止不安全的直接对象引用的方法有以下两种: 1.      使用非直接的对象引用——这防止了攻击者直接访问其并未授权的对象,通过一种mapping或是其他的方法让攻击者无法直接访问。 2.      检查访问——对每一个来自于不信任的源的直接对象引用都必须包含访问控制检查,从而确信该用户对该对象拥有访问权。 A5-伪造跨站请求(CSRF) 跨站请求伪造,也被称成为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与 / 39 XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。 CSRF攻击通过在授权用户访问的页面中包含链接或者脚本的方式工作。例如:一个网站用户Bob可能正在浏览聊天论坛,而同时另一个用户Alice也在此论坛中,并且后刚刚发布了一个具有Bob银行链接的图片消息。设想一下,Alice编写了一个在Bob的银行站点上进行取款的form提交的链接,并将此链接作为图片tag。如果Bob的银行在cookie中保存他的授权信息,并且此cookie没有过期,那么当Bob的浏览器尝试装载图片时将提交这个取款form和他的cookie,这样在没经Bob同意的情况下便授权了这次事务。 CSRF是一种依赖web浏览器的、被混淆过的代理人攻击(deputy attack)。在上面银行示例中的代理人是Bob的web浏览器,它被混淆后误将Bob的授权直接交给了Alice使用。 下面是CSRF的常见特性: l        依靠用户标识危害网站 l        利用网站对用户标识的信任 l        欺骗用户的浏览器发送HTTP请求给目标站点 风险在于那些通过基于受信任的输入form和对特定行为无需授权的已认证的用户来执行某些行为的web应用。已经通过被保存在用户浏览器中的cookie进行认证的用户将在完全无知的情况下发送HTTP请求到那个信任他的站点,进而进行用户不愿做的行为。 使用图片的CSRF攻击常常出现在网络论坛中,因为那里允许用户发布图片而不能使用JavaScript。 防范措施 对于web站点,将持久化的授权方法(例如cookie或者HTTP授权)切换为瞬时的授权方法(在每个form中提供隐藏field),这将帮助网站防止这些攻击。一种类似的方式是在form中包含秘密信息、用户指定的代号作为cookie之外的验证。 另一个可选的方法是“双提交”cookie。此方法只工作于Ajax请求,但它能够作为无需改变大量form的全局修正方法。如果某个授权的cookie在form. post之前正被JavaScript代码读取,那么限制跨域规则将被应用。如果服务器需要在Post请求体或者URL中包含授权cookie的请求,那么这个请求必须来自于受信任的域,因为其它域是不能从信任域读取cookie的。 与通常的信任想法相反,使用Post代替Get方法并不能提供卓有成效的保护。因为JavaScript能使用伪造的POST请求。尽管如此,那些导致对安全产生“副作用”的请求应 / 39 该总使用Post方式发送。Post方式不会在web服务器和代理服务器日志中留下数据尾巴,然而Get方式却会留下数据尾巴。 尽管CSRF是web应用的基本问题,而不是用户的问题,但用户能够在缺乏安全设计的网站上保护他们的帐户:通过在浏览其它站点前登出站点或者在浏览器会话结束后清理浏览器的cookie。 影响CSRF的因素 CSRF攻击依赖下面的假定: l        攻击者了解受害者所在的站点 l        攻击者的目标站点具有持久化授权cookie或者受害者具有当前会话cookie l        目标站点没有对用户在网站行为的第二授权 防范CSRF漏洞——测试篇 CSRF(Cross Site Request Forgey)跨站点伪造请求,是排在OWASP Top10第5位的漏洞,它迫使已被认证的用户在Web系统上执行其所不欲的操作。这种攻击依赖于以下: 1) Web浏览器对会话相关信息的处理方式(如cookie或Http认证信息)   2) 攻击者对正确的Web系统的URL的了解;   3) 应用会话管理仅依赖于浏览器所了解的信息;   4) 一些HTML的tag会导致对http(s)资源的直接访问其中,前3点是确认系统是否存在该漏洞的主要前提,第4点则是用来帮助攻击者利用该漏洞的。   第1点:浏览器自动发送用于识别用户会话的信息,假设site是一个Web应用站点,victim是一个已经在该系统上经过认证的用户。在server的响应中,site发送一个带有代表victim身份的cookie给victim,原则上,一旦浏览器接收到了服务器发送的cookie,就会在后面对站点的访问中都带上这个cookie;   第2点:如果应用在URL中没有使用会话相关的信息,那就意味着应用的URL,它们的参数,相应的值可以被识别。   第3点:是指诸如cookie、或者是基于http的认证信息,存放在浏览器中后,就会包含在后面的每次请求中。   下面,我们用Get方法在做个例子,如果用户已经通过了认证,那么在他做下一次请求时,请求数据中会自动加上cookie / 39   GET请求一般会有多种原因产生,   * 用户真正在访问Web系统;   * 用户在访问地址栏中切实敲入了URL;   * 用户点击了一个连接指向了这个URL;   这些调用对于系统来说是无法区别的,特别的,第三种方式相对来说是极为危险的,有很多种方法可以用来仿造连接的真实属性,连接可以被嵌入到一封邮件中,或者在某个恶意网站上,看上去这个连接好像是在访问另一个网站,而事实上却是被引到了Web系统的访问上。如果用户点击了连接,由于它已经被系统认证通过了,浏览器就会对系统提交一个待用认证信息的GET请求。这就在系统上完成了一个操作(尽管这个操作不是用户本身所期望做的)。 攻击者还可以通过Web的一些标记,注入img来达到这个目的。举个例子,假设攻击者发给用户一封邮件,引诱用户访问了一个URL,而这个URL的页面含有下面的HTML: ... ...   那么用户在点击这个URL时,浏览器将会做什么呢,它将会尝试显示一个宽度为0的图片,而事实上这是访问了www.company.example/action,显然如果浏览器并没有阻断下载img的图片,那么该动作就会执行了。   该问题的存在是基于以下一些事实:   * 有一些HTML的tags可能会执行一些脚本(如img) / 39   * 浏览器本身并不能识别img这个tag里的值是否是真实合法的图片   * 不管图片是否是在网站本地或是其他网站,图片都会被下载   举个例子:   假设用户要登录到某个防火墙web管理系统,登录时,用户必须对系统进行身份验证,所以用户的会话信息会保存在cookie中。假设我们的防火墙管理系统允许认证过的用户根据防火墙规则的排号来删除规则(甚至允许用户输入“*”来删除所有的规则),那么下一步显示的就是删除页面,假定表单下面就会提交一个GET请求,是以如下的格式:   https://[target]/fwmgt/delete?rule=1   或https://[target]/fwmgt/delete?rule=*   我们举的例子很简单,仅仅是为了说明CSRF的存在。   那么,如果用户输入了“*”,然后按取了Delete键,那么就提交了如下的GET请求,   https://www.company.example/fwmgt/delete?rule=*   同时就删除了所有的防火墙规则。 显然,如果用户直接在地址栏中输入https://[target]/fwmgt/delete?rule=*,或者通过某个链接转接到这个url,或者如上面所说,把链接隐藏在img这个tag后面,诸如此种方法, / 39 如果用户在点击这个连接的时候,已经登录进了防火墙管理系统,显然这个访问就能成功奏效,从而达到了删除所有规则的目的。   让我们想象一下,如果这样的攻击用于一些敏感系统,竞拍系统,或者是银行转账等等,所造成的后果将会多大。   应对方法:   对于用户来说,由于CSRF漏洞极为普遍,所以在我们的日常使用中要注意以下几点:   * 保证系统使用完就注销登录的习惯;   * 不要使用浏览器的保存用户名/密码的功能,不要使用网站的“记住我”功能   * 不要使用同一个浏览器浏览普通网页和你的关键性Web系统   对于开发人员来说,如上所述,由于将会话相关的信息放入了URL才造成了上述的问题,那么如果我们在URL层面增加会话特定的信息,那么对攻击者来说就增加了了解URL结构的难度。另外,我们还可以尽可能的使用POST,而不是GET;尽可能多的增加一些诸如“你确定要这样做吗?”的页面等……   说到这,想必大家都已明白CSRF是什么了,下面我们来看下针对这个漏洞,作为测试人员该如何去测试。   一般的测试用例应该如下构建:   1. 假设u是需要被测试的URL,例如u =http://www.example.com/action;   2. 构建一个包含了访问上述URL信息的html页面;   3. 确保合法用户已经登录了系统;   4. 诱使该用户在自己不知情的情况下访问上述URL;   5. 确认是否执行了该操作。 A6-安全误配置(Security Misconfiguration) 排在第六位的是不当的安全配置,事实上,这个问题可能存在于Web应用的各个层次,譬如平台、Web服务器、应用服务器,系统框架,甚至是代码中。开发人员需要和网络管理人员共同确保所有层次都合理配置,有很多自动化的工具可以用于查找是否缺少补丁,错误的安全配置,缺省用户是否存在,不必要的服务等等。 这个漏洞往往使得攻击者能够访问未被授权的系统数据和功能,甚至有时,会导致整个系统被破坏。 其实说这个漏洞该怎么防范并没有什么实际的措施,唯一的方法就是尽可能的对你的系统的所有方面都做好安全配置。 / 39 l         验证你的系统的安全配置 n         可使用自动化的安全配置向导; n         必须覆盖整个平台和系统; n         对所有组件都必须保证安装了最新的补丁; n         完善分析变更带来的安全影响 l         对所有你做的安全配置进行记录 l         使用自动化扫描工具对你的系统进行验证。 A7-限制远程访问失败 排在第7位的是“Failure to Restrict URL Access”,这个漏洞事实上也是与认证相关的,与我们前面提到的Top4不安全的直接对象引用也是类似的,不同在于这个漏洞是说系统已经对URL的访问做了限制,但这种限制却实际并没有生效。常见的错误是,我们在用户认证后只显示给用户认证过的页面和菜单选项,而实际上这些仅仅是表示层的访问控制而不能真正生效,攻击者能够很容易的就伪造请求直接访问未被授权的页面。 我们举个例子来说明这个过程: 1.      攻击者发现他自己的访问地址为/user/getAccounts; / 39 2.      他修改他的目录为/admin/getAccounts或/manager/getAccounts; 3.      这样攻击者就能够查看到更多的账户信息了。 那么,该如何防范出现这个漏洞呢? l        对每个URL,我们必须做三件事 n        如果这个URL不是公开的,那么必须限制能够访问他的授权用户; n        加强基于用户或角色的访问控制; n        完全禁止访问未被授权的页面类型(如配置文件、日志文件、源文件等) l        验证你的构架 n        在每一个层次都使用简单肯定的模型; n        确保每一层都有一个访问机制 l        验证你的实现 n        不要使用自动化的分析工具 n        确保每个URL都被外部过滤器或其他机制保护 n        确保服务器的配置不允许对非授权页面的访问 A8-未验证的重定向和传递 在Web应用中重定向是极为普遍的,并且通常重定向所引向的目的是带有用户输入参数的目的URL,而如果这些重定向未被验证,那么攻击者就可以引导用户访问他们所要用户访问的站点。 同样,转发也是极为普遍的,本质上转发是在同一个应用中对一个新页面发送请求,并且有时是用参数来定义目标页面的。同样,如果参数未被验证,那么攻击者就可以利用其来绕过认证或是授权检查。 而最终造成的后果,重定向会使得用户访问钓鱼网站或是恶意网站,而转发则会让攻击者利用先前安全检查过的请求来绕过认证或是授权。 对于这个漏洞,常用的防范方式包括: l         尽可能的避免使用重定向和转发机制; l         如果使用了,那么在定义目标url的时候不要包含用户参数; l         如果一定要包含用户的参数,那么, n         对每个参数都必须进行验证以确保它的正确性和合法性;或是 n         在服务器端提供映射机制,将用户的选择参数转变为真正的目标页面; / 39 A9-不安全的加密存储 我们常说数据的安全性是极为重要的,而在程序人员的编程过程中,由于有些需求或是设计的问题,往往会造成特别是机密数据的安全性得不到保证,常见的不安全的数据存储包括: l        未能识别全部的机密数据; l        对某个机密数据未能识别其所有的存放地;(数据库、文件、目录、日志文件……) l        未对数据的每个存放地进行合理的保护 那么显然,这样造成的后果是极为严重的: l        攻击者能够取得或是篡改机密的或是私有的信息; l        攻击者通过这些秘密的窃取从而进行进一步的攻击; l        造成企业形象破损,用户满意度下降,甚至会有法律诉讼等; 一般来说,我们采用以下的方法来避免这个漏洞的存在: l        验证你的结构 n        识别所有的敏感数据; n        识别这些数据存放的所有位置; n        确保所应用的威胁模型能够应付这些攻击; n        使用加密手段来应对威胁 l        使用一定的机制来进行保护 n        文件加密;数据库加密;数据元素加密 l        正确的使用这些机制 n        使用标准的强算法; n        合理的生成,分发和保护密钥; n        准备密钥的变更 l        验证实现方法 n        确保使用了标准的强算法; n        确保所有的证书、密钥和密码都得到了安全的存放; n        有一个安全的密钥分发和应急处理的方案; / 39 A10-不足的传输层保护 最后一个漏洞事实上也是与上一个漏洞有所相似,都是一种缺少了对敏感数据保护的漏洞。不同在于这种漏洞更多关注的是数据在网络上的传输,造成这个漏洞的原因往往如下: l         未能识别所有的敏感数据; l         未能识别敏感数据发送的所有位置; l         未能在每个位置对敏感数据提供合理的保护 这个漏洞造成的后果和排在第9位的类似,这里不做赘述。 但是防范方法却和第9位的方法有一定的区别,主要的方法包括: l         提供合理的保护机制 n         对于敏感数据的传输,对所有连接都要使用TLS; n         在传输前对单个数据都要进行加密;(如XML-Encryption) n         在传说前对信息进行签名;(如XML-Signature) l         正确的使用这些机制 n         使用标准的强算法 n         合理管理密钥和证书; n         在使用前验证SSL证书 / 39

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档