Web系统安全漏洞(JAVA)

引言

最近,公司中通过AppScan和360两种工具,对系统进行漏洞扫描。由于我们做的是传统行业项目,运用的框架等技术,比较落后。所以扫描结果可想而知,“雪崩”。于是乎,我们就开始了无尽的折磨…

1.代码注入

(1)命令注入

我们的系统,是跑在WinServer上的,里面有部分代码会对操作系统的CPU、内存等进行监控,这时就用到了System.Runtime.getRuntime().exec();这个方法,执行对应的cmd命令。由于对入参的String,未做任何关键校验,导致出现此漏洞。

下面我举个栗子:

以下代码来自一个Web应用程序,该段代码通过运行rmanDB.bat脚本启动Oracle数据库备份,然后运行cleanup.bat脚本删除一些临时文件。脚本文件rmanDB.bat接受一个命令行参数,其中指明需要执行的备份类型。

...
String btype = request.getParameter("backuptype");
String cmd = new String("cmd.exe /K \"c:\\util\\rmanDB.bat "+btype+"&& c:\\utl\\cleanup.bat\"");
System.Runtime.getRuntime().exec(cmd);
...

该段代码没有对来自用户请求中的backuptype参数做任何校验。
通常情况下,Runtime.exec()函数不会执行多条命令,但在以上代码中,为了执行多条命令,程序调用Runtime.exec()方法,首先运行了cmd.exe指令,因此能够执行用&&分隔的多条命令了。
如果攻击者传递了一个形式为"&& del c:\\dbms\\*.*"的字符串,那么该段代码将会在执行其他指定命令的同时执行这条命令,对系统造成伤害。

(2)SQL注入

什么是SQL注入呢?它是一种数据库攻击手段,用户可以通过输入的参数,对原本的这个sql语句,进行更改,导致该sql执行出其它效果,对系统造成伤害。

例如:

我们在进行系统登陆的场景中,系统会执行这样一条SQL语句,
" SELECT id,username,password FROM db_user WHERE username = ' " + username + " ' AND password = ' " + pwd + " ' ";

如果将username的值写为张三’ OR ‘1’=1,这时这个sql语句,就变为:
SELECT id,username,password FROM db_user WHERE username=‘张三’ OR ‘1’=‘1’ AND password=’’;
这样的情况,攻击者会在不知道用户的方式,登入你的系统,进行侵入。

同样,攻击者可以为password提供如下字符串,’ OR ‘1’='1
SELECT id,username,password FROM db_user WHERE username=’’ AND password=’'OR ‘1’=‘1’;
也可以达到入侵系统的目的。

而在我们的项目中,使用公司自己的框架,其中框架中与数据库的操作,大多是对JDBC操作的封装。很多地方使用java.sql.Statement拼接出来的sql语句都是类似上面的场景描述的那样,会引起SQL注入。而且,前人在写代码时,也未对具体的入参进行关键校验。

下面说说怎么改进:

就是,将之前的java.sql.Statement替换为java.sql.PreparedStatement,更换了API,使用后者的好处不少,我来简单罗列一下:

  1. 很好的,防止SQL注入,具体的原因还是因为有预编译的能力,在后期参入传入时通过替换占位符,将指定参数传入。(SQL注入只会在编译期存在隐患)
  2. 有预编译效果,使数据库多次执行同一个sql语句,性能更高。
  3. 使代码更加简洁(强加的优点,哈哈)。

鉴于以上优点,尽量使用“PreparedStatement” 。不过身为21世纪的程序猿,在项目中与数据库的交互,普遍都在用MyBatis、Hibernate框架,这类框架已经很好的屏蔽了这一层次的问题。但是在这些框架中依然存在SQL注入的情况,这个安全问题,值得注意。

MyBatis框架SQL注入

这个框架在我们的项目中,没有用到,我在这里作为知识点,简单总结一下。
其实主要就是通过 #{} 防止SQL注入。
可以通过DeBug得到,它通过代码执行出的sql语句是这样的:

	//数据库执行该语句之前,会进行预编译
	SELECT id,username,password FROM db_user WHERE username = ? AND password = ?;	

在数据库执行时,会动态的将 “?”这个占位符替换为具体参数,执行SQL语句。从而避免SQL注入问题。本质上还是使用了JDBC的PreparedStatement先进行了预编译,这是个关键点。

还有一种表达式是**${}**,它也可以将变量插入sql语句中,但是它未进行预编译,是非安全的,存在SQL注入的隐患。因为它在代编译期的时候,会将参数值传入SQL语句中,与上面的登陆场景效果一样。这种表达式,可以用于动态传入数据库对象,例如传入表名。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值