龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > JAVA开发 >

Java服务器端编程安全必读(5)

时间:2009-12-23 15:42来源:未知 作者:admin 点击:
分享到:
执行过程 下 如果用户输入的查询条件中,用户名字等于“fred”,密码等于“something”,则系统执行的查询实际上是: SELECT id FROM users WHERE username=fred AN

  执行过程 下

  如果用户输入的查询条件中,用户名字等于“fred”,密码等于“something”,则系统执行的查询实际上是:

  SELECT id FROM users WHERE

  username='fred' AND password=

  'something'

  这个查询能够正确地对用户名字和密码进行检查。但是,如果用户输入的查询条件中,名字等于“fred' AND ('a'='b”,密码等于“blah') OR 'a'='a”,此时系统执行的查询变成了:

  SELECT id FROM users

  WHERE username='fred' AND (

  'a'='b' AND password='blah') OR 'a'='a'

  可以看出,这个查询无法正确地对用户名字和密码进行检查。Listing 6的代码要安全得多,它从根本上防止了用户修改SQL命令逃避检查。

  (Listing 6)

  String user = request.getAttribute("username");

  String pass = request.getAttribute("password");

  String query = "SELECT id FROM users

  WHERE username=? AND password=?";

  PreparedStatement stmt = con.prepareStatement(query);

  stmt.setString(1, user);

  stmt.setString(2, pass);

  ResultSet rs = stmt.executeQuery();

  ...

  所有对文件系统的访问都是字符串可能被解释执行的地方。用Java访问文件系统时,我们应该注意文件的命名方式。Listing 7是一个可能带来危险的例子。这个程序根据用户输入决定读取哪个文件,它的危险就在于攻击者能够输入“../../../etc/passwd”这样的文件名字并获得系统的密码文件。这可不是我们希望出现的事情。预防出现这种安全漏洞最简单的方法是:除非绝对需要,否则不要使用平面文件(Flat File)。

  (Listing 7)

  public class UnsafeServlet

  {

  public void doGet(HttpServletRequest request,

  HttpServletResponse response)

  {

  String product = request.getAttribute("product");

  Reader fin = new FileReader(

  "/usr/unsafe/products/"+ product);

  BufferedReader in = new BufferedReader(fin);

  String cost = in.readLine();

  // 其他处理过程

  response.getWriter().println(cost);

  }

  }

  大多数服务器系统,包括Servlet、JSP和EJB,都支持不直接依赖文件系统访问的配置方法。使用定制的SecurityManager或者使用一个简单的检查脚本(检查程序是否直接操作文件系统以及是否使用映像API),我们就可以实施“无文件系统直接访问”策略。尽管大多数应用服务器允许使用文件系统,但一个好的EJB不会使用它。

  最后,请务必不要忘记保持数据充分分离、精确定义这一良好的编程习惯。假设我们有一个用来保存用户信息的数据库,现在需要增加一个字段标示用户是否具有超级用户权限。如果在原来的表中增加一个列实在过于复杂,采用下面这种方法就变得很有吸引力:在用户名字中加上一个特殊字符表示用户是否具有特殊权限,当用户登录时检查该特殊字符,以便防止非法用户宣称自己拥有特殊权限。但事实上,这种做法是非常有害的。所有的数据域,不管它是在数据库中还是作为局部变量,都应该精确定义且只保存一份信息。

  五、基本原则总结

  根据上述讨论,我们得到如下防止出现安全问题的基本原则:

  对于各个输入域,严格地定义系统可接受的合法输入字符,拒绝所有其他输入内容。

  应该尽可能早地对用户输入进行检查,使得使用危险数据的区域减到最小。

  不要依赖浏览器端JavaScript进行安全检查(尽管对用户来说这是一种非常有用的功能),所有已经在客户端进行的检查应该在服务器端再进行一次。

  这些原则有助于消除大量的安全问题。本质上,在应用这一级上,URL和POST数据是用户和应用交互的唯一途径,所以我们的注意力应该集中在URL和用户输入数据的安全性上。

  当然,简单地遵从本文的建议并不能够保证绝对的安全。你必须分析其他各方面的因素,包括网络的安全性以及你所用到的其他服务的安全性。

  每天都有新的安全漏洞被发现和修正。在系统足够安全、可以连接到Internet之前,请务必听取专家的建议;在正式提交源代码之前,一定要留意可能存在的漏洞。小心永不过份。

精彩图集

赞助商链接