首页  ·  知识 ·  云计算
net系统安全开发手册
等待的家园  http://www.cnblogs.com/jk1001/  综合  编辑:dezai  图片来源:网络
一、 输入验证

一、 输入验证
1. 什么是输入
    输入是编译时以外的全部数据交换。WEB应用程序从各种来源获取输入,例如所有用户发送的,或者应用程序运行的往返数据(用户提交的数据、视图状态、cookie、查询字符串参数等),以及后台数据(数据库、配置数据和其他数据来源)。所有输入的数据都会在某种情况下影响请求的处理。[1]


2. 输入验证的必要性
为什么输入验证如此重要?第一个原因非常明显:用户都不希望使用虚假的数据。应用程序会处理这些数据,根据它们得出结果,并最终存储到后台数据存储中。网络上的其他应用程序有可能在某种情况下需要这些数据,这些程序可能依赖于数据的正确性。(如果这些数据没有经过验证,就有可能会带来麻烦。)[1]
一切从外部获取的数据都可能是恶意的,如果缺少对数据的验证,将会带来很多安全问题。如EMAIL 验证、用户名验证等。如:缺少对EMAIL的长度验证,在存储EMAIL时将出现数据库溢出错误。缺少对EMAIL的格式验证,在发送邮件时将会给程序带来错误等。


3. 输入验证技术
3.1 主要防御方式
防御手段一:验证控件验证
保护级别:★★★★☆
描述:
      对于表现层, 可以利用验证控件,对用户输入的数据进行类型、大小、范围的验证。
验证控件必须做到在客户端和服务端同时验证,客户端的验证可以减轻对服务端请求的次数和用户操作的方便性。服务端验证确保数据的正确性,同时也防止用户伪造请求绕过客户端的验证。
优点: 验证简单有效,可重复使用,通常应用于客户端验证较多。
缺点: 验证不完整,有些验证用户可以绕过。
应用举例:
     动易SiteFactory系统中,除了使用VS自带的验证控件外,还扩展了和增加了部份验证控件,在PowerEasy.Framework.Controls 命名空间下,可以看到扩展的RequiredFieldValidator 控件,邮箱验证控件EmailValidator等。具体可以查看文件夹 Core Items 中PowerEasy.Framework.Controls项目下的ExtendedValidator文件夹。这些控件一般使用在用户输入的验证,如注册时用户名的验证:
                            SetFocusonError="false" ErrorMessage="用户名不能为空" Display="None">

 

防御手段二:业务逻辑层验证
保护级别:★★★★☆
描述:
      关键的地方(涉及到点数、金钱、权限)根据情况还需要在业务层或者数据访问层进行验证,以保证数据的合法性。对于HTML代码输入的地方,输入时一定要进行HTML格式化处理,否则有可能会引起全局显示错误。如输入:
   
     
 

基于窗体(Forms)的身份验证配置站点,当没有登陆的用户访问需要身份验证的网页,网页自动跳转到登陆网页。其中元素loginUrl表示登陆网页的名称,name表示Cookie名称

 

2.authorization 节点





allow      向授权规则映射添加一个规则,该规则允许对资源进行访问。
deny      向授权规则映射添加一条拒绝对资源的访问的授权规则。
users="*"  是指任何用户      users="?"  是指经身份验证的用户
注意: 运行时,授权模块从最本地的配置文件开始,循环访问 allow 和 deny 元素,直到它找到适合特定用户帐户的第一个访问规则。然后,该授权模块根据找到的第一个访问规则是 allow 还是 deny 规则来允许或拒绝对 URL 资源的访问。默认的授权规则为 。因此,默认情况下允许访问,除非另外配置。
如果在根目录下的web.config配置太繁琐,可以配置到相应目录下,例如User目录下的web.config文件

 

3.customErrors 节点





defaultRedirect  可选的属性。指定出错时将浏览器定向到的默认 URL。如果未指定该属性,则显示一般性错误。
Mode  必选的属性。指定是启用或禁用自定义错误,还是仅向远程客户端显示自定义错误。
此属性可以为下列值之一。
值  说明 
On  指定启用自定义错误。如果未指定 defaultRedirect,用户将看到一般性错误。
Off  指定禁用自定义错误。这允许显示标准的详细错误。
RemoteOnly  指定仅向远程客户端显示自定义错误并且向本地主机显示 ASP.NET 错误。这是默认值。
默认值为 RemoteOnly。
error 可选的元素。指定给定 HTTP 状态代码的自定义错误页。错误标记可以出现多次。子标记的每一次出现均定义一个自定义错误条件。
例如:





这里可以让用户自定义出错页。

 

4.pages 节点


validateRequest="true"
该值确定 ASP.NET 是否针对危险值检查来自浏览器的输入。如果 ASP.NET 针对危险值检查来自浏览器的输入,则为 true;否则为 false。默认值为 true。
这个功能是为了防止跨站脚本等危险代码。使全局默认为true。只有小数页面,如搜索页面
Search.aspx   设为 :  ValidateRequest="false" 。为了可以搜索类似

等内容,如果只是文字性的输入,可修改页 search.aspx 的设置,以增强系统安全性。

 

 

 

十三、 综合实例讲解
      本综合实例,资料是从网上搜集和个人发现,只讲漏洞的存在性和修改方法,与开发语言无关。

实例1: 创力CMS注册验证漏洞
漏洞文件:user/Reg.asp  注册页面。
Sub Reg_Post()    ‘46行 开始
  if NameLen > MaxLen or NameLen < MiniLen then    '84行
  ErrMsg=ObjErr.selectSingleNode("NameLen").text
  ErrMsg=Replace(ErrMsg,"{$MaxLen}",MaxLen)
  ErrMsg=Replace(ErrMsg,"{$MiniLen}",MiniLen)
  Call Cl.OutErr(0,ErrMsg)
 else
  if Instr(UserName,chr(32))>0 or Instr(UserName,",")>0 or Instr(UserName,chr(34))>0 or Instr(UserName,chr(9))>0 or Instr(UserName,"")>0 then
   Call Cl.OutErr(0,ObjErr.selectSingleNode("NameChar").text)
  end if
  end If
只对用户名进行长度检查,和检查 chr(32) 空格 , chr(34) " chr(9)  tab
但没对chr(39)  ‘ 进行过滤,而程序很多地方调用到用户名,造成多处SQL注入漏洞。

解决方法:加强输入验证,过滤重要字符。

 

实例 2: DedeCms跨站漏洞


可以从上面看出,程序没有对用户输入的“’“进行编码处理输出,因此造成页面编码乱,造成html注入漏洞。

解决方法:根据环境要求,进行编码输出。

 

实例 3: Discuz!NT 2.5 SQL注入漏洞
漏洞文件:
showuser.aspx
漏洞主要函数:
GetUserList(int pagesize, int pageindex, string orderby, string ordertype)

漏洞分析:
public DataTable GetUserList(int pagesize, int pageindex, string orderby, string ordertype)
{
    string[] array = new string[] { "username", "credits", "posts", "admin", "lastactivity", "joindate", "oltime" };
    switch (Array.IndexOf(array, orderby))
    {
        case 0:
            orderby = string.Format("ORDER BY [{0}users].[username] {1},[{0}users].[uid] {1}", BaseConfigs.GetTablePrefix, ordertype);
            break;

        case 1:
            orderby = string.Format("ORDER BY [{0}users].[credits] {1},[{0}users].[uid] {1}", BaseConfigs.GetTablePrefix, ordertype);
            break;
    ……
    }
    DbParameter[] commandParameters = new DbParameter[] { DbHelper.MakeInParam("@pagesize", DbType.Double, 4, pagesize), DbHelper.MakeInParam("@pageindex", DbType.Double, 4, pageindex), DbHelper.MakeInParam("@orderby", DbType.AnsiStringFixedLength, 0x3e8, orderby) };
    return DbHelper.ExecuteDataset(4, BaseConfigs.GetTablePrefix + "getuserlist", commandParameters).Tables[0];
}

从上面可以看出,ordertype没有过滤就直接进入了SQL查询,
ordertype 就是SQL注入的地方,从那里我们可以加入任何SQL语句。如:
省略..........
出现:
“/”应用程序中的服务器错误。
________________________________________
第 12 行: ',[dnt_users].[uid] asc' 附近有语法错误。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。

异常详细信息: System.Data.SqlClient.SqlException: 第 12 行: ',[dnt_users].[uid] asc' 附近有语法错误。

解决方法:对ordertype进行过滤,或用白名单形式处理。


实例 4: 存储过程注入举例
存储过程也可能存在SQL注入,由于存储过程中存在用于字符串连接的 + 号连接SQL语句,这就造成SQL注入的可能性.
CREATE PROCEDURE [dbo].[PR_UserManage_Users_BatchMove]
(
@UserType int = 1,
@GroupId NVarChar(500) ='',
@UserId NVarChar(4000) = '',
@UserName NVarChar(255) = '',
@StartUserId int = 0,
@EndUserId int = 0,
@BatchUserGroupId NVarChar(500) =''
)
AS
BEGIN
SET NOCOUNT OFF
If (@UserType = 1)
        BEGIN
    EXEC('Update PE_Users set GroupID= ' + @GroupId +' Where UserID in (' + @UserId + ')')
        END
    Else If(@UserType = 2)
        BEGIN
    EXEC('Update PE_Users set GroupID= ' + @GroupId +' Where UserName in (''' + @UserName + ''')')
        END
Else If(@UserType = 3)
        BEGIN
    EXEC('Update PE_Users set GroupID= ' + @GroupId +' Where UserId between ' + @StartUserId + ' and ' + @EndUserId)
        END
    Else If(@UserType = 4)
        BEGIN
    EXEC('Update PE_Users set GroupID= ' + @GroupId +' Where GroupID in (' + @BatchUserGroupId + ')')
        END
END

可以看出,在用户名的地方,没有过滤直接放入查询,造成in 类型的SQL注入漏洞。

解决方法:调用时要对参数进行过滤

 

实例 5: YXBBS任意文件下载漏洞
漏洞文件: ViewFile.asp
    Function ChkFile(FileName)
    Dim Temp,FileType,F
    ChkFile=false
    FileType=Lcase(Split(FileName,".")(ubound(Split(FileName,"."))))
    Temp="|asp|aspx|cgi|php|cdx|cer|asa|"
    If Instr(Temp,"|"&FileType&"|")>0 Then ChkFile=True
   F=Replace(Request("FileName"),".","")
    If instr(1,F,chr(39))>0 or instr(1,F,chr(34))>0 or instr(1,F,chr(59))>0 then ChkFile=True
End Function
可以从上面代码中看出,代码是使用黑名单形式,如果名称中等于列表中的就不能下载,但如果用户输入conn.asp%20(%20是指空格)这样就能绕黑名单验证,下载了conn.asp名件。

解决方法:使用白名单验证。

 

实例 6: 风讯任意文件浏览漏洞
漏洞文件:http://nt.demo.foosun.net/configuration/system/selectPath.aspx
如图:
 
                                 

                                      图1

查看源码:
string Path = this.str_FilePath + base.Request.Form["Path"];
构造提交表单:
http://nt.demo.foosun.net/configuration/system/selectPath.aspx" method=POST >



    

     

                    图 2

 

可以看出,系统没有对“..”进行进滤,于是就造成了这个漏洞。

解决方法:过滤 “..” 。


实例 7: KesionCMS浏览任意目录,删除任意目录和文件漏洞
漏洞文件:
Kesion.WebFilesCls.asp

漏洞描述:

<%
    webDir=KS.Setting(3)
    TopDir=Replace(WebDir&Topdir,"//","/")
    action=LCase(Trim(KS.G("action")))
    CurrentDir=Trim(Replace(KS.G("CurrentDir"),"../",""))
    CurrentPage=KS.ChkClng(KS.G("page"))
   
    if CurrentDir<>"" then
     CurrentDir=Replace(CurrentDir & "/","//","/")
    end if
    Set Fso=Server.CreateObject(Trim(KS.Setting(99)))
    Select Case action
可以看出,上面只过滤“../ ”
但可以这样绕过 “…/./” 过滤后就成了“../”。
 

解决方法:过滤 “..”


实例 8: 博客园CuteEditor文件管理漏洞
CuteEditor编辑品中的插入图片的都有对以上传的文件进行操作,但也没有限制性对“..”的使用,这样就可以让用户复制或移动任意文件到系统任意目录。
 

造成的危害有:
用户上传任意图片,复盖博客园中任何图片(有写权限目录)。
用户上传任意js,复盖博客园中任何js等。

解决方法:过滤“..”

本文作者:等待的家园 来源:http://www.cnblogs.com/jk1001/
CIO之家 www.ciozj.com 微信公众号:imciow
   
免责声明:本站转载此文章旨在分享信息,不代表对其内容的完全认同。文章来源已尽可能注明,若涉及版权问题,请及时与我们联系,我们将积极配合处理。同时,我们无法对文章内容的真实性、准确性及完整性进行完全保证,对于因文章内容而产生的任何后果,本账号不承担法律责任。转载仅出于传播目的,读者应自行对内容进行核实与判断。请谨慎参考文章信息,一切责任由读者自行承担。
延伸阅读