解决方案

防SQL注入的五种方法

seo靠我 2023-09-24 08:19:20
防止SQL注入

一、SQL注入简介

    SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库。

二、SQL注入SEO靠我攻击的总体思路

1.寻找到SQL注入的位置

2.判断服务器类型和后台数据库类型

3.针对不通的服务器和数据库特点进行SQL注入攻击

三、SQL注入攻击实例

比如在一个登录界面,要求输入用户名和密码:

可以这样输入SEO靠我实现免帐号登录:

用户名: ‘or 1 = 1 –

密 码:

点登陆,如若没有做特殊处理,那么这个非法用户就很得意的登陆进去了.(当然现在的有些语言的数据库API已经处理了这些问题)

这是为什么呢? 下面我们SEO靠我分析一下:

从理论上说,后台认证程序中会有如下的SQL语句:

String sql = "select * from user_table where username=

"+userName+" and SEO靠我password= "+password+" ";

当输入了上面的用户名和密码,上面的SQL语句变成:

SELECT * FROM user_table WHERE username=

’or 1 = 1 SEO靠我-- and password=’

分析SQL语句:

条件后面username=”or 1=1 用户名等于 ” 或1=1 那么这个条件一定会成功;

然后后面加两个-,这意味着注释,它将后面的语句注释,让他们SEO靠我不起作用,这样语句永远都能正确执行,用户轻易骗过系统,获取合法身份。

这还是比较温柔的,如果是执行

SELECT * FROM user_table WHERE

username= ;DROP DATABASEO靠我SE (DB Name) -- and password=

….其后果可想而知…

四、应对方法

【一、在服务器端配置】

       安全,PHP代码编写是一方面,PHP的配置更是非常关键。

我们php手手工安装的,php的SEO靠我默认配置文件在 /usr/local/apache2/conf/php.ini,我们最主要就是要配置php.ini中的内容,让我们执行 php能够更安全。整个PHP中的安全设置主要是为了防止phpshSEO靠我ell和SQL Injection的攻击,一下我们慢慢探讨。我们先使用任何编辑工具打开 /etc/local/apache2/conf/php.ini,如果你是采用其他方式安装,配置文件可能不在该目录SEO靠我

(1) 打开php的安全模式

php的安全模式是个非常重要的内嵌的安全机制,能够控制一些php中的函数,比如system(),

同时把很多文件操作函数进行了权限控制,也不允许对某些关键文件的文件,比如/SEO靠我etc/passwd,

但是默认的php.ini是没有打开安全模式的,我们把它打开:

safe_mode = on

(2) 用户组安全

当safe_mode打开时,safe_mode_gid被关闭,那么phpSEO靠我脚本能够对文件进行访问,而且相同

组的用户也能够对文件进行访问。

建议设置为:

safe_mode_gid = off

如果不进行设置,可能我们无法对我们服务器网站目录下的文件进行操作了,比如我们需要

对文件进SEO靠我行操作的时候。

(3) 安全模式下执行程序主目录

如果安全模式打开了,但是却是要执行某些程序的时候,可以指定要执行程序的主目录:

safe_mode_exec_dir = D:/usr/bin

一般情况下是不SEO靠我需要执行什么程序的,所以推荐不要执行系统程序目录,可以指向一个目录,

然后把需要执行的程序拷贝过去,比如:

safe_mode_exec_dir = D:/tmp/cmd

但是,我更推荐不要执行任何程序,那SEO靠我么就可以指向我们网页目录:

safe_mode_exec_dir = D:/usr/www

(4) 安全模式下包含文件

如果要在安全模式下包含某些公共文件,那么就修改一下选项:

safe_mode_incluSEO靠我de_dir = D:/usr/www/include/

其实一般php脚本中包含文件都是在程序自己已经写好了,这个可以根据具体需要设置。

(5) 控制php脚本能访问的目录

使用open_basedir选SEO靠我项能够控制PHP脚本只能访问指定的目录,这样能够避免PHP脚本访问

不应该访问的文件,一定程度上限制了phpshell的危害,我们一般可以设置为只能访问网站目录:

open_basedir = D:/usSEO靠我r/www

(6) 关闭危险函数

如果打开了安全模式,那么函数禁止是可以不需要的,但是我们为了安全还是考虑进去。比如,

我们觉得不希望执行包括system()等在那的能够执行命令的php函数,或者能够查看pSEO靠我hp信息的

phpinfo()等函数,那么我们就可以禁止它们:

disable_functions = system,passthru,exec,shell_exec,popen,phpinfo

如果你要禁SEO靠我止任何文件和目录的操作,那么可以关闭很多文件操作

disable_functions = chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unSEO靠我link,delete,copy,mkdir, rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown

以上只是列了部分不叫SEO靠我常用的文件处理函数,你也可以把上面执行命令函数和这个函数结合,

就能够抵制大部分的phpshell了。

(7) 关闭PHP版本信息在http头中的泄漏

我们为了防止黑客获取服务器中php版本的信息,可以关闭SEO靠我该信息斜路在http头中:

expose_php = Off

比如黑客在 telnet www.12345.com 80 的时候,那么将无法看到PHP的信息。

(8) 关闭注册全局变量

在PHP中提交的变量,SEO靠我包括使用POST或者GET提交的变量,都将自动注册为全局变量,能够直接访问,

这是对服务器非常不安全的,所以我们不能让它注册为全局变量,就把注册全局变量选项关闭:

register_globals = OSEO靠我ff

当然,如果这样设置了,那么获取对应变量的时候就要采用合理方式,比如获取GET提交的变量var,

那么就要用$_GET[var]来进行获取,这个php程序员要注意。

(9) 打开magic_quotesSEO靠我_gpc来防止SQL注入

SQL注入是非常危险的问题,小则网站后台被入侵,重则整个服务器沦陷,

所以一定要小心。php.ini中有一个设置:

magic_quotes_gpc = Off

这个默认是关闭的,如SEO靠我果它打开后将自动把用户提交对sql的查询进行转换,

比如把 转为 \等,这对防止sql注射有重大作用。所以我们推荐设置为:

magic_quotes_gpc = On

(10) 错误信息控制

一般php在没有SEO靠我连接到数据库或者其他情况下会有提示错误,一般错误信息中会包含php脚本当

前的路径信息或者查询的SQL语句等信息,这类信息提供给黑客后,是不安全的,所以一般服务器建议禁止错误提示:

display_errSEO靠我ors = Off

如果你却是是要显示错误信息,一定要设置显示错误的级别,比如只显示警告以上的信息:

error_reporting = E_WARNING & E_ERROR

当然,我还是建议关闭错误提示SEO靠我

(11) 错误日志

建议在关闭display_errors后能够把错误信息记录下来,便于查找服务器运行的原因:

log_errors = On

同时也要设置错误日志存放的目录,建议根apache的日志存在SEO靠我一起:

error_log = D:/usr/local/apache2/logs/php_error.log

注意:给文件必须允许apache用户的和组具有写的权限。

MYSQL的降权运行

新建立一个用户比SEO靠我如mysqlstart

net user mysqlstart fuckmicrosoft /add

net localgroup users mysqlstart /del

不属于任何组

如果MYSQL装在SEO靠我d:\mysql ,那么,给 mysqlstart 完全控制 的权限

然后在系统服务中设置,MYSQL的服务属性,在登录属性当中,选择此用户 mysqlstart 然后输入密码,确定。

重新启动 MYSQSEO靠我L服务,然后MYSQL就运行在低权限下了。

如果是在windos平台下搭建的apache我们还需要注意一点,apache默认运行是system权限,

这很恐怖,这让人感觉很不爽.那我们就给apache降降SEO靠我权限吧。

net user apache fuckmicrosoft /add

net localgroup users apache /del

ok.我们建立了一个不属于任何组的用户apche。

我们打开计SEO靠我算机管理器,选服务,点apache服务的属性,我们选择log on,选择this account,我们填入上面所建立的账户和密码,

重启apache服务,ok,apache运行在低权限下了。

实际上我们还SEO靠我可以通过设置各个文件夹的权限,来让apache用户只能执行我们想让它能干的事情,给每一个目录建立一个单独能读写的用户。

这也是当前很多虚拟主机提供商的流行配置方法哦,不过这种方法用于防止这里就显的有点大SEO靠我材小用了。

【二、在PHP代码编写】

虽然国内很多PHP程序员仍在依靠addslashes防止SQL注入,还是建议大家加强中文防止SQL注入的检查。addslashes的问题在于黑客可以用0xbf27来代SEO靠我替单引号,而addslashes只是将0xbf27修改为0xbf5c27,成为一个有效的多字节字符,其中的0xbf5c仍会被看作是单引号,所以addslashes无法成功拦截。

当然addslashesSEO靠我也不是毫无用处,它是用于单字节字符串的处理,多字节字符还是用mysql_real_escape_string吧。

       另外对于php手册中get_magic_quotes_gpc的举例:

if (!get_mSEO靠我agic_quotes_gpc()) {

$lastname = addslashes($_POST[‘lastname’]);

} else {

$lastname = $_POST[‘lastname’SEO靠我];

}

最好对magic_quotes_gpc已经开放的情况下,还是对$_POST[’lastname’]进行检查一下。

再说下mysql_real_escape_string和mysql_escape_SEO靠我string这2个函数的区别:

mysql_real_escape_string 必须在(PHP 4 >= 4.3.0, PHP 5)的情况下才能使用。否则只能用 mysql_escape_stringSEO靠我 ,两者的区别是:mysql_real_escape_string 考虑到连接的

当前字符集,而mysql_escape_string 不考虑。

总结一下:

* addslashes() 是强行加\;

* mSEO靠我ysql_real_escape_string()  会判断字符集,但是对PHP版本有要求;

* mysql_escape_string不考虑连接的当前字符集。

---------------------SEO靠我----------------------------------------------------------------------------

在PHP编码的时候,如果考虑到一些比较基本的安全SEO靠我问题,首先一点:

1. 初始化你的变量

为什么这么说呢?我们看下面的代码:

PHP代码   

   1 2 3 4 5 6 7 8 9 10 11 <?php          if  ( $admin )       SEO靠我   {          echo  登陆成功! ;          include ( admin.php );          }          else          {     SEO靠我     echo  你不是管理员,无法进行管理! ;          }          ?>

好,我们看上面的代码好像是能正常运行,没有问题,那么加入我提交一个非法的参数过去呢,那么效果会如何呢SEO靠我?比如我们的这个页是http://daybook.diandian.com/login.php,那么我们提交:http://daybook.diandian.com/login.php?admin=1SEO靠我,呵呵,你想一些,我们是不是直接就是管理员了,直接进行管理。

当然,可能我们不会犯这么简单错的错误,那么一些很隐秘的错误也可能导致这个问题,比如phpwind论坛有个漏洞,导致能够直接拿到管理员权限,就SEO靠我是因为有个$skin变量没有初始化,导致了后面一系列问题。那么我们如何避免上面的问题呢?首先,从php.ini入手,把php.ini里面的register_global =off,就是不是所有的注册变SEO靠我量为全局,那么就能避免了。但是,我们不是服务器管理员,只能从代码上改进了,那么我们如何改进上面的代码呢?我们改写如下:

PHP代码      

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 SEO靠我16 17 18 19 20 21 22 <?php        $admin  = 0;  // 初始化变量        if  ( $_POST [ admin_user ] &&  $_POSEO靠我ST [ admin_pass ])        {        // 判断提交的管理员用户名和密码是不是对的相应的处理代码        // ...        $admin  = 1;  SEO靠我      }        else        {        $admin  = 0;        }        if  ( $admin )        {        echoSEO靠我  登陆成功! ;        include ( admin.php );        }        else        {        echo  你不是管理员,无法进行管理! ; SEO靠我       }        ?>

那么这时候你再提交http://daybook.diandian.com/login.php?admin=1就不好使了,因为我们在一开始就把变量初始化为 $admiSEO靠我n = 0 了,那么你就无法通过这个漏洞获取管理员权限。

2. 防止SQL Injection (sql注射)

SQL 注射应该是目前程序危害最大的了,包括最早从asp到php,基本上都是国内这两年流行的SEO靠我技术,基本原理就是通过对提交变量的不过滤形成注入点然后使恶意用户能够提交一些sql查询语句,导致重要数据被窃取、数据丢失或者损坏,或者被入侵到后台管理。

那么我们既然了解了基本的注射入侵的方式,那么我们SEO靠我如何去防范呢?这个就应该我们从代码去入手了。

我们知道Web上提交数据有两种方式,一种是get、一种是post,那么很多常见的sql注射就是从get方式入手的,而且注射的语句里面一定是包含一些sql语句SEO靠我的,因为没有sql语句,那么如何进行,sql语句有四大句:select 、update、delete、insert,那么我们如果在我们提交的数据中进行过滤是不是能够避免这些问题呢?

于是我们使用正则就构SEO靠我建如下函数:

PHP代码

 1 2 3 4 5 6 7 8 9 10 11 12 13 <?php            function  inject_check( $sql_str )       {SEO靠我       return  eregi ( select|insert|update|delete| |       function  verify_id( $id =null)       { SEO靠我      if  (! $id ) {  exit ( 没有提交参数! ); }  // 是否为空判断       elseif  (inject_check( $id )) {  exit ( 提SEO靠我交的参数非法! ); }  // 注射判断       elseif  (! is_numeric ( $id )) {  exit ( 提交的参数非法! ); }  // 数字判断       $iSEO靠我d  =  intval ( $id );  // 整型化           return  $id ;       }       ?>

呵呵,那么我们就能够进行校验了,于是我们上面的程序代码就变成SEO靠我了下面的:

PHP代码     

   1 2 3 4 5 6 7 8 9 10 11 <?php         if  (inject_check( $_GET [ id ]))         {         SEO靠我exit ( 你提交的数据非法,请检查后重新提交! );         }         else         {         $id  = verify_id( $_GET [ id ]SEO靠我);  // 这里引用了我们的过滤函数,对$id进行过滤         echo  提交的数据合法,请继续! ;         }         ?>

好,问题到这里似乎都解决了,但是我们有没有考SEO靠我虑过post提交的数据,大批量的数据呢?

比如一些字符可能会对数据库造成危害,比如 _ , %,这些字符都有特殊意义,那么我们如果进行控制呢?还有一点,就是当我们的php.ini里面的magic_quoSEO靠我tes_gpc = off的时候,那么提交的不符合数据库规则的数据都是不会自动在前面加 的,那么我们要控制这些问题,于是构建如下函数:

PHP代码      

  1 2 3 4 5 6 7 8 9 10 11 12 1SEO靠我3 <?php           function  str_check(  $str  )        {        if  (!get_magic_quotes_gpc())  // 判断SEO靠我magic_quotes_gpc是否打开        {        $str  =  addslashes ( $str );  // 进行过滤        }        $str  = SEO靠我 str_replace ( "_" ,  "\_" ,  $str );  // 把 _过滤掉        $str  =  str_replace ( "%" ,  "\%" ,  $str )SEO靠我;  // 把 % 过滤掉                 return  $str ;        }        ?>

    我们又一次的避免了服务器被沦陷的危险。

最后,再考虑提交一些大批量数据的情况SEO靠我,比如发贴,或者写文章、新闻,我们需要一些函数来帮我们过滤和进行转换,再上面函数的基础上,我们构建如下函数:

PHP代码  

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php   SEO靠我        function  post_check( $post )          {          if  (!get_magic_quotes_gpc())  // 判断magic_SEO靠我quotes_gpc是否为打开          {          $post  =  addslashes ( $post );  // 进行magic_quotes_gpc没有打开的情况对提交SEO靠我数据的过滤          }          $post  =  str_replace ( "_" ,  "\_" ,  $post );  // 把 _过滤掉          $post SEO靠我 =  str_replace ( "%" ,  "\%" ,  $post );  // 把 % 过滤掉          $post  =  nl2br ( $post );  // 回车转换  SEO靠我        $post = htmlspecialchars( $post );  // html标记转换             return  $post ;          }      SEO靠我    ?>

呵呵,基本到这里,我们把一些情况都说了一遍,其实我觉得自己讲的东西还很少,至少我才只讲了两方面,再整个安全中是很少的内容了,考虑下一次讲更多,包括php安全配置,apache安全等等,让我SEO靠我们的安全正的是一个整体,作到最安全。

    最后在告诉你上面表达的:1. 初始化你的变量 2. 一定记得要过滤你的变量

一个是没有对输入的数据进行过滤(过滤输入),还有一个是没有对发送到数据库的数据进行转义(转SEO靠我义输出)。这两个重要的步骤缺一不可,需要同时加以特别关注以减少程序错误。

对于攻击者来说,进行SQL注入攻击需要思考和试验,对数据库方案进行有根有据的推理非常有必要(当然假设攻击者看不到你的源程序和数据SEO靠我库方案),考虑以下简单的登录表单:

复制代码代码如下:

Username:

Password:

</form>

作为一个攻击者,他会从推测验证用户名和密码的查询语句开始。通过查看源文件,他就能开始猜测你的习惯。SEO靠我

比如命名习惯。通常会假设你表单中的字段名为与数据表中的字段名相同。当然,确保它们不同未必是一个可靠的安全措施。

第一次猜测,一般会使用下面例子中的查询:

复制代码代码如下:

$password_hash =SEO靠我 md5($_POST[password]);

$sql = "SELECT count(*)

      FROM   users

      WHERE  username = {$_POST[username]}

AND   SEO靠我 password = $password_hash";

 ?>

使用用户密码的MD5值原来是一个通行的做法,但现在并不是特别安全了。最近的研究表明MD5算法有缺陷,而且大量MD5数据库降低了MD5反向破解SEO靠我的难度。请访问http://md5.rednoize.com/ 查看演示(原文如此,山东大学教授王小云的研究表明可以很快的找到MD5的“碰撞”,就是可以产生相同的MD5值的不同两个文件和字串。MD5是SEO靠我信息摘要算法,而不是加密算法,反向破解也就无从谈起了。不过根据这个成果,在上面的特例中,直接使用md5是危险的。)。

最好的保护方法是在密码上附加一个你自己定义的字符串,例如:

复制代码代码如下:

$salSEO靠我t = SHIFLETT;

$password_hash = md5($salt . md5($_POST[password] . $salt));

 ?>

当然,攻击者未必在第一次就能猜中,他们常常还需要做SEO靠我一些试验。有一个比较好的试验方式是把单引号作为用户名录入,原因是这样可能会暴露一些重要信息。有很多开发人员在Mysql语句执行出错时会调用函数mysql_error()来报告错误。见下面的例子:

复制代SEO靠我码代码如下:

 mysql_query($sql) or exit(mysql_error());

 ?>

虽然该方法在开发中十分有用,但它能向攻击者暴露重要信息。如果攻击者把单引号做为用户名,mypass做为SEO靠我密码,查询语句就会变成:

复制代码代码如下:

 $sql = "SELECT *

      FROM   users

      WHERE  username =

AND    password = a029d0df84eb5549SEO靠我c641e04a9ef389e5";

 ?>

当该语句发送到MySQL后,系统就会显示如下错误信息:

复制代码代码如下:

You have an error in your SQL syntax. Check SEO靠我the manual that corresponds to your

MySQL server version for the right syntax to use near WHERE usernSEO靠我ame = AND

password = a029d0df84eb55

不费吹灰之力,攻击者已经知道了两个字段名(username和password)以及他们出现在查询中的顺序。除此以外,攻击者还知道了数SEO靠我据没有正确进行过滤(程序没有提示非法用户名)和转义(出现了数据库错误),同时整个WHERE条件的格式也暴露了,这样,攻击者就可以尝试操纵符合查询的记录了。

在这一点上,攻击者有很多选择。一是尝试填入一个SEO靠我特殊的用户名,以使查询无论用户名密码是否符合,都能得到匹配:

复制代码代码如下:

myuser or foo = foo --

假定将mypass作为密码,整个查询就会变成:

复制代码代码如下:

$sql = SEO靠我"SELECT *

      FROM   users

      WHERE  username = myuser or foo = foo --

AND    password = a029d0df84eb5549c641eSEO靠我04a9ef389e5";

?>

幸运的是,SQL注入是很容易避免的。正如前面所提及的,你必须坚持过滤输入和转义输出。

虽然两个步骤都不能省略,但只要实现其中的一个就能消除大多数的SQL注入风险。如果你只是SEO靠我过滤输入而没有转义输出,你很可能会遇到数据库错误(合法的数据也可能影响SQL查询的正确格式),但这也不可靠,合法的数据还可能改变SQL语句的行为。另一方面,如果你转义了输出,而没有过滤输入,就能保证数SEO靠我据不会影响SQL语句的格式,同时也防止了多种常见SQL注入攻击的方法。

当然,还是要坚持同时使用这两个步骤。过滤输入的方式完全取决于输入数据的类型(见第一章的示例),但转义用于向数据库发送的输出数据只要SEO靠我使用同一个函数即可。对于MySQL用户,可以使用函数mysql_real_escape_string( ):

复制代码代码如下:

 $clean = array();

$mysql = array();

$clSEO靠我ean[last_name] = "OReilly";

$mysql[last_name] = mysql_real_escape_string($clean[last_name]);

$sql = "ISEO靠我NSERT

      INTO   user (last_name)

      VALUES ({$mysql[last_name]})";

 ?>

尽量使用为你的数据库设计的转义函数。如果没有,使用函数addslashes()是SEO靠我最终的比较好的方法。

当所有用于建立一个SQL语句的数据被正确过滤和转义时,实际上也就避免了SQL注入的风险。如果你正在使用支持参数化查询语句和占位符的数据库操作类(如PEAR::DB, PDO等),你SEO靠我就会多得到一层保护。见下面的使用PEAR::DB的例子:

复制代码代码如下:

$sql = INSERT

      INTO   user (last_name)

      VALUES (?);

$dbh->query($sqlSEO靠我, array($clean[last_name]));

?>

由于在上例中数据不能直接影响查询语句的格式,SQL注入的风险就降低了。PEAR::DB会自动根据你的数据库的要求进行转义,所以你只需要过滤输SEO靠我出即可。

如果你正在使用参数化查询语句,输入的内容就只会作为数据来处理。这样就没有必要进行转义了,尽管你可能认为这是必要的一步(如果你希望坚持转义输出习惯的话)。实际上,这时是否转义基本上不会产生影响,SEO靠我因为这时没有特殊字符需要转换。在防止SQL注入这一点上,参数化查询语句为你的程序提供了强大的保护。

注:关于SQL注入,不得不说的是现在大多虚拟主机都会把magic_quotes_gpc选项打开,在这种SEO靠我情况下所有的客户端GET和POST的数据都会自动进行addslashes处理,所以此时对字符串值的SQL注入是不可行的,但要防止对数字值的SQL注入,如用intval()等函数进行处理。但如果你编写的SEO靠我是通用软件,则需要读取服务器的magic_quotes_gpc后进行相应处理。

===================================

总的说来,防范一般的SQL注入只要在代码规范上下点功SEO靠我夫就可以了。

凡涉及到执行的SQL中有变量时,用JDBC(或者其他数据持久层)提供的如:PreparedStatement就可以 ,切记不要用拼接字符串的方法就可以了。

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2