`
C_J
  • 浏览: 127863 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java应用中的SQL注入攻击和防范

阅读更多
    说说自己对注入的一些体会吧。
    什么叫SQL注入?顾名思义,就是依赖于SQL语句的一种攻击方式,主要采用特殊字符串来处理的SQL漏洞。
    这个SQL依赖注入已经是很老的漏洞了,现在基本上DAO层的编写已经很少使用纯JDBC来写sql语句了。

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

    突破第一个用户名的障碍
登录模块
如:
 User validUser = login.getUserInfo(user.getName());

这里的user.getName()是前台从Textfield控件中获得得值,没有做任何处理,于是再看看getUserInfo的方法,如下:
 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,只做一个查询操作,这样并不能达到任意登录的目的,没关系,我们再看。

    突破第二层障碍   
    我们发现:

 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方法;
 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语句为:
 String sql = "Select * from WEB_USER where NAME='" + userName + "' and PASSWD='"+Passwd+"'";

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


我们看到,这个应用有待改进的地方:
1、对输入含有'符号进行转换或者禁止;
2、update用户锁定状态时,应该把user.getName()改为:

validUser.getName()

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



分享到:
评论
29 楼 liwenjie 2010-04-27  
evilseed 写道
PrepareStatement是怎样解决这种问题的?是因为一个参数必须对应一个?么?一个萝卜一个坑。

我的理解是sql的预编译是将sql的执行计划在内存中进行存储,下次执行该sql不必再次经过查询分析器计算执行计划。预编译sql先是发送sql,然后匹配参数,非预编译sql是整条sql发送出去。请大家讨论
28 楼 didiluck 2010-04-27  
都是用sql预编译就没有问题了。
27 楼 evilseed 2010-04-27  
PrepareStatement是怎样解决这种问题的?是因为一个参数必须对应一个?么?一个萝卜一个坑。
26 楼 lz12366 2010-04-26  
以前记得asp中常常玩点入侵...jsp这没试过....
25 楼 godymoon 2010-04-26  
SQl注入就是了,哥们还加个“依赖”。。。还控制反转呢。。。
24 楼 a379803901 2010-04-26  
''这个初学者一般都知道吧。。。
23 楼 lzstone 2010-04-26  
这个问题确实有点老,做ASP的时候经常会有这样的问题,java提供的决绝方案已经很完备,现在自己可以进行关键字的筛选
22 楼 liann151 2010-04-26  
C_J 写道
    说说自己对注入的一些体会吧。
    什么叫SQL依赖注入?顾名思义,就是依赖于SQL语句的一种攻击方式,主要采用特殊字符串来处理的SQL漏洞。
    这个SQL依赖注入已经是很老的漏洞了,现在基本上DAO层的编写已经很少使用纯JDBC来写sql语句了。

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

    突破第一个用户名的障碍
登录模块
如:
 User validUser = login.getUserInfo(user.getName());

这里的user.getName()是前台从Textfield控件中获得得值,没有做任何处理,于是再看看getUserInfo的方法,如下:
 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,只做一个查询操作,这样并不能达到任意登录的目的,没关系,我们再看。

    突破第二层障碍   
    我们发现:

 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方法;
 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语句为:
 String sql = "Select * from WEB_USER where NAME='" + userName + "' and PASSWD='"+Passwd+"'";

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


我们看到,这个应用有待改进的地方:
1、对输入含有'符号进行转换或者禁止;
2、update用户锁定状态时,应该把user.getName()改为:

validUser.getName()

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




21 楼 ardy 2010-04-26  
楼主用词就不当,这哪是什么依赖注入啊,这以前就叫SQL语句注入攻击。
不要加依赖注入进去就混淆视听,当现代技术
20 楼 habzyhs 2010-04-26  
C_J 写道
godfish 写道
这都什么年代的事情了

我们现在的项目就有,看来已经out了~~



我们项目也有啊,而且到处都是,看来也已经out了。
19 楼 habzyhs 2010-04-26  
这样来说,ibatis拼出来的sql也会有问题咯。。。如果对所有此类型的输入都过滤一下还是挺麻烦的嘛~~
18 楼 joehe 2010-04-26  
asd070512 写道
joehe 写道
楼主你举的这个登录的例子,并不能说明问题,不管如何,保存在数据库里的密码总是加密的吧?你查询的时候,不管用户输入的密码怎么变相处理,加密去查就不会有这个问题了

怎么会没有问题,我直接在本地用MD5加密再更新密码就有问题了!

这样的系统只怕只有你做出来
17 楼 huangjin871218 2010-04-26  
erikchang 写道
用面向对象的查询,哪里还存在这样弱智的问题!


被框架祸害的孩子....
16 楼 asd070512 2010-04-26  
joehe 写道
楼主你举的这个登录的例子,并不能说明问题,不管如何,保存在数据库里的密码总是加密的吧?你查询的时候,不管用户输入的密码怎么变相处理,加密去查就不会有这个问题了

怎么会没有问题,我直接在本地用MD5加密再更新密码就有问题了!
15 楼 Javac_MyLife 2010-04-25  
erikchang 写道
用面向对象的查询,哪里还存在这样弱智的问题!

很久没写SQL
14 楼 joehe 2010-04-25  
楼主你举的这个登录的例子,并不能说明问题,不管如何,保存在数据库里的密码总是加密的吧?你查询的时候,不管用户输入的密码怎么变相处理,加密去查就不会有这个问题了
13 楼 C_J 2010-04-25  
liwenjie 写道
godfish 写道
这都什么年代的事情了

如果你在做大数据量的查询,采用IBatis方案,sql注入的问题是肯定要考虑的。在金融、电信领域,复杂的sql查询是面向数据分析的,这是很普遍的,根本不是简单的OO映射,hibernate做这个是不是不太适合??所以我们一直使用IBaits



这个是有同感的!

** 对于你说的查询$$的问题,IBATIS的XML解析的时候如果带;符号,貌似是报错的。
比如:

<select ...>
SELECT * FROM APP ORDER BY $para1$
</select>


para1里是不是过滤掉了;号? 莫非是处于安全的考虑?
12 楼 wang79 2010-04-25  
不管用什么方式,能不能写个公用的方法,过滤一下页面传进来的所有参数?
11 楼 玲cc 2010-04-25  
呵呵,各种牛人
不过对我来说还是新鲜的东西
学习了
10 楼 liwenjie 2010-04-25  
godfish 写道
这都什么年代的事情了

如果你在做大数据量的查询,采用IBatis方案,sql注入的问题是肯定要考虑的。在金融、电信领域,复杂的sql查询是面向数据分析的,这是很普遍的,根本不是简单的OO映射,hibernate做这个是不是不太适合??所以我们一直使用IBaits

相关推荐

    Java防止SQL注入的几个途径

    SQL 注入攻击是黑客最常用的攻击方式之一,它可以让攻击者访问或修改数据库中的敏感信息。因此,防止 SQL 注入是 Java 开发者必须注意的安全问题。 1.杜绝 SQL 拼接 最简单的办法是杜绝 SQL 拼接。SQL 注入攻击能...

    SQL注入攻击原理分析及JavaWeb环境下的防范措施.pdf

    本文在分析了SQL 注入原理的基础上,提出了几点Java Web 环境下防范措施。   随着Ineternet 技术的迅猛发展,为了能更充分地使用互联网这个世界上最大的交流平台,许多单位或个人纷纷建立自己的网站。但是...

    用Java Web防范SQL注入攻击.pdf

    【Java Web防范SQL注入攻击】 Java Web平台因其跨平台性和"一次编写,到处运行"的特性,被广泛应用在各种web应用程序开发中。然而,如果不妥善处理用户输入,就可能为SQL注入攻击提供机会。以下是一些Java Web环境中...

    SQL 数据库 注入攻击的种类和防范手段

    本文将深入探讨SQL注入攻击的多种类型及其有效的防范策略,帮助企业和开发者构建更加安全的网络环境。 #### SQL注入攻击的种类 1. **未确认转换类型的漏洞**:当应用程序未能正确处理用户输入,将其视为SQL语句的...

    基于J2EE应用的SQL注入分析与防范.pdf

    在测试过程中,有效发现漏洞之后,通过综合运用屏蔽出错信息、分配最小权限、参数化查询、输入验证及输入转义等防范方法,可以显著降低SQL注入攻击的风险,提高应用程序的安全性和实用性。 在实际应用中,防范SQL...

    SQL注入攻击的种类和防范手段,代码教程

    SQL注入攻击是网络安全领域中的一个严重威胁,它发生在应用程序与数据库交互时,恶意用户通过输入特殊的SQL代码,篡改原本的查询逻辑,从而获取、修改、删除敏感数据或执行非法操作。了解SQL注入的种类和防范手段...

    基于jQuery的SQL注入攻击防范实现

    ### 基于jQuery的SQL注入攻击防范实现 #### 一、引言 SQL注入攻击是Web应用程序中常见的安全威胁之一。它通过恶意输入来操纵数据库查询,从而获取未授权的数据或执行非法操作。传统的防御措施多集中在服务器端,如...

    JSP如何防范SQL注入攻击

    SQL注入攻击通过将恶意代码插入到SQL查询中,从而绕过应用系统的安全措施,实现非法获取数据或破坏数据库的目的。 #### SQL注入原理 SQL注入攻击的核心在于利用应用程序对用户输入的数据未做充分验证这一漏洞,...

    java web Xss及sql注入过滤器.zip

    总之,这个项目提供了预防XSS和SQL注入的实例,对于学习如何在Spring Boot应用中实现安全防护非常有帮助。开发者可以通过研究项目源码,了解如何自定义过滤器、配置安全策略以及利用Spring Boot的安全特性,提升自己...

    关于JSP防范SQL注入攻击

    本文将详细介绍如何在JSP开发过程中防范SQL注入攻击,包括SQL注入的基本原理、常见的防范策略及具体实现方法。 #### 二、SQL注入攻击原理 SQL注入攻击是指攻击者通过向Web应用程序提交恶意构造的SQL语句,使得这些...

    防范Java中的SQL注入:策略与实践

    SQL注入是一种常见的Web应用安全漏洞,它允许攻击者通过在应用程序的输入字段中插入恶意SQL代码,从而对数据库进行未授权的访问或操作。由于Java广泛用于企业级Web应用的开发,因此了解如何在Java中识别和防护SQL...

    SQL注入攻击与防护措施研究

    由于SQL注入攻击通常通过Web应用的标准端口进行,并且看起来与正常的Web页面访问并无二异,因此大多数防火墙难以检测到此类攻击。攻击者往往能轻易获取敏感信息,如数据库账号、密码等,并进一步篡改管理员账户信息...

    SQL注入源码+SQL注入命令

    在这个实验中,我们将关注Java语言如何处理SQL查询,以及如何防范SQL注入。 标题中的"SQL注入源码+SQL注入命令"提示我们将探讨实际的源代码片段和可能的注入命令。在Java应用中,通常使用JDBC(Java Database ...

    如何解决sql注入问题

    ### 如何解决SQL注入问题:全面解析与防范策略 #### SQL注入概述 ...通过采用安全编码实践、强化输入验证、合理使用数据库功能以及持续监控和更新安全策略,可以显著降低应用程序遭受SQL注入攻击的风险。

    面向MyBatis程序的SQL注入攻击及防御策略.pdf

    本文主要针对MyBatis框架下的程序开发环境,分析了SQL注入攻击的原理,探讨了在WEB应用中SQL注入攻击的常见方式,并针对MyBatis框架提出了有效的防御措施。 首先,SQL注入攻击原理主要涉及攻击者通过构造特定的SQL...

    Oracle数据库中SQL注入攻击的检测与防御

    ### Oracle数据库中SQL注入攻击的检测与防御 #### 摘要 本文深入探讨了SQL注入攻击的概念及其在Oracle数据库中的检测与防御方法,并提出了有效的应对策略。虽然文中以Oracle数据库为例进行了阐述,但这些技术和...

    程序分析技术在SQL注入防御中的应用研究.pdf

    程序分析技术在SQL注入防御中的应用研究是指利用程序分析技术来防御SQL注入攻击的方法。SQL注入攻击是一种常用且易于实施的攻击手段,对Web应用程序的安全构成严重危害。本文提出了一种基于程序分析技术的SQL注入...

    mybatis如何防止SQL注入

    SQL注入是一种常见的Web应用程序安全漏洞,攻击者可以通过提交恶意的SQL代码到应用程序的输入字段中(如表单、URL等),利用这些输入来操控数据库执行非预期的操作,进而获取敏感数据、修改数据甚至破坏整个数据库...

Global site tag (gtag.js) - Google Analytics