保护无辜的MySQL的SQL注入
作者:
安萨里阿什法克

评论者:
等级:
5
十月 19, 2012
上次修改:一月 18, 2013

总结:

详细指导如何预防注射的MySQL在PHP. 安全编码规则和功能,以防止SQL注入.

介绍

 

如何保护您的无辜,这是一个简短的指南 MySQL的 数据库 SQL注入 攻击.
 

什么是SQL注入?

 

正如它的名字所暗示的, SQL注入 当用户发生注入到您的应用程序中的SQL语句.
 
这是如何发生?
 
假设我们有一个简单的登录表单,需要一个用户名和密码, 并针对数据库进行验证. 如果用户名和密码进行验证, 用户登录到系统.
 

这可能是这个样子的代码:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?PHP
// 从POST请求获得用户名和密码
$USER_NAME = $彦博[ '用户名' ];
$密码  = $彦博[ “密码” ];

$询问 = “SELECT名字, 姓氏, 从USERS_TABLE其中username ='ACCOUNT_NUMBER$USER_NAME及密码='$密码“ ";

$导致 = 请求mysql_query( $询问 );

// 检查如果MySQL发现了什么, 并获得成功的记录,如果它
如果 ( mysql_num_rows( $导致 ) > 0 ) {
    $数据 = mysql_fetch_assoc( $导致 );
    呼应 '欢迎' . $用户 . “!“;
    呼应 “你的帐户号码是: “ . $数据[ 'ACCOUNT_NUMBER' ] . ;
} //打印出来的errorr消息
其他 {
    呼应 “用户名或密码无效! 请再试一次!“;
}
?>

 

上面的脚本能正常工作,它可以让真正的用户输入他们的用户名和密码,看到自己的银行账户号码.
 

假设我进入 “的演示” 我的用户名, 和 “demopass” 我的密码, 然后传递到MySQL的SQL查询看起来是这样的:
 

1
选择 FIRST_NAME, 姓氏, ACCOUNT_NUMBER USERS_TABLE WHERE 用户名 = “演示” 密码 = 'Demopass' ;

 

如果被成功验证,在数据库中输入数据, 那么我们就会被记录到系统中,我们将介绍其他账号,我们将无法获得对系统的访问,我们将提出一个错误消息 “用户名或密码无效! 请再试一次!
 

的问题时,恶意用户输入其他字符,是为了终止SQL语句.
 

让我们假设一个用户试图登录用户名 dem'o 和密码作为 demopass.
 

现在, 让我们看看如何在SQL语句看起来像.
 

1
选择 FIRST_NAME, 姓氏, ACCOUNT_NUMBER USERS_TABLE WHERE 用户名 = ''及密码='demopass“ ;

 

当MySQL执行语句, 将只会 “” 作为用户名,当遇到另一个 ‘“, 然后它把 ‘‘ 作为一个SQL命令,它会抛出的错误消息,因为它不承认 ‘‘ 作为一个有效的SQL命令.
 
错误 1064 (42000): 你有一个错误的SQL语法; 'O附近使用正确的语法检查手册,相当于你的MySQL服务器版本’ 和密码=”demopass”; ” 行 1
 

真棒. 上述错误信息,指出有一些在SQL语法错误. 如果 魔术引号 已启用, 那么我们可能没有得到上面的错误讯息.
 

现在, 让我们来看看,如果恶意用户输入用户名作为会发生什么 (‘ OR'1'='1) 和密码作为 “demopass“.

SQL查询看起来像这样:

1
选择 FIRST_NAME, 姓氏, ACCOUNT_NUMBER USERS_TABLE WHERE 用户名 = '1'='1' 密码 = 'Demopass' ;

 

什么是上面的SQL查询的意思? 它告诉MySQL找到所有行,用户名相同 “” (空白) 或 (1= 1) 和一个密码等于 “demopass“.
 

让我们来代表上面的SQL查询的详细逻辑上理解什么是其实是错误的SQL语句:
 

用户名= “” 或 “1= 1” 和密码= “demopass”
 

现在, 我们已经知道,1 = 1总是要为TRUE. 故, 用户将能够登录到系统,如果密码正确,用户名是错误的.
 

让我们来分析更糟糕的情况下使用不同的攻击字符串.
 

攻击字符串: ‘ OR 1 = 1–
 

请注意 (#) 用于 终止SQL语句. 让我们把攻击字符串中的SQL查询,看看最终的SQL语句将如何看.
 

现在, 我们假设攻击者甚至不知道密码.
 

1
选择 FIRST_NAME, 姓氏, ACCOUNT_NUMBER USERS_TABLE WHERE 用户名 = 1=1--'和密码='idonotknow' ;

 

看看SQL语句是MySQL的解释.
 

用户名= “” OR 1 = 1– 和密码= “idonotknow”
 

请注意: 在上述声明中. 因为我们知道, 是在SQL语句终止和 1= 1 总是如此, 其余的SQL查询语句终止后,将不会被执行.
 

故, 将返回表中的所有记录,用户将能够登录到系统. 攻击者将能够看到的第一条记录在数据库中的账号.
 

让我们帮助无辜的MySQL
 

魔术引号

 

魔术引号 是一个有争议的PHP脚本语言功能, 其中特殊字符准备被传递之前用反斜杠结束.
 

魔术引号 在新安装的默认启用 PHP3PHP4, 因为它们的工作是在幕后,不会立即明显, 开发人员可能不知道他们的存在和潜在的问题,他们可以引进.
 

我们将不得不打开 魔术引号php.ini中 在Web网站根目录的文件.
 

魔术引号如何帮助?

 

我们需要摆脱这些引号字符 ( 单引号和双引号, 以及反斜线).
这是通过将在他们面前的一个斜线.
 

So usename = dem'o 成为 DEM 'O , 和MySQL可以制定出与引号,因为它是 “保护” 由斜线.
 

让我们看看会发生什么时, 魔术引号 接通. 让我们来看看攻击者是如何影响与魔术引号.
 

1
选择 FIRST_NAME, 姓氏, ACCOUNT_NUMBER USERS_TABLE WHERE 用户名 = \“ OR 1 = 1 - ' 密码 = “Idonotknow” ;

 

该用户名被解释为: \’ OR 1 = 1–

这是一个完美的 转义SQL查询, 没有什么可以得到注入. magic_quotes_gpc的 逃脱我们的危险单引号. 故, 攻击者将不能够登录到系统.

与魔术引号的问题

 

魔术引号 只有前几个字符插入一个反斜杠, 而已. 这可以保护我们免受SQL注入共同的发病率只在某些特定情况下,只有像上面. 如果我们有 display_errors的开, 我们只是很高兴与您的数据库信息输出的攻击就在他的眼睛. 即使你不, 仍然是一个盲目的SQL注入和利用先进的SQL注入方式的可能性,有可能绕过 magic_quotes_gpc的 功能.
 
所以, 我们需要一种方法逃避数据,是不是蹩脚, 不容易字符集问题, 是不容易的魔育种削减报价.
 
十一月 2005 PHP核心开发人员考虑这些问题,决定 魔术引号 从PHP功能将被删除 6.
一旦 魔术引号 功能被撤回, 然后会出现一些重大问题.
 

SQL注入缓解
 

有很多的方法,以防止 MySQL的 注射内 PHP. 最常见的方法是使用功能,如 和addslashes()mysql_real_escape_string().
 

和addslashes()

 

和addslashes() 用一个反斜杠字符前,需要进行消毒,数据库查询将返回一个字符串. 这些字符是单引号 (‘ = ’) 双引号 (” = ”) 和空字节的作用 (%00 = \0).
 

和addslashes() 只会工作,如果查询字符串被包裹在报价. 如下面的字符串将仍然容易受到SQL注入:
 

1
2
3
$USER_NAME = 和addslashes( $彦博[ '用户名' ] );
$密码  = 和addslashes( $彦博[ “密码” ] );
$询问 = “SELECT名字, 姓氏, 从USERS_TABLE其中username ='ACCOUNT_NUMBER$USER_NAME及密码='$密码“ ";

mysql_real_escape_string()

 

mysql_real_escape_string() 一点点更强大的比 和addslashes() 调用MySQL的库函数 mysql_real_escape_string, 以下字符前面加上反斜线: \X00, \Ñ, \ŗ, \, “, ” X1A.
 

正如 和addslashes(), mysql_real_escape_string() 只会工作,如果查询字符串被包裹在报价. 如下面的字符串将仍然容易受到SQL注入:
 

1
2
3
$USER_NAME = mysql_real_escape_string( $彦博[ '用户名' ] );
$密码  = mysql_real_escape_string( $彦博[ “密码” ] );
$询问 = “SELECT名字, 姓氏, 从USERS_TABLE其中username ='ACCOUNT_NUMBER$USER_NAME及密码='$密码“ ";

 

sprintf的()

 

sprintf的() 可用于与转换规格,以确保动态参数被视为它的方式假设待处理. 例如, 如果呼叫是在字符串中的用户ID号, 将用于确保参数被视为一个字符串. 这样的一个例子是如下:
 

1
2
3
$USER_NAME = $彦博[ '用户名' ];
$密码  = $彦博[ “密码” ];
$询问 = sprintf的(“SELECT名字, 姓氏, 从USERS_TABLE其中username ='ACCOUNT_NUMBER及密码='“ ", $USER_NAME, $密码);

 

ヶ辆($是, ENT_QUOTES)

 

ヶ辆() 与可选第二quote_style参数结合, 允许使用 ENT_QUOTES, 双和单引号转换. 这将工作在同样的意义 和addslashes()mysql_real_escape_string() 关于引号, 然而, 而不是在前面加上一个反斜杠, 它会使用HTML实体引号.
 

除了使用 ENT_QUOTESヶ辆(), 第三个参数可以设置强制使用的字符集转换内. 这将有助于阻止使用的不可预知的结果 多字节 字符集的字符,如 BIG5GPK.
 

下面是一个示例代码,这将有助于防止 SQL注入 在PHP.
 

1
2
3
4
5
$USER_NAME = $彦博[ '用户名' ];
$USER_NAME = ヶ辆( $USER_NAME, ENT_QUOTES, 'utf-8' );
$密码  = $彦博[ “密码” ];
$密码  = ヶ辆( $密码, ENT_QUOTES, 'utf-8' );
$询问 = “SELECT名字, 姓氏, 从USERS_TABLE其中username ='ACCOUNT_NUMBER$USER_NAME及密码='$密码“ ";

 

优化SQL代码

 

数据库服务器是复杂的野兽和他们有更多的功能比你需要的. 至于安全性方面, 更是从来没有好. 例如, 在 xp_cmdshell的 扩展存储过程中 MS SQL 可以访问的外壳,这是正是黑客的梦想. 这就是为什么你应该禁用此程序,任何其他功能, 它可以很容易被误用. 只是消除或至少停用任何功能,你也离不开谁.
 

禁用默认的SQL错误消息

 

错误消息是对攻击者有用,因为它们提供了有关数据库和SQL查询的其他信息. 所有SQL的攻击通常是基于类型的错误发出SQL, 这意味着这种类型的错误决定黑客黑客网站或应用程序的方法. 一个更好的解决方案,不危及安全,将显示 一般性错误消息 只是指出一个错误已经发生.
 

安全存储数据库凭据

 

为了将损失降至最低的情况下的 SQL注入攻击, 总是在一个单独的加密文件存储数据库凭据. 现在,即使一个黑客设法打破, 他或她将得不到什么好处,因为他可以在你的数据库没有做太多.
 

使用最小特权原则

 

最小特权原则是非常有益的,它适用于 SQL注入 以及. 始终认为两次检查什么 特权 您所提供 用户物体. 假设你婉提供主持人的访问某些用户, 所以只提供他的访问,他/她需要这些表, 而不是证明他整个数据库的访问. 如果你必须提供访问系统, 它能够更好地 创建分区表空间内的数据库,并提供了具体的表空间的访问. 该技术将 大大减少了攻击面.
 

禁用壳

 

很多数据库提供shell访问 到这基本上就是一个攻击者或黑客需要数据库. 正因为如此,你需要关闭这个开放的漏洞. 每个服务提供者有不同的方法来 禁用炮弹的执行 在他们的数据库. 有关如何禁用shell访问您的特定数据库或表空间或特定的表,所以咨询您的数据库文件.
 

使用SQL注入工具查看漏洞

 

最后但并非最不重要, 觉得像黑客. 黑客如何破解我的数据库,通过 SQL注入, 他可以使用什么样的工具和技术,找到漏洞. 你应该总是有干运行的SQL注入式黑客工具,如 SQLI, Haviz, SQL injectme 等等. 更多,如果你能负担得起视网膜漏洞扫描器,然后不太好. 它包括所有最新暴露的漏洞.

非常感谢. 我希望你们都必须享受. 请提出意见,使我们可以做的更多更好.

 
 

28,914 总的看法, 13 今日观点

下面的两个选项卡下面的内容转变.

安萨里阿什法克

安全研究员
阿什法克安萨里是创始人 HackSys队 代号为 "豹". 他是一位安全研究人员在信息安全的各个方面的经验. 他曾撰写 "HackSys极端脆弱的驱动程序" 和 "死亡的shellcode". 他还撰写并出版了低层次软件开发的各种白皮书. 他的核心利益在于 "低水平开发", "逆向工程", "项目分析" 和 "混合起毛". 他是人工智能和机器学习的变形金刚迷. 他是章负责人 空普纳.

阿什法克安萨里的最新文章 (查看全部)

发表评论

您的电子邮件地址不会被公开. 必需字段标记 *