sql注入攻击与防御java_Java应用中的SQL依赖注入攻击和防范

说说自己对注入的一些体会吧。

什么叫SQL依赖注入?顾名思义,就是依赖于SQL语句的一种攻击方式,主要采用特殊字符串来处理的SQL漏洞。

这个SQL依赖注入已经是很老的漏洞了,现在基本上DAO层的编写已经很少使用纯JDBC来写sql语句了。

所以在没有使用framework来做DAO,而直接使用JDBC且凭凑的SQL语句的话,那么很容易产生依赖注入的漏洞,如下用户登录模块(目前手头项目中就有活生生的例子)

突破第一个用户名的障碍

登录模块

如:

Java代码

User validUser = login.getUserInfo(user.getName());

User validUser = login.getUserInfo(user.getName());

这里的user.getName()是前台从Textfield控件中获得得值,没有做任何处理,于是再看看getUserInfo的方法,如下:

Java代码

publicUser getUserInfo(String userName)

{

User validUser = null;

String sql = "Select * from WEB_USER where NAME='"+ userName +"'";

Database db = null;

ResultSet rs = null;

try{

db = newDatabase("XXX");

rs = db.execQuery(sql);

if(rs !=null&& rs.next()) {

validUser = newUser();

....

}

}

}

public User getUserInfo(String userName) { User validUser = null; String sql = "Select * from WEB_USER where NAME='" + userName + "'"; Database db = null; ResultSet rs = null; try { db = new Database("XXX"); rs = db.execQuery(sql); if (rs != null && rs.next()) { validUser = new User(); .... } } }

我们看到从前台传过来的userName没有经过任何处理而直接凭凑的SQL语句,所以如果输入者精心构造的话,就可以突破第一个屏障,生成一个有效的用户对象,比如:

输入: cjcj' or '1'='1

这样的字符串输入到后台的SQL语句就为:

select * from web_user where name='cjcj' or '1'='1'

显然,这个rs肯定是结果集的。我们完成了突破第一个屏障的任务。

细心的人可能注意到,这里我们是用的execQuery,只做一个查询操作,这样并不能达到任意登录的目的,没关系,我们再看。

突破第二层障碍

我们发现:

Java代码

if(retry_cnt >=3)

{

login.lockUser(user);

List errors = newArrayList();

ErrorObj error = newErrorObj();

error.setErrorMsg("登录3次失败,该用户已被锁定,请与管理员联系");

errors.add(error);

this.getSession().setAttribute(CTDRConstants.ERROR_ATTRIBUTES, errors);

this.getRequest().setAttribute("userName", user.getName());

}

if(retry_cnt >= 3) { login.lockUser(user); List errors = new ArrayList(); ErrorObj error = new ErrorObj(); error.setErrorMsg("登录3次失败,该用户已被锁定,请与管理员联系"); errors.add(error); this.getSession().setAttribute(CTDRConstants.ERROR_ATTRIBUTES, errors); this.getRequest().setAttribute("userName", user.getName()); }

当用户3次输入密码错误的时候,就更改用户状态,用户被锁定(目前很多网站是这种机制,所以需要谨慎一点),既然需要更改用户状态,就有可能涉及到为execUpdate操作,只要有execUpdate操作,hacker们就有机会了,我们继续往下看lockUser方法;

Java代码

publicvoidlockUser(User user)

{

String sql = "update WEB_USER set status=1 where NAME='"+ user.getName() +"'";

Database db = null;

try{

db = newDatabase("XXX");

db.execUpdate(sql);

}

...

}

public void lockUser(User user) { String sql = "update WEB_USER set status=1 where NAME='" + user.getName() + "'"; Database db = null; try { db = new Database("XXX"); db.execUpdate(sql); } ... }

这里的user对象就是刚从表里select出来的第1个对象,且user.getName()也是直接从前台页面上取的,并没有重新赋值,所以这里可以构造一个拥有语法错误的SQL,让前台报错,从而找到存储用户的表名,比如

输入cjcj' select '1'='1

后台会执行:select * from web_user where name='cjcj' select '1'='1'

然后这条出错的SQL语句信息就有可能暴露在前台了,这样我们就拿到了存储用户信息的表名。

于是我构建一个重置所有密码的SQL语句,如:

输入cjcj' or 1=1;update WEB_USER set passwd='

这样导致WEB_USER所有密码都为空或者MD5的密码。

最后就可以用cjcj' or '1'='1 这个用户登录了。

但是这样做的缺点是所有用户的密码都更改了很容易被管理员发现的。应该有更好的办法,待续...

另外如果执行的SQL语句为:

Java代码

String sql ="Select * from WEB_USER where NAME='"+ userName +"' and PASSWD='"+Passwd+"'";

String sql = "Select * from WEB_USER where NAME='" + userName + "' and PASSWD='"+Passwd+"'";

这样就更简单了,直接构造上面的那个输入就可以任意登录了。

我们看到,这个应用有待改进的地方:

1、对输入含有'符号进行转换或者禁止;

2、update用户锁定状态时,应该把user.getName()改为:

Java代码

validUser.getName()

validUser.getName()

3、使用PrepareStatement或者使用dao层框架。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值