A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 孙传磊 中级黑马   /  2013-3-1 20:42  /  1537 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 孙传磊 于 2013-3-8 11:55 编辑

描述如下:
   sql注入攻击是黑客常用的攻击方式之一,他们利用在界面传入服务器数据库的sql语句的漏洞,进行添加一些貌似合理的sql语句,进入数据库,植入木马,当然利用sql注入,防火墙是管不到的,因为防火墙也分不清传入的sql 是否是合法的,所以服务器很容易遭遇这种攻击,望有大侠详细介绍jsp如何实现防止sql注入。

6 个回复

倒序浏览
jdbc 预处理
回复 使用道具 举报
这个要交给与之相对应的数据库驱动程序来出来,在后台数据库连接的时候就不能字符串拼接的方法。
比如说
不安全的是用字符串拼接的。
不安全的:

  Connection conn = null;
  Statement st = null;
  ResultSet rs = null;
  try {
   // 2.建立连接
   conn = JdbcUtils.getConnection();
   // conn = JdbcUtilsSing.getInstance().getConnection();
   // 3.创建语句
   String sql = "select id, name, money, birthday  from user where name='"
     + name + "'";
   st = conn.createStatement();
   // 4.执行语句
   rs = st.executeQuery(sql);
   // 5.处理结果
   while (rs.next()) {
    // System.out.println(rs.getObject("id") + "\t"
    // + rs.getObject("name") + "\t"
    // + rs.getObject("birthday") + "\t"
    // + rs.getObject("money"));
   }
  } finally {
   JdbcUtils.free(rs, st, conn);
  }
}


如果要安全要用
PreparedStatement的应用
把数据交给数据库驱动来做
安全代码如下:
  Connection conn = null;
  PreparedStatement ps = null;
  ResultSet rs = null;
  try {
   // 2.建立连接
   conn = JdbcUtils.getConnection();
   // conn = JdbcUtilsSing.getInstance().getConnection();
   // 3.创建语句
   String sql = "select id, name, money, birthday  from user where name=?";
   ps = conn.prepareStatement(sql);
   ps.setString(1, name);
   // 4.执行语句
   rs = ps.executeQuery();
   // 5.处理结果
   while (rs.next()) {
    System.out.println(rs.getInt("id") + "\t"
      + rs.getString("name") + "\t" + rs.getDate("birthday")
      + "\t" + rs.getFloat("money"));
   }
  } finally {
   JdbcUtils.free(rs, ps, conn);
  }

评分

参与人数 1技术分 +1 收起 理由
张庚 + 1

查看全部评分

回复 使用道具 举报
当然这是jdbc上的办法,在Hibernate上也有相对应的解决办法
回复 使用道具 举报
好多高手,完全听不懂
回复 使用道具 举报
我也不懂 别人是这么说的
sql注入攻击的总体思路:
发现sql注入位置;
判断服务器类型和后台数据库类型;
确定可执行情况

对于有些攻击者而言,一般会采取sql注入法。下面我也谈一下自己关于sql注入法的感悟。

注入法:
从理论上说,认证网页中会有型如:
select  from admin where username= xxx  and password= yyy  的语句,若在正式运行此句之前,如果没有进行必要的字符过滤,则很容易实施sql注入。
如在用户名文本框内输入:abc’ or 1=1-- 在密码框内输入:123 则sql语句变成:
select  from admin where username= abc’ or 1=1 and password= 123’ 不管用户输入任何用户名与密码,此语句永远都能正确执行,用户轻易骗过系统,获取合法身份。

猜解法:
基本思路是:猜解所有数据库名称,猜出库中的每张表名,分析可能是存放用户名与密码的表名,猜出表中的每个字段名,猜出表中的每条记录内容。
还有一种方式可以获得你的数据库名和每张表的名。
就是通过在形如:http://www. .cn/news?id=10 的方式来通过报错获得你的数据库名和表名!
对于jsp而言我们一般采取一下策略来应对:
1、preparedstatement
如果你已经是稍有水平开发者 你就应该始终以preparedstatement代替statement.
以下是几点原因
1、代码的可读性和可维护性.
2、preparedstatement尽最大可能提高性能.
3、最重要的一点是极大地提高了安全性.
到目前为止,有一些人(包括本人)连基本的恶义sql语法都不知道.
string sql = " select  from tb_name where name= " +varname+"   and passwd= " +varpasswd+" "   
如果我们把[  or 1  = 1]作为name传入进来.密码随意 看看会成为什么? 网管网bitscn.com

select  from tb_name = or 1  = 1  and passwd = 随意   
因为 1 = 1 肯定成立 所以可以任何通过验证.更有甚者:
把[   drop table tb_name  ]作为varpasswd传入进来 则:
select  from tb_name = 随意  and passwd =    drop table tb_name  有些数据库是不会让你成功的 但也有很多数据库就可以使这些语句得到执行.
而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.(前提是数据库本身支持预编译 但上前可能没有什么服务端数据库不支持编译了 只有少数的桌面数据库 就是直接文件访问的那些只要全使用预编译语句 你就用不着对传入的数据做任何过虑.而如果使用普通的 statement 有可能要对drop   等做费尽心机的判断和过虑.
2、正则表达式
2.1、检测sql meta-characters的正则表达式 /(27)|( )|(--)|(23)|(#)/ix
2.2、修正检测sql meta-characters的正则表达式 /((3d)|(=))[^ ]((27)|( )|(--) 54ne.com

|(3b)|(:))/i
2.3、典型的 sql 注入攻击的正则表达式 /w((27)|( ))((6f)|o|(4f))((72)|r|( 中国网管联盟www.bitscn.com

52))/ix
2.4、检测sql注入,union查询关键字的正则表达式 /((27)|( ))union/ix(27)|( ) - 单

引号和它的hex等值  union - union关键字。
2.5、检测ms sql server sql注入攻击的正则表达式 / (s|+)+(s|x)pw+/ix

3、字符串过滤
public static string filtercontent(string content){
string flt =" |and| |insert|select|delete|update|count||

|chr|mid|master|truncate|char|declare|  |or|-|+| "   
stringfilter[] = flt.split(" |" )  
for(int i=0  i {
content.replace(filter[i]  " " )  
}
return content  
}
4、不安全字符屏蔽

本部分采用js来屏蔽,起的作用很小,这样用屏蔽关键字的方法虽然有一定作用,但是在实际应用中这些 sql的关键字也可能成为真正的查询关键字,到那是被你屏蔽了那用户不是不能正常的使用了。 只要在代码规范上下点功夫就可以了。
凡涉及到执行的sql中有变量时,用jdbc(或者其他数据持久层)提供的如:preparedstatement就可以 ,切记不要用拼接字符串的方法就可以了.
功能介绍:检查是否含有" "  " \"  " /"  
参数说明:要检查的字符串
返回值:0:是 1:不是
函数名是
function check(a)
{
return 1  
fibdn = new array (" "   " \"  " /" )  
i=fibdn.length  
j=a.length  
for (ii=0  ii { for (jj=0  jj

{ temp1=a.charat(jj)  
temp2=fibdn[ii]  
if (tem   p1==temp2)
{ return 0  }
}
}
return 1  

}


回复 使用道具 举报
如果也问题已解决,请改为已经解决,没有,就追问,谢谢合作
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马