【导读】Java安全编码标准—第2章 输入验证和数据净化

章节概述

输入验证是防止各种注入攻击,SQL 注入,XML 注入,LDAP 注入,以及 XSS 跨站攻击的有效手段。

LDAP(Lightweight Directory Access Protocol):轻量级目录访问协议,是一种在线目录访问协议,主要用于目录中资源的搜索和查询,是X.500的一种简便的实现。随着互联网的广泛使用,web应用的数量呈爆炸式的增长,而这些应用的资源和数据呈分布式存储于目录中。通常不同的应用会有专属于自己相关数据的目录,即专有目录,专有目录数量的增长导致了信息孤岛(一种不能与其他相关信息系统之间进行互操作或者说协调工作的信息系统)的出现,系统和资源的共享及管理变得日益困难。

以查找联系人和加密证书为例,太多的目录明显会给计算机搜索带来巨大的压力,当然随之出现了相应的解决方案,如X.500,X.500申明了目录客户端和目录服务器使用的目录访问协议(DAP),然而作为应用层协议,DAP要求完整的7层OSI协议栈操作,会要求比小环境(配置、资源有限的环境)所能提供的更多的资源,因此需要一种轻量级的协议来代替X.500,LDAP正是因此而生。

LDAP注入攻击和SQL注入攻击相似,因此接下来的想法是利用用户引入的参数生成LDAP查询。一个安全的Web应用在构造和将查询发送给服务器前应该净化用户传入的参数。在有漏洞的环境中,这些参数没有得到合适的过滤,因而攻击者可以注入任意恶意代码。

XSS:跨站脚本(cross site script)为了避免与样式css混淆,所以简称为XSS

XSS是一种经常出现在web应用中的计算机安全漏洞,也是web中最主流的攻击方式。那么什么是XSS呢?

XSS是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码。

从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。

XSS攻击的危害包括:

1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号

2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力

3、盗窃企业重要的具有商业价值的资料

4、非法转账

5、强制发送电子邮件

6、网站挂马

7、控制受害者机器向其它网站发起攻击

主要原因:过于信任客户端提交的数据!

解决办法:不信任任何客户端提交的数据,只要是客户端提交的数据就应该先进行相应的过滤处理然后方可进行下一步的操作。

简单例子

正常发送消息:

http://www.test.com/message.php?send=Hello,World!

接收者将会接收信息并显示Hello,Word

非正常发送消息:

http://www.test.com/message.php?send=

接收者接收消息显示的时候将会弹出警告窗口

工具审计 Fortify 和 Findbugs 均可。

Fortify 和 Findbugs 均为静态代码扫描与分析工具。

尽可能先使用自动化分析工具,当一个规则不能由工具审计的时候,或者怀疑工具漏报误报的时候,必须采用人工审计的方式。

整改原则

当存在公用 Java 代码库和解析器的数据净化和验证方法时,应该优先考虑使用它们。

1560252685788.png

表 2. Java 输入验证和数据净化编程标准审计方法

标准 审计复杂度 严重性 整改代价 审计方法
IDS00-J 工具为主,人工为辅
IDS01-J 工具
IDS02-J N/A
IDS03-J 人工
IDS04-J 人工
IDS05-J 人工
IDS06-J 人工
IDS07-J 人工
IDS08,09,11 N/A
IDS012-J 人工
IDSother 中低 N/A

2.1 审计重点 IDS00-J 净化穿越受信边界的非受信数据

程序接受未经过验证的用户数据。问题严重,包括 SQL 注入攻击和 XML 注入攻击。发生可能性大,修复代价中等。

审计方法:

工具检测 SQL 注入

Fortify 可以检测 SQL injection(由 Juliet Test Case SWE89 验证支持)

人工审计 XML 注入有难度

Fortify 和 findbugs 都无法检测 XML injection。

整改方法:

SQL 命令行解析器和 XML 解析器都提供了自己的数据净化和验证的方法。当存在这样的方法的时候,应当优先考虑它们,因为自定义的方法会忽略一些特殊情况,会忽略解析器自身所隐含的复杂性。

  1. SQL 注入相关攻击

    用 PreparedStatement 代替 Statement, 通过使用 PreparedStatement 类的 set*() 方法,可以进行强制类型检查,会自动转义双引号内的输入数据,减少 SQL 注入漏洞。

    设计精巧的注入文本还是有可能规避 PreparedStatement,更进一步的整改方法,可以是根据数据库,代替使用$符号的地方。比如对于 DB2,可以使用'%'||'#param#'||'%'或者 CONCAT('%', #param#, '%') 避免。

    演示SQL注入例子,示例输入:

    userName:yuhuan' or '1=1 password:1(any word)

    防止SQL注入总体思路:

    1、检查变量数据类型和格式

    2、过滤特殊符号

    3、绑定变量,使用预编译语句

  2. XML 注入相关攻击

    1. 一个方法是,写程序时候使用白模板,Pattern.matches, 使用何种 pattern 和业务逻辑相关,比如年龄字段只能是数字且不能大于 150
    2. 另外一个通用方法是,写程序时候使用 Java 类库类 SchemaFactory 以及 setEntityResolver 方法,通过定义 schema 来规范并验证 xml 输入。比如姓名字段只能 (0,1] 代表无名或者一个名字, 而不允许多个名字。语法可参考:http://www.w3school.com.cn/schema/schema_intro.asp

    book.xml:

    
    
    
        
            冰与火之歌
            乔治马丁
            2014
            
                89.00
                
            
        
        
            安徒生童话
            安徒生
            2004
            77.50
        
        
            think think think
            aaa
            1997
            100.00
        
    
    

    book.xsd:

    
    
     
         
             
                 
                     
                         
                             
                             
                             
                                 
                                     
                                         
                                         
                                     
                                 
                             
                             
                                 
                                     
                                         
                                     
                                 
                             
                         
    
                         
    
                     
                 
             
         
     
    
    
  3. XML外部实体攻击(XXE攻击)

    XXE原理

    既然XML可以从外部读取DTD文件,那我们就自然地想到了如果将路径换成另一个文件的路径,那么服务器在解析这个XML的时候就会把那个文件的内容赋值给SYSTEM前面的根元素中,只要我们在XML中让前面的根元素的内容显示出来,不就可以读取那个文件的内容了。这就造成了一个任意文件读取的漏洞。

    那如果我们指向的是一个内网主机的端口呢?是否会给出错误信息,我们是不是可以从错误信息上来判断内网主机这个端口是否开放,这就造成了一个内部端口被探测的问题。另外,一般来说,服务器解析XML有两种方式,一种是一次性将整个XML加载进内存中,进行解析;另一种是一部分一部分的、“流式”地加载、解析。如果我们递归地调用XML定义,一次性调用巨量的定义,那么服务器的内存就会被消耗完,造成了拒绝服务攻击。

2.2 审计重点 IDS01-J 先标准化,然后再检验字符串

问题严重,可以包庇 XSS 跨站攻击,使得代码无法识别跨站攻击使用的

你可能感兴趣的:(【导读】Java安全编码标准—第2章 输入验证和数据净化)