mysql 之sql注入详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql 之sql注入详解相关的知识,希望对你有一定的参考价值。

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 语句。所以归根到底

摘自MySQLDBA修炼之道

本文出自 “大李子” 博客,谢绝转载!

以上是关于mysql 之sql注入详解的主要内容,如果未能解决你的问题,请参考以下文章

SQL注入详解之FILES注入!

sql注入详解

详解基于MSSQL “order by”语句报错的SQL注入技术

Web安全黑铁到传说四.常见漏洞攻防之SQL注入基础详解(权限提升绕过技巧注入技巧)

SQL注入之mysql显错注入

mysql 手注入之information_schema数据库详解