在sql语句或可调用语句中传递密码的安全问题

时间:2014-12-11 06:14:49

标签: oracle security jdbc

我打算在我的数据库中保留密码哈希而不是纯文本。当我在准备好的语句中从JDBC执行查询时,我的担忧是什么:

SELECT username FROM users WHERE username = 'userName' 
and password = dbms_crypto.hash(utl_raw.cast_to_raw('password'),3);

INSERT INTO users VALUES ('username',  dbms_crypto.hash(utl_raw.cast_to_raw('passowrd'),3);

或者如果我调用PLSQL程序,希望我传递明文密码,然后这些程序将在他们的身体中有上述查询。我关心的是,有人可以通过JDBC通过这些查询来点击从我的服务器发送到我的数据库的密码。使用预准备语句或plsql程序来克服这种安全问题是否更好?或者我应该首先使用我的java代码哈希我的密码,然后传递这些密码以便插入或选择?

3 个答案:

答案 0 :(得分:2)

克服您引用的安全问题的唯一方法是在通过网络发送密码之前预先对服务器端密码进行哈希处理。

这是最好的做法。

dbms_crypto.hash 对密码存储安全,您不应该使用它。相反,你应该使用适当的盐和成本的BCrypt。在服务器代码中生成bcrypt哈希,然后将其发送到已经哈希的数据库(用于插入)或使用用户名(用于选择)从数据库中提取哈希值。

此外,我想指出,如果攻击者能够与您的数据库足够接近以查看您在其上运行的查询,则会出现严重问题。虽然我是深度防守的粉丝,所以你应该防范这种可能性,如果这实际上发生了大量问题。

答案 1 :(得分:1)

我建议在使用java加密发送sql之前加密密码或保护SQLNet。 有关保护SQLNet的更多信息,请参阅orafaq.com,他们有一个简短的描述:http://www.orafaq.com/wiki/Network_Encryption

BTW:这些SQL语句没有“准备好”。

答案 2 :(得分:0)

ircmaxell的答案是最佳解决方案。

如果由于某种原因您无法预先散列该值,并且必须将明文密码传递给数据库,您至少应该确保数据库不会缓存包含明文的语句密码。可以使用以下代码从共享池中清除特定语句,即GV$SQL

--Remove a SQL statement from the shared pool.
begin
    for cached_sql in
    (
        select *
        from gv$sql
        where lower(sql_fulltext) like
            'insert into users values%dbms_crypto.hash(utl_raw.cast_to_raw%'
    ) loop
        sys.dbms_shared_pool.purge(cached_sql.address||','
                ||cached_sql.hash_value, 'C', 1);
    end loop;
end;
/