件:
Runtime.getRuntime().exec("/usr/sbin/sendmail -t $retaddr < $data");
事实上这是行不通的。Java一般不允许把OS级“<”和“;”之类的构造符号作为
Runtime.exec()的一部分。你可能会尝试用下面的方法解决这个问题:
Runtime.getRuntime().exec("sh /usr/sbin/sendmail -t $retaddr < $data");
但是,这种代码是不安全的,它把前面Perl代码面临的危险带入了Java程序。按照常规
的Java方法解决问题有时看起来要比取巧的方法复杂一点,但它几乎总是具有更好的可
移植性、可扩展性,而且更安全、错误更少。Runtime.exec()只是该问题的一个简单例
子,其他许多情形更复杂、更隐蔽。
让我们来考虑一下Java的映像API(Reflection API)。Java映像API允许我们在运行时
决定调用对象的哪一个方法。任何由用户输入命令作为映像查找条件的时机都可能成为
系统的安全弱点。例如,下面的代码就有可能产生这类问题:
Method m = bean.getClass().getMethod(action, new Class {});
m.invoke(bean, new Object {});
如果“action”的值允许用户改变,这里就应该特别注意了。注意,这种现象可能会在
一些令人奇怪的地方出现——或许最令人奇怪的地方就是JSP。大多数JSP引擎用映像
API实现下面的功能:
<jsp:setProperty name="bean" property="*" />
这个Bean的set方法应该特别注意,因为所有这些方法都可以被远程用户调用。例如,
对于Listing 3的Bean和Listing 4的JSP页面:
(Listing 3)
public class Example
{
public void setName(String name) {
this.name = name; }
public String getName() { return name; }
public void setPassword(String pass) {
this. pass = pass; }
public String getPassword() { return
pass; }
private String name;
private String pass;
}
(Listing 4)
<%@ page import="Example" %>
<jsp:useBean id="example" scope="page"
class="Example" />
<jsp:setProperty name="example" property="*" />
<html>
<head>
<title>Bean示例</title>
</head>
<body>
<form>
<input type="text" name="name" size="30">
<input type="submit" value="Submit">
</form>
</html>
从表面上看,这些代码只允许用户访问example Bean的名字。然而,了解该系统的用户
可以访问“http://whereever.com/example.jsp?name=Fred&password=hack”这种URL
。这个URL既改变name属性,也改变password密码属性。当然,这应该不是页面编写者
的意图,作者的意图是设计一个只允许用户访问名字属性的页面。因此,在使用
<jsp:setProperty property="*" />。>
时应该非常小心
字符串被解释执行的问题可能在允许嵌入脚本代码的任何环境中出现。例如,这类问题
可能在Xalan(也称为LotusXSL)中出现,当然这是指系统设置不严格、易受攻击的情
况下。
Xalan的脚本支持能够关闭(而且这是Xalan的默认设置),在敏感的应用中关闭脚本支
持是一种明智的选择。当你需要用DOM处理XML文档时还必须考虑到另外一点:DOM保证
所有文本都经过正确的转义处理,防止非法的标记插入到脚本之内。LotusXSL缺乏这个
功能,但这绝不是一个BUG。支持脚本是LotusXSL的一个特色,而且它(明智地)默认
处于关闭状态。XSL的W3C规范并没有规定支持脚本的能力。
现在我们来看看字符串解释执行如何影响SQL和JDBC。假设我们要以用户名字和密码为
条件
搜索数据库中的用户,Listing 5的Servlet代码看起来不错,但事实上它却是