精华内容
下载资源
问答
  • SQL注入问题

    千次阅读 多人点赞 2019-12-02 12:18:07
    今天使用Java语言,来分析一下sql注入的相关问题。 一、什么是SQL注入 SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL...

    sql注入是一种通过在输入中注入sql语句,来达到攻击数据库的效果。今天使用Java语言,来分析一下sql注入的相关问题。

    一、什么是SQL注入

    SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

    二、模拟SQL注入

    我们先创建一个简单的数据库和一个user表:

    create database test;
    use database test;
    create table user(username varchar(20), password(20));
    

    我们在表中插入两个数据:

    insert into user values('zack', '123456');
    insert into user values('rudy', '123456');
    

    我们再看一个简单的Java程序:

    package com.zack.sql;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Scanner;
    
    public class Sql {
    	//链接的url
    	private static String url = "jdbc:mysql:///all_test?serverTimezone=GMT";
    	//用户名
    	private static String user = "root";
    	//密码
    	private static String password = "123456";
    	//用于输入
    	Scanner sc = new Scanner(System.in);
    	
    	public static void main(String[] args) throws Exception {
    		//加载驱动
    		Class.forName("com.mysql.jdbc.Driver");
    		//获取连接
    		Connection conn = DriverManager.getConnection(url, user, password);
    		//获取statment对象
    		Statement stat = conn.createStatement();
    		
    		//要求用户输入用户名和密码
    		System.out.println("请输入你的用户名:");
    		String name = sc.next();
    		System.out.println("请输入密码:");
    		String pwd = sc.next();		
    		
    		//code1、通过用户输入的用户名和密码来查询数据库中是否存在该用户
    		ResultSet set = stat.executeQuery("select * from user where username = '" + name + "' and password = '" + pwd + "'");
    
    		//将匹配到的数据打印出来
    		while(set.next()) {
    			String username = set.getString("username");
    			String password = set.getString("password");
    			System.out.println("name:" + username + ", pwd:" + password);
    		}
    	}
    
    }
    

    我们看到code1,假设我们输入的如下:

    zack
    123456
    

    这个正好是与我们数据库中匹配的,那么code1中执行的sql语句如下:

    select * from user where username = 'zack' and password = '123456';
    

    我们原本设想的是,如果输入不匹配的数据,将无法在数据库中查找到相应的东西,但是我们进行如喜爱输入:

    zack' or '1' = '1
    111
    

    这个时候,code1中执行的语句如下:

    select * from user where username = 'zack' or '1'='1' and password = '123456';
    

    其中’1’ = '1’是恒为真的,所以这个sql语句不会再去判断密码是否正确,这样就完成了SQL注入攻击的效果。

    三、如何防止SQL注入

    防止sql注入的方法也非常简单,在jdbc中有一个sql语句预编译的对象,我们可以通过PrepareStatement类来实现。假设我们还是要执行查询操作,执行语句如下:

    String sql = "select * from user where username = ? and password = ?";
    

    这里我们使用“?”来表示字段的值。然后我们来创建一个PrepareStatement对象,这里和Statement有些不一样:

    //在创建PrepareStatement对象时,就传入了sql语句
    PrepareStatement preStat = conn.prepareStatement(sql);
    

    这里是在创建PrepareStatement对象时就传入了sql语句,而Statement是在执行查询操作时才传入sql语句。
    因为我们已经传入了sql语句,所以在执行查询时不需要传入sql语句,但是要多一步匹配参数的操作:

    //将name的值替换到sql语句中第一个?
    preStet.setString(1, name);
    //将name的值替换到sql语句中第二个?
    preStat.setString(2, pwd);
    

    其中name和pwd是我们输入的字符串变量。接下来我们就可以进行查询操作了:

    ResultSet set = preStat.executeQuery();
    while(set.next()) {
    	String username = set.getString("username");
    	String password = set.getString("password");
    	System.out.println("name:" + username + ", pwd:" + password);
    }
    

    这里操作和之前类似,只是不需要传入sql语句。完整代码如下:

    package com.zack.sql;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Scanner;
    
    public class Sql {
    	
    	private static String url = "jdbc:mysql:///all_test?serverTimezone=GMT";
    	private static String user = "root";
    	private static String password = "123456";
    	private static Scanner sc = new Scanner(System.in);
    	private static String sql = "select * from user where username = ? and password = ?";
    	
    	public static void main(String[] args) throws Exception {
    		//数据库操作
    		Class.forName("com.mysql.jdbc.Driver");
    		Connection conn = DriverManager.getConnection(url, user, password);
    		PreparedStatement stat = conn.prepareStatement(sql);
    		
    		//要求用户输入用户名和密码
    		System.out.println("请输入你的用户名:");
    		String name = sc.next();
    		System.out.println("请输入密码:");
    		String pwd = sc.next();		
    		
    		//通过用户输入的用户名和密码来查询数据库中是否存在改用户
    		stat.setString(1, name);
    		stat.setString(2, pwd);
    		ResultSet set = stat.executeQuery();
    		while(set.next()) {
    			String username = set.getString("username");
    			String password = set.getString("password");
    			System.out.println("name:" + username + ", pwd:" + password);
    		}
    	}
    
    }
    

    四、总结

    SQL注入是早期比较流行的一种攻击数据库的方式,但现在很少会直接使用jdbc进行数据库操作,更不会直接使用sql语句拼接的方式进行操作。所以大多数情况SQL注入都是无效的,可能在一比较老的网址还是有效的,大家可以尝试以下。

    展开全文
  • PreparedStatement解决sql注入问题

    千次阅读 2017-12-27 08:33:01
    转载自PreparedStatement解决sql注入问题解决sql注入的问题 PreparedStatement解决sql注入问题 总结 PreparedStatement解决sql注入问题 :sql中使用?做占位符 2.得到PreparedStatement对象 PreparedStatement pst=...

    转载自PreparedStatement解决sql注入问题解决sql注入的问题

    PreparedStatement解决sql注入问题
    总结 PreparedStatement解决sql注入问题
    :sql中使用?做占位符
    2.得到PreparedStatement对象
    PreparedStatement pst=conn.prepareStatement(String sql);
    pst.setString(1,"aaa");//设置 第一个?的占位符赋值
    pst.setString(2,"bbb");
     
     
     
    // 查找用户 使用PreparedStatement 解决了 sql注入问题
         public User findUser(User user) {
               String sql = "select * from user where username='?' and password='?'";
               Connection conn = null;
               PreparedStatement pst = null;
               ResultSet rs = null;
                try {
                    conn = jdbcUtils. getConnection();
                    pst = conn.prepareStatement(sql);
                    pst.setString(1, user.getUsername());
                    pst.setString(2, user.getPassword());
                    rs = pst.executeQuery();
                     if (rs.next()) {
                         User u = new User();
                         u.setId(rs.getInt( "id"));
                         u.setUsername(rs.getString( "username"));
                         u.setPassword(rs.getString( "password"));
                         u.setEmail(rs.getString( "email"));
                          return u;
                    }
               } catch (Exception e) {
                     // TODO Auto-generated catch block
                    e.printStackTrace();
               }
                return null;
         }


    展开全文
  • 数据库JDBC使用步骤,c3p0连接池,SQL注入问题 一、jdbc的创建步骤:(导入JDBC架包) 1、注册驱动: class.forName("com.mysql.jdbc.Driver"); 2、获取连接: Connection connection=Drivermanager.get...

    数据库JDBC使用步骤,c3p0连接池,SQL注入问题

    一、jdbc的创建步骤:(导入JDBC架包)

    	1、注册驱动:		class.forName("com.mysql.jdbc.Driver");
    	2、获取连接:		Connection connection=Drivermanager.getconnection("数据库路径",“用户名”,“密码”);
    	3、获取执行SQL语句的类对象:	PreparedStatement preparedstement=connection.preparedstatement("SQL语句");
    	4、执行SQL语句返回结果集:	
    			语句一:	ResultSet	rs=preparedstement.executeUpdate();
    			语句二:	ResultSet 	rs=preparedstement.executeQuery();
    	5、处理结果(根据需求遍历):
    				while(rs.next()) (
    					 int id=rs.getInt("id");    
    					System.out.println(id);	
    					)
    	6、关闭资源:	rs.close(),connection.close();									
    

    二、编写JDBCUtils
    public Class JDBCUtlis{

    		private   static   String   url="jdbc:mysql://localhost:3306/test";
    		private   static   String   username="root";
    		private   static   String   password="root";
    	static{
    	      Class.forName("com.mysql.jdbc.Driver");
    	}
    	
    	public static   Connection   getConn(){
    		Connection   connection=DriverManager.getConnection(url,username,password);
    		return  connection;
    	}
    
    //关闭资源
    	public  static   void     close(ResultSet rs,Perparedstment perparedstment,Connection conn){
    		if(!Objects.isNull(rs)){rs.close();}
            			if(!Objects.isNull(perparedstment)){perparedstment.close()}
    		if(!Objects.isNull(conn)){conn.close();}
    	}
    }	
    

    三、SQL注入问题:
    1、根据JDBCUtlis获取数据库连接:
    Connection conn=JDBC.getConn();
    2、创建执行SQL语句的类对象:
    Statement statement=conn.createStatement();
    3、执行SQL语句:
    statement.executeQuety(select * from 表名 where username=‘真龙天子’ AND password=‘123456’ or ‘a’=‘a’);

    	语句中 or ‘a’=‘a’ 是SQL语句注入部分,此条件永远成立,会将你的数据库所有的数据暴露
    	java程序中执行的SQL语句是从前台获取数据然后以SQL语句拼接的方式对数据库进行操作,这就出现SQL语句注入的安全问题,所有java程序在获取数据后不能
    	采取SQL语句拼接的方式对数据库进行操作。
    所有我们要用:
    	Perparedstment perparedstment =conn.perparedstment("select * from 表名  where username=? and password=?");  //这里采用?就是占位符的方式,它可预编译(封装安全验证)
    	perparedstment.setString(1,'真龙天子');  //第一个参数是SQL语句第几个占位符,第二个参数是数据
    	perparedstment.SetString(2,'123456');
    注意:操作数据库时一定要根据数据库各个字段的数据类型选用相同类型的方法。
    

    四、数据库连接池(c3p0连接池)

    1、导入c3p0数据连接池架包,导入c3p0conf.xml的配置文件
    
    2、加载c3p0数据库驱动:
    	ComboPooledDataSource  dataSource=new ComboPoledDataSource();
    3、获取连接	:
    	Connection connection=dataSource.getConnection();
    4、关闭资源:
    	ResultSet.close();
    	perparedstment.close();
    	Connectin.close();
    

    展开全文
  • Node.js 解决sql注入问题

    千次阅读 2019-04-01 12:58:00
    这段时间维护Node.js编写的项目,发现登陆SQL注入问题。经过一番折腾解决了这个问题,现记录如下: 一、问题描述 const crypto = require('crypto'); const conn = require('../../libs/Conn'); const mysql = ...

    这段时间维护Node.js编写的项目,发现登陆SQL注入问题。经过一番折腾解决了这个问题,现记录如下:

    一、问题描述 

    const crypto = require('crypto');
    const conn = require('../../libs/Conn');
    const mysql = require('mysql');
    
    module.exports = async function (params) {
        let hash = crypto.createHash('sha256');
        let login_name = params.login_name;
        let password = hash.update(params.password).digest('hex');
        let sql = `SELECT uf.* FROM user_file uf WHERE uf.login_name = '${login_name}' AND uf.password = '${password}' AND
                  uf.delete_sign = 1;
            `;
        let user = (await conn(sql)).shift();
        return user;
    };

    这样的方式很容易被人在动态参数中加入特殊字符产生sql注入,威胁数据库的安全。

    如果 login_name 输入'or'1'='1,SQL语句会变成  uf.login_name = '' or '1' = '1' AND uf.password = ' ' 

    也就是说不需要知道登录名,只要输密码就可以。


    二、解决方案

    如果对参数使用escape,就能将参数中的特殊字符进行转义,防止sql的注入。

    WHERE uf.login_name = `+ mysql.escape(login_name) +` AND uf.password = `+ mysql.escape(password) +` 

    三、拓展

       3.1 使用escape()对传入参数进行编码

    mysql.escape(param)

    connection.escape(param)

    pool.escape(param)

      3.2 escape()方法编码规则如下

       
        Numbers不进行转换;
        Booleans转换为true/false;
        Date对象转换为’YYYY-mm-dd HH:ii:ss’字符串;
        Buffers转换为hex字符串,如X’0fa5’;
        Strings进行安全转义;
        Arrays转换为列表,如[‘a’, ‘b’]会转换为’a’, ‘b’;
        多维数组转换为组列表,如[[‘a’, ‘b’], [‘c’, ‘d’]]会转换为’a’, ‘b’), (‘c’, ‘d’);
        Objects会转换为key=value键值对的形式。嵌套的对象转换为字符串;
        undefined/null会转换为NULL;
        MySQL不支持NaN/Infinity,并且会触发MySQL错误。

    参考:https://blog.csdn.net/lin_tuer/article/details/54809330

    展开全文
  • SQL注入问题及解决方法

    千次阅读 2019-04-01 19:31:51
      SQL注入是一个安全问题,因为应用程序使用拼接SQL的技术而成为hacker攻击后台的方式。下面就介绍一下3种SQL注入,及解决SQL注入的方法。 下面以登录的机制为例,进行SQL注入的讲解。 1,基于 1=1 总为真 ...
  • SQL注入问题及解决

    千次阅读 2017-10-13 17:27:40
    什么是SQL注入? 所谓SQL注入(sql inject),就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令...
  • 突然想到sql注入问题,举例:在某些安全系数不高的登陆网站我们输入特定字符组合就可以进行登陆,其实数据库中是没有这个账号和用户名的,这就是因为sql注入的漏洞 看了篇博客说的很好就转载了,附上连接: ...
  • 所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。 我们永远不要信任用户的输入,我们必须认定用户输入的数据都是不安全的,我们都...
  • mybatis解决sql注入问题

    千次阅读 2017-07-28 15:44:07
    sql注入大家都不陌生,是一种常见的攻击方式,攻击者在界面的表单信息或url上输入一些奇怪的sql片段,例如“or ‘1’=’1’”这样的语句,有可能入侵参数校验不足的应用程序。所以在我们的应用中需要做一些工作,来...
  • mybatis的sql注入问题

    千次阅读 2015-12-11 18:54:53
    sql注入大家都不陌生,是一种常见的攻击方式,攻击者在界面的表单信息或url上输入一些奇怪的sql片段,例如“or ‘1’=’1’”这样的语句,有可能入侵参数校验不足的应用程序。所以在我们的应用中需要做一些工作,来...
  • SQL注入问题总结

    千次阅读 2012-03-19 13:53:38
    一、SQL注入介绍 SQL注入就是将原本的SQL语句的逻辑结构改变,使得SQL语句的执行结果和原本开发者的意图不一样; 方法:在表单中将命令当作用户输入提交给程序; 二、SQL注入范例 这里我们根据用户...
  • 下面username后面的怎么解释,相当于什么sql语句 update user_info set password='1234' where username= ' ' or 1=1 or '1'='1 '
  • myBatis的SQL注入问题

    千次阅读 2015-05-30 22:03:29
    sqlMap中尽量不要使用$;$使用的是Statement...前者容易出现SQL注入之类的安全问题,所以ibatis推荐使用#。 1、 正确使用$示例:ORDER BY $sortFieldName$ $sortType$,当参数是数据库字段名时这样使用是合适的
  • sql注入问题解决——PrepareStatement

    千次阅读 2018-01-16 23:57:36
    SQL注入攻击 -- 早年登录逻辑,就是把用户在表单中输入的用户名和密码 带入如下sql语句. 如果查询出结果,那么 认为登录成功. SELECT * FROM USER WHERE NAME='xxxx' AND PASSWORD='xxx'; -- sql注入: 请...
  • ibatis解决sql注入问题

    万次阅读 2012-05-28 23:11:11
    对于ibaits参数引用可以使用#和$两种写法,其中#写法会采用预编译方式,将转义交给了数据库,不会出现注入问题;如果采用$写法,则相当于拼接字符串,会出现注入问题。 例如,如果属性值为“' or '1'='1 ”,采用#...
  • 什么是sql注入 我们写一个登录的界面,把密码设为fdsa和1,代码如下 select * from tbl_user where username = 'fdsafds' and password = 'fdsa' or '1'='1'; 当我们输入 用户名:fdsafds 密码:fdsa' or '1'='1 ...
  • ibatis解决sql注入问题 .

    千次阅读 2012-12-02 13:50:08
    最近看看了SQL注入问题,这篇文章解决了ibatis如何防sql注入攻击,值得参考,转自http://blog.csdn.net/scorpio3k/article/details/7610973     对于ibaits参数引用可以使用#和$两种写法,其中#写法会采用预...
  • 近期刚做完的restful接口项目用安全软件扫描后,出现blind sql inject高危漏洞,查看,程序里已经使用了PreparedStatement预编译sql,却仍不好使,找不出原因,最后不得已,自定义了一个sql注入拦截器,对含有非法...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 243,719
精华内容 97,487
关键字:

sql注入问题