设为首页 收藏本站
云服务器等爆品抢先购,低至4.2元/月
查看: 370|回复: 0

[经验分享] mysql 之sql注入详解

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2017-8-18 10:21:06 | 显示全部楼层 |阅读模式
SQL 注入( SQL Injection )攻击是发生在应用程序中的数据库层的安全漏洞。简而言之,是在输入的字符串之中注入 SQL 语句,如果在设计不良的程序中忽略了检查,那么这些注入进去的 SQL 语句就会被数据库服务器误认为是正常的 SQL 语句而运行,攻击者就可以执行计划外的命令或访问未被授权的数据。 SQL 注入已经成为互联网世界 Web 应用程序的最大风险。我们有必要从开发、测试、上线各个环节对其进行防范。以下将介绍 SQL 注入的原理及如何预防 SQL 注入。
SQL 注入的原理有如下 4 点
1 )拼接恶意查询。 SQL 命令可查询、插入、更新、删除数据,以分号字符分隔不同的命令。
例如:
select * from users where user_id = $user_id
user_id 是传入的参数,如果传入了 “1234;delete from users” ,那么最终的查询语句会变为:
select * from users where user_id = 1234; delete from users
如上语句如果执行,则会删除 user 表的数据。
2 )利用注释执行非法命令。 SQL 命令中,可以插入注释。
例如:
select count(*) as 'num' from game_score where game_id=24411 and platform_id=11 and version=$version and session_id =
sessid='d7a157-0f-48b6-98-c35592'
如果 version 包含了恶意的字符串 “'-1'OR 3 AND SLEEP(500)--” ,那么最终查询语句会变成下面这个样子:
select count(*) as 'num' from game_score where game_id=24411 and platform_id=11 and version='-1' OR 3 AND SLEEP(500)-- '
and session_id = sessid='d7a157-0f-48b6-98-c35592'
以上恶意查询只是想耗尽系统资源, SLEEP(500) 将导致 SQL 一直运行,如果添加了修改、删除数据的恶意指令,将会造成
更大的破坏。
3 ) SQL 命令对于传入的字符串参数是用单引号引起来的。如果字符串本身包含单引号而没有被处理,则可能会篡改原本
的 SQL 语法的作用。
例如:
select * from user_name where user_name = $user_name
如果 user_name 传入的是 G'chen ,那么最终的查询语句会变成这样:
select * from user_name where user_name ='G'chen'
以上语句将会出错,这样的语句风险比较小,因为语法错误的 SQL 语句不会被执行。但也可能恶意产生的 SQL 语句,没有
任何语法错误,并且以一种你不期望的方式运行。
4 )添加一些额外的条件为真值表达式,改变执行行为。
例如:
update users set userpass=SHA2('$userpass') where user_id=$user_id;
如果 user_id 被传入恶意的字符串 “1234 OR TRUE” ,最终的 SQL 语句会变成下面这样:
update users set userpass=SHA2('123456') where user_id=1234 OR TRUE;
这将更改所有用户的密码。
下面是避免 SQL 注入的一些方法。
( 1 )过滤输入内容,校验字符串
应该在将数据提交到数据库之前,就把用户输入中的不合法字符剔除掉。可以使用编程语言提供的处理函数,如 PHP 的
mysql_real_escape_string() 来剔除,或者定义自己的处理函数进行过滤,还可以使用正则表达式匹配安全的字符串。
如果值属于特定的类型或有约定的格式,那么在拼接 SQL 语句之前就要进行校验,验证其的有效性。比如对于某个传入的
值,如果可以确定是整型,那么我们要判断下它是否为整型,不仅在浏览器端(客户端),而且在服务器端也需要进行验证。
( 2 )参数化查询
参数化查询目前已被视作是最有效的预防 SQL 注入攻击的方法。不同于在 SQL 语句中插入动态内容,查询参数的做法是在
准备查询语句的时候,就在对应参数的地方使用参数占位符。然后,在执行这个预先准备好的查询时提供一个参数。
在使用参数化查询的情况下,数据库服务器不会将参数的内容视为 SQL 指令的一部分来进行处理,而是在数据库完成 SQL
指令的编译之后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。
可以使用 MySQLi 扩展或 pdo 扩展来绑定参数实现参数化查询。
如下是一个使用 MySQLi 扩展绑定参数的示例。
<html>
<head>
<title> test parameter query </title>
</head>
<body>
<?php
$host="127.0.0.1";
$port=3306;
$socket="";
$user="garychen";
$password="garychen";
$dbname="employees";
$con = new mysqli($host, $user, $password, $dbname, $port, $socket)
or die ('Could not connect to the database server' . mysqli_connect_error());
echo 'connect to employees database successfully';
echo "<br />";
echo "select departments table using parameter";
echo "<br />";
$query = "select * from departments where dept_name = ?";
if ($stmt = $con->prepare($query)) {
$stmt->bind_param("s",$depname);
$depname="Finance";
$stmt->execute();
$stmt->bind_result($field1, $field2);
while ($stmt->fetch()) {
printf("%s, %s\n", $field1, $field2);
echo "<br />";
}
$stmt->close();
}
$con->close();
?>
</body>
</html>
上例首先是预处理语句 if($stmt=$con->prepare($query)) ,然后绑定参数使用 bind_param() 方法,该方法的语法格式如下所示。
bool mysqli_stmt::bind_param ( string $types , mixed &$var1 [, mixed &$... ] )
其中, types 指定绑定参数的类型,包含了一个或多个字符。 I 代表整型, D 代表双精度, S 代表字符串, B 代表 BLOB 类型,
本例中是 S 。
但是绑定参数也有如下一些限制。
· 不能让占位符 “?” 代替一组值,例如:
SELECT * FROM departments WHERE userid IN ( ? );
· 不能让占位符 “?” 代替数据表名或列名,例如:
SELECT * FROM departments ORDER BY ?;
· 不能让占位符 “?” 代替 SQL 关键字,例如:
SELECT * FROM departments ORDER BY dept_no ?;
对于 Java 、 JSP 开发的应用,也可以使用预处理语句加绑定参数的方式来避免 SQL 注入。
( 3 )安全测试、安全审计
除了开发规范,还需要流程、机制和合适的工具来确保代码的安全。我们应该在开发过程中对代码进行审查,在测试环节
使用工具进行扫描,上线后定期扫描安全漏洞。通过多个环节的检查,一般是可以避免 SQL 注入的。
有些人认为存储过程可以避免 SQL 注入,存储过程在传统行业里用得比较多,对于权限的控制是有一定用处的,但如果存
储过程用到了动态查询,拼接 SQL ,那就一样会存在安全隐患。一些编程框架对于写出更安全的代码也有一定的帮助,因为它
提供了一些处理字符串的函数和使用查询参数的方法,但同样,你仍然可以编写出不安全的 SQL 语句。所以归根到底


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-403096-1-1.html 上篇帖子: mysqlbinlog根据时间点提取SQL 下篇帖子: mysql设置character set为utf8
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表