SQL关键字的黑名单过滤数据

时间:2012-12-06 06:31:04

标签: java validation security sql-injection

我试图在将数据插入数据库之前验证数据(POSTGRESQL)。使用Apache Commons Validator可以轻松验证与电子邮件,邮政编码等对应的数据。但是在名字的情况下我使用了这个:

^[a-zA-Z][ a-zA-Z]{1-30}$

这可以防止将任何特殊字符添加为名称,但无法阻止用户将DROP or GRANT添加为名称。当我使用PreparedStatement时,我认为这不会是一个问题,但现在要求SQL关键字不应该进入数据库,因为它可能会导致二阶SQL注入

我想过将所有SQL关键字列入黑名单(当然,这会阻止巨额资助登录我们的网站。:P)但似乎有> 64个关键字。这是(SQL关键字的黑名单过滤数据) 阻止二阶SQL注入的正确方法?我有什么选择?

我正在使用此代码:

String sql="INSERT INTO users (username, password, name) VALUES (?,?,?);";
        try{
            conn=SomeStaticClass.createConnection();
            ps=conn.prepareStatement(sql);
            ps.setString(1, dataBean.getUsername());
            ps.setString(2, dataBean.getPassword());
            ps.setString(3, dataBean.getName());
            ps.execute();
        }catch(SQLException e){
            e.printStackTrace()
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try{
                if(ps!=null){
                    ps.close();
                }
                conn.close();
            }catch(SQLException e){
                e.printStackTrace();
            }
        }

4 个答案:

答案 0 :(得分:2)

  

对于这种情况,这是一种正确的方法吗?

没有

通过连接字符串来组装SQL查询时会发生SQL注入。

防止SQL注入的“最佳实践”方法是使用具有常量SQL查询的PreparedStatement,这些查询具有参数的占位符。然后使用准备好的语句set方法为每个占位符参数设置值。这种方法将保证包含SQL关键字的任何“讨厌的”字符串参数将被解释为文字字符串。


更新 - 始终如一地使用PreparedStatements可以防止二阶攻击...假设您指的是这样的内容:

http://download.oracle.com/oll/tutorials/SQLInjection/html/lesson1/les01_tm_attacks2.htm

您只需要确保不要从可能被污染的任何内容构建SQL查询字符串。如果您使用占位符处理任何可能受污染的数据,则无论它来自何处都无关紧要。

(黑名单SQL关键字将有助于防止垃圾进入您的数据库。但正如您所提到的,它可能会对合法数据造成损害并影响您的系统的可用性。我不会这样做。最好是依靠良好的程序员纪律......以及彻底的代码审查。)

答案 1 :(得分:1)

如果您将关键字存储在数据库中,然后以不安全的方式使用它们,则只会发生二阶注入。如果您使用预准备语句并且它们已正确参数化,则不会发生。思科对理解SQL注入有很好的总结:

http://www.cisco.com/web/about/security/intelligence/sql_injection.html

除了你的“格兰特”的例子之外,还有许多例如IF,BY,IS,IN,TO,它们将以英语/名字出现。

答案 2 :(得分:1)

如果不是不可能的话,确保数据库中的所有数据都可以与任何脚本语言(如SQL或HTML)一起使用,而且未来没有适当的转义,这是非常困难的。现在,在您现在如何使用角色之前,无法区分“安全”和“不安全”字符。

在将所有数据插入数据库之前尝试转义并清除所有数据可能会让您相信数据库中用户生成的数据是“安全的”,这是一个非常危险的信念。只有在知道如何使用数据时才能知道数据是否安全,并且只有在实际使用数据时才会知道(因为数据库中的数据可以存活很长时间)。

避免此类问题的最佳策略是在实际使用时始终转义所有数据,或者像使用PreparedStatement一样,在html中使用它们时正确转义它们,当它们插入到html中时转义它们电子邮件等。

我在这个答案中给出了一些例子:

How to allow specific characters with OWASP HTML Sanitizer?

答案 3 :(得分:0)

除了使用PreparedStatement之外,您还必须检查用户在您的网页上提供的输入。

所以现在你有两张不同的支票。 1.在您的网页上,这将减少处理时间。 2.如果某些内容通过了您的初始检查,那么preparedstatement将确保您的查询得到正确解析。

E.g用户正在搜索某个项目..

用户输入

' OR ITEM in (Select ITEM from SOME_TABLE) OR ITEM = ''

您正在构建SQL,通过连接字符串,然后它将使SQL命令为

Select * from TABLE_X WHERE ITEM = '' OR ITEM in (Select ITEM from SOME_TABLE) OR ITEM = ''

所以你的DATABASE被黑了,但在其他情况下,PreparedStatement会解析你的查询,不会让make用户修改SQL ......