一般安全问题
本节描述了需要注意的一般安全问题,以及如何使MySQL安装更安全以防止受到攻击或滥用。有关MySQL用于设置用户帐户和检查数据库访问权限的访问控制系统的详细信息,
安全准则
在连接到Internet的计算机上使用MySQL的任何人都应阅读本节,以避免最常见的安全错误。
在讨论安全性时,有必要考虑完全保护整个服务器主机(不仅仅是MySQL服务器)免受所有类型的适用攻击:窃听,更改,播放和拒绝服务。在此,我们不涵盖可用性和容错性的所有方面。
MySQL对所有连接,查询和用户可以尝试执行的其他操作使用基于访问控制列表(ACL)的安全性。MySQL客户端和服务器之间还支持SSL加密的连接。这里讨论的许多概念根本不是特定于MySQL的。相同的基本思想适用于几乎所有应用程序。
运行MySQL时,请遵循以下准则:
- 永远不要让任何人(MySQL
root
帐户除外)访问系统数据库中的user
表mysql
!这很关键。 了解MySQL访问权限系统的工作原理(请参见“访问控制和帐户管理”)。使用
GRANT
ndREVOKE
语句控制对MySQL的访问。不要授予不必要的特权。切勿向所有主机授予特权。清单:
- 尝试
mysql -u root
。如果您能够成功连接到服务器而无需输入密码,则任何人都可以以root
具有完全特权的MySQL 用户身份连接到MySQL服务器!参见MySQL安装说明,特别注意有关设置root
密码的信息。请参见“保护初始MySQL帐户”。 - 使用该
SHOW GRANTS
语句检查哪些帐户有权访问什么。然后,使用该REVOKE
语句删除那些不必要的特权。
- 尝试
不要在数据库中存储明文密码。如果您的计算机受到威胁,入侵者可以获取完整的密码列表并使用它们。而是使用
SHA2()
或其他单向哈希函数并存储哈希值。为防止使用彩虹表恢复密码,请不要在普通密码上使用这些功能;而是选择一些字符串作为盐,并使用hash(hash(password) + salt)值。
- 不要从词典中选择密码。存在特殊程序来破解密码。甚至“ xfish98 ”之类的密码也非常糟糕。更好的是“ duag98 ”,它包含相同的单词“ fish ”,但在标准QWERTY键盘的左侧键入了一个键。另一种方法是使用从句子中每个单词的开头字符获取的密码(例如,“四分制和七年前”得出的密码为“ Fsasy ”)。密码很容易记住和输入,但是对于不知道该句子的人来说很难猜出来。在这种情况下,您可以用数字代替数字单词以获得短语“ 4 score and 7 years ago ”,从而产生密码“ 4sa7y ”,这更加难以猜测。
投资防火墙。这可以保护您免受任何软件中至少50%的所有类型的利用。将MySQL放在防火墙后面或非军事区(DMZ)中。
清单:
尝试使用诸如的工具从Internet扫描端口
nmap
。MySQL默认使用端口3306。无法从不受信任的主机访问此端口。作为检查MySQL端口是否打开的简单方法,请从某些远程计算机尝试以下命令,其中server_host
是运行MySQL服务器的主机的主机名或IP地址:shell>
telnet server_host 3306如果telnet挂起或连接被拒绝,则端口被阻止,这就是您想要的状态。如果获得连接和一些垃圾字符,则该端口是打开的,并且应该在防火墙或路由器上关闭该端口,除非您确实有充分的理由将该端口保持打开状态。
- 访问MySQL的应用程序不应信任用户输入的任何数据,而应使用适当的防御性编程技术来编写。请参见“客户端编程安全性准则”。
- 不要通过Internet传输纯数据(未加密)。有时间和能力将其拦截并用于自己目的的每个人都可以访问此信息。而是使用加密协议,例如SSL或SSH。MySQL支持内部SSL连接。另一种技术是使用SSH端口转发创建用于通信的加密(和压缩)隧道。
了解如何使用tcpdump和字符串实用程序。在大多数情况下,您可以通过发出以下命令来检查MySQL数据流是否未加密:
shell>
tcpdump -l -i eth0 -w - src or dst port 3306 | strings这可以在Linux下工作,并且应该可以在其他系统上进行一些小的修改。
警告
如果看不到明文数据,则并不总是意味着该信息实际上是加密的。如果需要高安全性,请咨询安全专家。
保持密码安全
密码在MySQL中的几种情况下都会出现。以下各节提供了一些准则,使最终用户和管理员可以保护这些密码的安全并避免暴露它们。此外,该validate_password
插件可用于在可接受的密码上实施策略。最终用户密码安全准则
MySQL用户应遵循以下准则来保护密码安全。
当您运行客户端程序以连接到MySQL服务器时,建议您以使其他用户无法发现的方式指定密码。此处列出了您在运行客户端程序时可以用来指定密码的方法,以及每种方法的风险评估。简而言之,最安全的方法是让客户端程序提示输入密码,或在受适当保护的选项文件中指定密码。
- 使用mysql_config_editor实用程序,该实用程序使您可以将身份验证凭据存储在名为的加密登录路径文件中
.mylogin.cnf
。稍后,MySQL客户端程序可以读取该文件,以获得用于连接到MySQL Server的身份验证凭据。请参见“mysql_config_editor-MySQL配置实用程序”。 在命令行上使用或选项。例如:
--password=password
-ppassword
shell>
mysql -u francis -pfrank db_name警告
这很方便,但是没有安全感。在某些系统上,您的密码对系统状态程序(例如ps)可见,其他用户可能会调用该密码来显示命令行。MySQL客户端通常在初始化序列期间用零覆盖命令行密码参数。但是,仍然存在一个短暂的时间间隔,在此间隔内该值是可见的。同样,在某些系统上,这种覆盖策略无效,并且ps仍然可以看到密码。(SystemV Unix系统以及其他系统可能会遇到此问题。)
如果将您的操作环境设置为在终端窗口的标题栏中显示当前命令,则即使该命令在窗口内容区域中滚动到视图之外,只要该命令正在运行,密码仍然保持可见。
在命令行上使用
--password
或-p
选项,未指定密码值。在这种情况下,客户端程序以交互方式请求密码:shell>
mysql -u francis -p db_name Enter password: ********该
*
字符显示在您输入密码。输入密码时不会显示。这种方式输入的密码比在命令行上指定密码更安全,因为其他用户看不到该密码。但是,这种输入密码的方法仅适用于以交互方式运行的程序。如果要从非交互运行的脚本中调用客户端,则没有机会从键盘输入密码。在某些系统上,您甚至可能发现脚本的第一行被读取并(错误地)解释为您的密码。
将密码存储在选项文件中。例如,在Unix上,您可以在主目录中文件的
[client]
部分中列出密码.my.cnf
:[client] password=password
为了确保密码安全,除了您自己之外,任何人都不能访问该文件。为此,请将文件访问模式设置为
400
或600
。例如:shell>
chmod 600 .my.cnf要从命令行命名包含密码的特定选项文件,请使用选项,其中是文件的完整路径名。例如:
--defaults-file=file_name
file_name
shell>
mysql --defaults-file=/home/francis/mysql-opts“使用选项文件”中,更详细地讨论了选项文件。
在Unix上,mysql客户端将已执行语句的记录写入历史文件(请参见“ mysql客户端日志”)。默认情况下,该文件被命名.mysql_history
并在您的主目录中创建。密码可以在诸如CREATE USER
和的SQL语句中以纯文本形式编写ALTER USER
,因此,如果使用这些语句,它们将记录在历史记录文件中。为确保此文件的安全,请使用限制性访问模式,与前面针对该.my.cnf
文件所述的方式相同。
如果将命令解释器配置为保留历史记录,则保存命令的任何文件都将包含在命令行上输入的MySQL密码。例如,bash使用~/.bash_history
。任何此类文件都应具有限制性访问模式。
管理员密码安全准则
数据库管理员应使用以下准则来保护密码的安全。
MySQL将用户帐户的密码存储在mysql.user
系统表中。切勿将任何非管理帐户授予对该表的访问权限。
帐户密码可以过期,以便用户必须重置它们。请参见“帐户密码管理”和“服务器处理过期密码”。
该validate_password
插件可用于对可接受的密码实施策略。请参见“密码验证组件”。
有权修改插件目录(plugin_dir
系统变量的值)或my.cnf
指定插件目录位置的文件的用户可以替换插件并修改插件提供的功能,包括身份验证插件。
应该保护可能写入密码的文件(例如日志文件)。
密码和登录
口令可以写在SQL语句,如纯文本CREATE USER
,GRANT
和SET PASSWORD
。如果此类语句由MySQL服务器以书面形式记录,则其中的密码对于任何有权访问该日志的人都是可见的。
语句记录避免为以下语句将密码写为明文:
CREATE USER ...IDENTIFIED BY ...ALTER USER ...IDENTIFIED BY ...SET PASSWORD ...SLAVE START ...PASSWORD = ...CREATE SERVER ...OPTIONS (...PASSWORD ...)ALTER SERVER ...OPTIONS (...PASSWORD ...)
这些语句中的密码将被重写,以使它们不会真正出现在写入常规查询日志,慢速查询日志和二进制日志的语句文本中。重写不适用于其他语句。具体而言,INSERT
或UPDATE
对语句mysql.user
引用文字密码系统表中记录为是,那么你应该避免这样的语句。(无论如何,不建议直接修改授予表。)
对于常规查询日志,可以通过使用--log-raw
选项启动服务器来抑制密码重写。出于安全原因,不建议将此选项用于生产。出于诊断目的,参见服务器接收到的语句的确切文本可能会很有用。
默认情况下,审核日志插件生成的审核日志文件的内容未加密,并且可能包含敏感信息,例如SQL语句的文本。出于安全原因,应将审核日志文件写入只有MySQL服务器和出于正当理由参见日志的用户才能访问的目录。请参见“ MySQL企业审核安全注意事项”。
如果安装了查询重写插件,则服务器所接收的语句可能会被重写(请参阅查询重写插件)。在这种情况下,该--log-raw
选项将影响语句记录,如下所示:
- 如果不使用
--log-raw
,服务器将记录查询重写插件返回的语句。这可能与收到的声明有所不同。 - 使用
--log-raw
,服务器记录收到的原始语句。
密码重写的含义是,无法解析(例如由于语法错误)的语句不会写入通用查询日志,因为无法知道它们没有密码。需要记录所有语句(包括错误语句)的用例应使用该--log-raw
选项,请牢记这也绕过了密码重写。
仅当需要纯文本密码时才进行密码重写。对于具有期望密码哈希值的语法的语句,不会进行重写。如果错误地为这种语法提供了纯文本密码,则将按给定的密码记录密码,而不进行重写。
要防止日志文件遭受不必要的泄露,请在限制访问服务器和数据库管理员的目录中找到它们。如果服务器登录到mysql
数据库中的表,则仅向数据库管理员授予对这些表的访问权限。
复制从属服务器将复制主服务器的密码存储在主服务器信息存储库中,该信息默认情况下是mysql
数据库中名为的表slave_master_info
。现在不建议在数据目录中使用主信息存储库中的文件,但是仍然可以使用(请参见“复制中继和状态日志”)。确保仅数据库管理员可以访问主信息存储库。将密码存储在主信息存储库中的另一种方法是使用该START SLAVE
语句指定用于连接主数据库的凭据。
使用受限访问模式可以保护包括日志表或包含密码的日志文件的数据库备份。
使MySQL安全防范攻击者
连接到MySQL服务器时,应使用密码。密码不会以明文形式通过连接传输。
所有其他信息均以文本形式传输,任何能够参见连接的人都可以阅读。如果客户端和服务器之间的连接通过不受信任的网络,并且您对此感到担心,则可以使用压缩协议使通信更难以解密。您还可以使用MySQL的内部SSL支持来使连接更加安全。请参见“使用加密的连接”。或者,使用SSH获取MySQL服务器和MySQL客户端之间的加密TCP / IP连接。您可以在http://www.openssh.org/上找到一个开源SSH客户端,并在下面可以找到开源SSH客户端和商业SSH客户端的比较。 http://en.wikipedia.org/wiki/Comparison_of_SSH_clients。
为了使MySQL系统安全,您应该强烈考虑以下建议:
要求所有MySQL帐户都具有密码。客户程序不一定知道运行它的人的身份。对于客户端/服务器应用程序,用户通常可以为客户端程序指定任何用户名。例如,任何人都可以使用MySQL的程序为任何其他人简单地调用它作为连接,如果没有密码。如果所有帐户都具有密码,则使用其他用户的帐户进行连接将变得更加困难。
mysql -u other_userdb_name
other_user
有关设置密码的方法的讨论,请参见“帐户密码管理”。
- 确保数据库目录中唯一具有读取或写入特权的Unix用户帐户是用于运行mysqld的帐户。
切勿以Unix
root
用户身份运行MySQL服务器。这是非常危险的,因为任何具有FILE
特权的用户都可以使服务器创建文件root
(例如~root/.bashrc
)。为了避免这种情况,除非使用该选项明确指定,否则mysqld拒绝运行。root
--user=root
mysqld可以(并且应该)以普通,无特权的用户身份运行。您可以创建一个单独的Unix帐户,以
mysql
使一切变得更加安全。仅将此帐户用于管理MySQL。要以另一个Unix用户身份启动 mysqld,请在用于指定服务器选项的选项文件组中添加一个user
用于指定用户名的选项。例如:[mysqld]
my.cnf
[mysqld] user=mysql
无论您手动启动服务器还是使用mysqld_safe或mysql.server,它都会以指定用户身份启动服务器。有关更多详细信息,请参见“如何以普通用户身份运行MySQL”。
以非Unix用户身份运行mysqld
root
并不意味着您需要更改表中的root
用户名user
。MySQL帐户的用户名与Unix帐户的用户名无关。不要将
FILE
特权授予非管理用户。具有此特权的任何用户都可以使用mysqld守护程序的特权在文件系统中的任何位置写入文件。这包括服务器的数据目录,该目录包含实现特权表的文件。为了使FILE
-privilege操作更加安全,使用生成的文件SELECT ... INTO OUTFILE
不会覆盖现有文件,并且每个人都可以写入。该
FILE
特权还可以用于读取服务器可读的世界上可读的文件或Unix用户可以访问的任何文件。拥有此特权,您可以将任何文件读入数据库表。例如,可以使用LOAD DATA
加载/etc/passwd
到表中,然后将其显示为来滥用它SELECT
。要限制文件的读写位置,请将
secure_file_priv
系统设置为特定目录。请参见“服务器系统变量”。- 加密二进制日志文件和中继日志文件。加密有助于保护这些文件以及其中包含的潜在敏感数据,以防止外部攻击者滥用这些文件以及存储文件的操作系统用户未经授权的参见。通过将
binlog_encryption
系统变量设置为,可以在MySQL服务器上启用加密ON
。有关更多信息,请参见“加密二进制日志文件和中继日志文件”。 不要将
PROCESS
或SUPER
特权授予非管理用户。的输出中mysqladmin的processlist并SHOW PROCESSLIST
显示正在执行当前的任何陈述文字,所以谁被允许参见服务器进程列表可能能够参见其他用户发表声明,任何用户。mysqld为具有
CONNECTION_ADMIN
或SUPER
特权的用户保留了一个额外的连接,这样,root
即使所有正常连接都在使用中,MySQL用户也可以登录并检查服务器活动。该
SUPER
特权可用于终止客户端连接,通过更改系统变量的值来更改服务器操作以及控制复制服务器。- 不允许使用符号链接到表。(此功能可通过禁用
--skip-symbolic-links
选项。)如果您运行,这一点尤其重要的mysqld为root
,因为具有对服务器的数据目录的写访问,则任何人都可以在系统中删除任何文件!请参见“在Unix上为MyISAM表使用符号链接”。 - 应使用“存储的对象访问控制”中讨论的安全性准则来编写存储的程序和视图。
- 如果您不信任DNS,则应在授予表中使用IP地址而不是主机名。无论如何,您应该非常小心地使用包含通配符的主机名值创建授权表条目。
- 如果要限制单个帐户允许的连接数,可以通过
max_user_connections
在mysqld中设置变量来限制。该CREATE USER
和ALTER USER
语句也支持资源控制选项来限制服务器使用的允许的范围内的账户。请参见“ CREATE USER语句”和“ ALTER USER语句”。 - 如果插件目录可被服务器写入,则用户可能会使用将可执行代码写入目录中的文件
SELECT ... INTO DUMPFILE
。可以通过使plugin_dir
服务器只读或将secure_file_priv
目录设置为SELECT
可以安全进行写操作的目录来防止这种情况。
安全相关的mysqld选项和变量
下表显示了影响安全性的mysqld选项和系统变量。有关每一个的描述,请参见“服务器命令选项”和“服务器系统变量”。
表6.1安全选项和变量摘要
Name | Cmd-Line | Option File | System Var | Status Var | Var Scope | Dynamic |
---|---|---|---|---|---|---|
llow-suspicious-udfs | Yes | Yes | ||||
utomatic_sp_privileges | Yes | Yes | Yes | Global | Yes | |
chroot | Yes | Yes | ||||
local_infile | Yes | Yes | Yes | Global | Yes | |
safe-user-create | Yes | Yes | ||||
secure_file_priv | Yes | Yes | Yes | Global | No | |
skip-grant-tables | Yes | Yes | ||||
skip_name_resolve | Yes | Yes | Yes | Global | No | |
skip_networking | Yes | Yes | Yes | Global | No | |
skip_show_database | Yes | Yes | Yes | Global | No |
如何以普通用户身份运行MySQL
在Windows上,您可以使用普通用户帐户将服务器作为Windows服务运行。
在Linux上,对于使用MySQL存储库或RPM软件包执行的安装,MySQL服务器mysqld应该由本地mysql
操作系统用户启动。MySQL存储库中包含的初始化脚本不支持由另一个操作系统用户启动。
在Unix上(或Linux使用tar.gz
软件包执行安装),MySQL服务器mysqld可以由任何用户启动和运行。但是,root
出于安全原因,应避免以Unix 用户身份运行服务器。要将mysqld更改为以普通非特权Unix用户身份运行user_name
,必须执行以下操作:
- 如果服务器正在运行,请停止它(使用mysqladmin shutdown)。
更改数据库目录和文件,以使其
user_name
具有在其中读写文件的特权(您可能需要以Unixroot
用户身份进行此操作):shell>
chown -R user_name /path/to/mysql/datadir如果不执行此操作,则服务器以身份运行时将无法访问数据库或表
user_name
。如果MySQL数据目录中的目录或文件是符号链接,
chown -R
那么您可能不跟随符号链接。如果没有,您还需要跟随这些链接并更改它们指向的目录和文件。- 以用户身份启动服务器
user_name
。另一种选择是以Unix 用户身份启动mysqldroot
并使用该选项。mysqld启动,然后切换为以Unix用户身份运行,然后接受任何连接。--user=user_name
user_name
要在系统启动时自动以给定的用户身份启动服务器,请通过在服务器数据目录中的选项文件或选项文件组中添加
user
选项来指定用户名。例如:[mysqld]
/etc/my.cnf
my.cnf
[mysqld] user=user_name
如果您的Unix机器本身不受保护,则应root
在授权表中为MySQL 帐户分配密码。否则,该计算机上具有登录帐户的任何用户都可以运行带有选项的mysql客户端--user=root
并执行任何操作。(在任何情况下,最好将密码分配给MySQL帐户,但尤其是在服务器主机上存在其他登录帐户时,尤其如此。)请参见“保护初始MySQL帐户”。
LOAD DATA LOCAL的安全问题
该LOAD DATA
语句可以加载服务器主机上的文件,或者,如果LOCAL
指定了关键字,则可以加载客户端主机上的文件。
该LOCAL
版本存在两个潜在的安全问题LOAD DATA
:
- 因为
LOAD DATA LOCAL
是SQL语句,所以解析是在服务器端进行的,并且文件从客户端主机到服务器主机的传输是由MySQL服务器启动的,它将告诉客户端该语句中命名的文件。从理论上讲,打补丁的服务器可以告诉客户端程序传输服务器选择的文件,而不是语句中命名的文件。这样的服务器可以访问客户端用户具有读取访问权限的客户端主机上的任何文件。(打补丁的服务器实际上可以用文件传输请求回复任何语句,而不仅仅是LOAD DATA LOCAL
,因此更根本的问题是客户端不应连接到不受信任的服务器。) - 在客户端从Web服务器进行连接的Web环境中,用户可以
LOAD DATA LOCAL
用来读取Web服务器进程具有读取权限的任何文件(假设用户可以针对SQL Server运行任何语句)。在这种环境中,相对于MySQL服务器的客户端实际上是Web服务器,而不是由连接到Web服务器的用户运行的远程程序。
为避免连接到不受信任的服务器,客户端可以建立安全连接并通过使用--ssl-mode=VERIFY_IDENTITY
选项和适当的CA证书进行连接来验证服务器身份。
为避免出现LOAD DATA
问题,客户应避免使用LOCAL
。
为了使管理员和应用程序能够管理是否允许本地数据加载,LOCAL
功能的配置如下:
在服务器端:
- 所述
local_infile
系统变量控制服务器端LOCAL
的能力。根据local_infile
设置,服务器会拒绝或允许已LOCAL
在客户端启用的客户端加载本地数据。默认情况下local_infile
为禁用。 - 要明确地使服务器拒绝或允许
LOAD DATA LOCAL
语句(无论在构建时或运行时如何配置客户端程序和库),请在禁用或启用的情况下启动mysqldlocal_infile
。local_infile
也可以在运行时设置。
- 所述
在客户端:
该CMake的选项控制编译默认的MySQL客户端库的能力。因此,没有明确安排的客户端将根据MySQL构建时指定的设置禁用或启用功能。
ENABLED_LOCAL_INFILE
LOCAL
LOCAL
ENABLED_LOCAL_INFILE
默认情况下,MySQL二进制发行版中的客户端库在
ENABLED_LOCAL_INFILE
禁用的情况下进行编译。如果从源代码编译MySQL,请ENABLED_LOCAL_INFILE
根据未进行显式安排的客户端应LOCAL
禁用还是启用功能,将其配置为禁用或启用。- 对于使用C API的客户端程序,本地数据加载功能由编译到MySQL客户端库中的默认值决定。要显式启用或禁用它,请调用
mysql_options()
以禁用或启用该MYSQL_OPT_LOCAL_INFILE
选项。请参见“ mysql_options()”。 - 对于mysql客户端,本地数据加载功能由编译到MySQL客户端库中的默认值决定。要明确禁用或启用它,请使用
--local-infile=0
或--local-infile[=1]
选项。 - 对于mysqlimport客户端,默认情况下不使用本地数据加载。要明确禁用或启用它,请使用
--local=0
或--local[=1]
选项。 如果
LOAD DATA LOCAL
在Perl脚本或其他[client]
从选项文件中读取该组的程序中使用,则可以向该组添加local-infile
选项设置。为了防止不理解该选项的程序出现问题,请使用loose-
前缀指定它:[client] loose-local-infile=0
要么:
[client] loose-local-infile=1
- 在所有情况下,
LOCAL
客户端成功使用加载操作还需要服务器允许它。
如果LOCAL
禁用了功能,则在服务器或客户端上,尝试发出LOAD DATA LOCAL
语句的客户端都会收到以下错误消息:
ERROR 3950 (42000): Loading local data is disabled; this must be enabled on both the client and server side
客户端编程安全性准则
访问MySQL的应用程序不应信任用户输入的任何数据,用户可以尝试通过在Web表单,URL或您构建的任何应用程序中输入特殊或转义的字符序列来欺骗您的代码。如果用户输入,请确保您的应用程序保持安全; DROP DATABASE mysql;
。这是一个极端的例子,但是如果您不为黑客准备使用类似的技术,则可能由于黑客使用类似的技术而导致大量的安全漏洞和数据丢失。
一个常见的错误是仅保护字符串数据值。切记还要检查数字数据。如果应用程序生成查询(例如,SELECT * FROM table WHERE
(当用户输入值时)234
,则用户可以输入值234 OR 1=1
以使应用程序生成查询SELECT * FROM table WHERE OR 1=1
。结果,服务器检索表中的每一行。这会暴露每一行,并导致过多的服务器负载。防止此类攻击的最简单方法是在数字常量周围使用单引号:SELECT * FROM table WHERE
。如果用户输入其他信息,则所有信息都将成为字符串的一部分。在数字上下文中,MySQL自动将此字符串转换为数字,并从中去除所有尾随的非数字字符。
有时人们认为,如果数据库仅包含公共可用数据,则无需对其进行保护。这是不正确的。即使允许在数据库中显示任何行,您仍应防止拒绝服务攻击(例如,基于上段技术的那些导致服务器浪费资源的攻击)。否则,您的服务器将无法响应合法用户。
清单:
- 启用严格的SQL模式,以告诉服务器对其接收的数据值有更多的限制。请参见“服务器SQL模式”。
- 尝试在所有Web表单中输入单引号和双引号(
'
和"
)。如果您遇到任何MySQL错误,请立即调查问题。 - 尝试通过在其上添加
%22
("
),%23
(#
)和%27
('
)来修改动态URL 。 - 尝试使用前面示例中显示的字符,将动态URL中的数据类型从数字类型修改为字符类型。您的应用程序应该对这些和类似的攻击是安全的。
- 尝试在数字字段中输入字符,空格和特殊符号,而不要输入数字。您的应用程序应在将它们传递给MySQL之前将其删除,否则会产生错误。将未经检查的值传递给MySQL非常危险!
- 在将数据传递给MySQL之前,请检查其大小。
- 让您的应用程序使用与用于管理目的的用户名不同的用户名连接到数据库。不要给您的应用程序不需要的访问权限。
许多应用程序编程接口提供了一种在数据值中转义特殊字符的方法。如果使用得当,这可以防止应用程序用户输入导致应用程序生成效果与您预期不同的语句的值:
- MySQL C API:使用
mysql_real_escape_string_quote()
API调用。 - MySQL + +:对查询流使用
escape
ndquote
修饰符。 PHP:使用
mysqli
或pdo_mysql
扩展名,而不使用旧的ext/mysql
扩展名。首选的API支持改进的MySQL身份验证协议和密码,以及带占位符的预备语句。另请参阅选择API。如果
ext/mysql
必须使用较旧的扩展名,则为了转义而使用该mysql_real_escape_string_quote()
功能,而不要使用此功能,mysql_escape_string()
或者ddslashes()
因为仅mysql_real_escape_string_quote()
识别字符集而使用;使用(无效)多字节字符集时,可以“绕过”其他功能。- Perl DBI:使用占位符或
quote()
方法。 - Ruby DBI:使用占位符或
quote()
方法。 - Java JDBC:使用
PreparedStatement
对象和占位符。
其他编程接口可能具有类似的功能。