访问MySQL的客户端应用程序应该使用以下准则,以避免错误地解释外部数据或暴露敏感信息。
访问MySQL的应用程序不应该信任用户输入的任何数据,因为用户可能会在Web表单、url或您构建的任何应用程序中输入特殊或转义字符序列来欺骗您的代码。如果用户试图通过输入以下内容来执行SQL注入,请确保您的应用程序保持安全
;删除mysql数据库
变成一种形式。这是一个极端的例子,但是如果您没有做好准备,黑客使用类似的技术可能会导致大规模的安全泄漏和数据丢失。一个常见的错误是只保护字符串数据值。记住还要检查数字数据。如果应用程序生成查询,例如
从表中查询ID=234的数据
当用户输入该值时234
,用户可输入该值234或1=1
使应用程序生成查询从表中选择ID=234或1=1的*
.结果,服务器检索表中的每一行。这会暴露每一行,并导致过多的服务器负载。防止这类攻击的最简单方法是在数值常量周围使用单引号:从ID='234'的表中查询
.如果用户输入额外的信息,这些信息都将成为字符串的一部分。在数值上下文中,MySQL自动将这个字符串转换为一个数字,并从它中剥离任何尾随的非数字字符。有时人们认为,如果数据库只包含公开可用的数据,则不需要对其进行保护。这是不正确的。即使允许显示数据库中的任何行,您仍然应该防止拒绝服务攻击(例如,那些基于上一段中的技术导致服务器浪费资源的攻击)。否则,您的服务器将对合法用户失去响应。
检查表:
启用严格SQL模式,告诉服务器对它接受的数据值有更严格的限制。看到
尝试输入单引号和双引号(
'
而且"
)。如果你得到任何类型的MySQL错误,立即调查这个问题。尝试通过添加来修改动态url
% 22
("
),% 23
(#
),% 27
('
)给他们。尝试使用前面示例中显示的字符将动态url中的数据类型从数字修改为字符类型。您的应用程序应该能够安全抵御这些和类似的攻击。
尝试在数值字段中输入字符、空格和特殊符号,而不是数字。应用程序应该在将它们传递给MySQL之前删除它们,否则会产生错误。向MySQL传递未经检查的值是非常危险的!
在将数据传递给MySQL之前检查数据的大小。
让应用程序使用不同于用于管理目的的用户名连接到数据库。不要给应用程序任何它们不需要的访问特权。
许多应用程序编程接口提供了转义数据值中的特殊字符的方法。如果使用得当,这将防止应用程序用户输入的值导致应用程序生成的语句具有与您预期不同的效果:
MySQL SQL语句:使用SQL准备语句,仅通过占位符接受数据值;看到
MySQL C API:使用
mysql_real_escape_string_quote ()
API调用。或者,使用C API预处理语句接口,仅通过占位符接受数据值;看到C API预处理语句接口.MySQL++:使用
逃避
而且报价
查询流的修饰符。PHP:使用
mysqli
或pdo_mysql
扩展,而不是旧的ext / mysql
扩展。首选API支持改进的MySQL身份验证协议和密码,以及带有占位符的准备语句。另请参阅选择API.如果年龄较大
ext / mysql
扩展名必须使用,然后用于转义使用mysql_real_escape_string_quote ()
功能与非功能mysql_escape_string ()
或addslashes ()
因为只有mysql_real_escape_string_quote ()
是字符集感知的;其他函数可以”绕过”当使用(无效)多字节字符集时。Perl DBI:使用占位符或
报价()
方法。Ruby DBI:使用占位符或
报价()
方法。Java JDBC:使用
PreparedStatement
对象和占位符。
其他编程接口可能具有类似的功能。
应用程序有责任拦截由于在MySQL数据库服务器上执行SQL语句而发生的错误,并适当地处理它们。
MySQL错误中返回的信息不是免费的,因为这些信息是使用应用程序调试MySQL的关键。例如,调试一个常见的10路连接几乎是不可能的选择
语句,而不提供有关问题涉及哪些数据库、表和其他对象的信息。因此,MySQL错误有时必然包含对这些对象名称的引用。
当应用程序从MySQL接收到这样的错误时,一个简单但不安全的方法是拦截它并逐字显示给客户端。但是,显示错误信息是一种已知的应用程序漏洞类型(cwe - 209),应用程序开发人员必须确保应用程序没有此漏洞。
例如,一个显示这样消息的应用程序向客户端暴露了数据库名和表名,这是客户端可能试图利用的信息:
ERROR 1146 (42S02):表mydb。Mytable '不存在
相反,当应用程序从MySQL接收到此类错误时,它的正确行为是将适当的信息(包括错误信息)记录到只有可信人员才能访问的安全审计位置。应用程序可以返回一些更通用的内容,例如”内部错误”对用户。