热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在PHP中全面禁止SQL注进式攻击之三

另一方面,应用这个库存在一个突出的毛病:你只能受限于某些人的思想,而且代码治理方面也添加了大批的工作。为此,在决定是否应用它们之前,你需要进行仔细地考虑。假如你决定这样做,那么,你至少确保它们能够真正帮助你'清算'你的用户输进的内容

一、 建立一个安全抽象层

  我们并不建议你手工地把前面先容的技巧利用于每一个用户输进的实例中,而是强烈推荐你为此创立一个抽象层。一个简略的抽象是把你的校验计划参加到一个函数中,并且针对用户输进的每一项调用这个函数。当然,我们还可以创立一种更复杂的更高一级的抽象-把一个安全的查询封装到一个类中,从而利用于全部利用程序。在网上已经存在很多这种现成的免费的类;在本篇中,我们正要讨论其中的一些。

  进行这种抽象至少存在三个长处(而且每一个都会改良安全级别):

  1. 本地化代码。

  2. 使查询的结构更快且更为可靠-由于这可以把部分工作交由抽象代码来实现。

  3. 当基于安全特点进行构建并且适当应用时,这将会有效地防止我们前面所讨论的各种各样的注进式攻击。

  二、 改良现有的利用程序

  假如你想改良一个现有的利用程序,则应用一个简略的抽象层是最适当的。一个能够简略地'清算'你所收集的任何用户输进内容的函数可能看起来如下所示:

function safe( $string ) {
 return ''' . mysql_real_escape_string( $string ) . '''
}
  【留心】我们已经构建了相应于值请求的单引号以及mysql_real_escape_string()函数。接下来,就可以应用这个函数来结构一个$query变量,如下所示:

$variety = safe( $_POST['variety'] );
$query = ' SELECT * FROM wines WHERE variety=' . $variety;
  现在,你的用户试图进行一个注进式攻击-通过输进下列内容作为变量$variety的值:

lagrein' or 1=1;
  留心,假如不进行上面的'清算',则最后的查询将如下所示(这将导致无法预感的成果):

SELECT * FROM wines WHERE variety = 'lagrein' or 1=1;'
  然而现在,既然用户的输进已经被清算,那么查询语句就成为下面这样一种无迫害的情势:

SELECT * FROM wines WHERE variety = 'lagrein\' or 1=1\;'

  既然数据库中不存在与指定的值相应的variety域(这正是恶意用户所输进的内容-lagrein' or 1=1;),那么,这个查询将不能返回任何成果,并且注进将会失败。

  三、 保护一个新的利用程序

  假如你正在创立一个新的利用程序,那么,你可以从头开端创立一个安全抽象层。如今,PHP 5新改良的对于MySQL的支撑(这重要体现在新的mysqli扩大中)为这种安全特点供给了强有力的支撑(既有过程性的,也有面向对象特点的)。你可以从站点http://php.net/mysqli上获取有关mysqli的信息。留心,只有当你应用--with-mysqli=path/to/mysql_config选项编译PHP时,这种mysqli支撑才可用。下面是该代码的一个过程性版本,用于保护一个基于mysqli的查询:



<?php
 //检索用户的输进
 $animalName = $_POST['animalName'];
 //连接到数据库
 $cOnnect= mysqli_connect( 'localhost', 'username', 'password', 'database' );
 if ( !$connect ) exit( 'connection failed: ' . mysqli_connect_error() );
 //创立一个查询语句源
 $stmt = mysqli_prepare( $connect,'SELECT intelligence FROM animals WHERE name = ?' );
 if ( $stmt ) {
  //把调换绑定到语句上
  mysqli_stmt_bind_param( $stmt, 's', $animalName );
  //履行该语句
  mysqli_stmt_execute( $stmt );
  //检索成果...
  mysqli_stmt_bind_result( $stmt, $intelligence );
  // ...并显示它
  if ( mysqli_stmt_fetch( $stmt ) ) {
   print 'A $animalName has $intelligence intelligence.\n';
  } else {
   print 'Sorry, no records found.';
  }
  //清除语句源
  mysqli_stmt_close( $stmt );
 }
 mysqli_close( $connect );
?>
  该mysqli扩大供给了一组函数用于结构和履行查询。而且,它也非常准确地供给了前面应用我们自己的safe()函数所实现的功效。

  在上面的片段中,首先收集用户提交的输进内容并建立数据库连接。然后,应用mysqli_prepare()函数创立一个查询语句源-在此命名为$stmt以反应应用它的函数的名称。这个函数应用了两个参数:连接资源和一个字符串(每当你应用扩大插进一个值时,'?'标记被插进到其中)。在本例中,你仅有一个这样的值-动物的名字。

  留心,在一个SELECT语句中,放置'?'标记的唯一的有效地位是在值比拟部分。这正是为什么你不需要指定应用哪个变量的原因(除了在mysqli_stmt_bind_param()函数中之外)。在此,你还需要指定它的类型-在本例中,'s'代表字符串。其它可能的类型有:'I'代表整数,'d'代表双精度数(或浮点数),而'b'代表二进制字符串。

  函数mysqli_stmt_execute(),mysqli_stmt_bind_result()和mysqli_stmt_fetch()负责履行查询并检索成果。假如存在检索成果,则显示它们;假如不存在成果,则显示一条无害的消息。最后,你需要封闭$stmt资源以及数据库连接-从内存中对它们加以开释。

  假定一个正当的用户输进了字符串'lemming',那么这个例程将(假定是数据库中适当的数据)输出消息'A lemming has very low intelligence.'。假定存在一个尝试性注进-例如'lemming' or 1=1;',那么这个例程将打印(无害)消息'Sorry, no records found.'。
此外,mysqli扩大还供给了一个面向对象版本的雷同的例程。下面,我们想阐明这种版本的应用方法。

<?php
 $animalName = $_POST['animalName'];
 $mysqli = new mysqli( 'localhost', 'username', 'password', 'database');
 if ( !$mysqli ) exit( 'connection failed: ' . mysqli_connect_error() );
 $stmt = $mysqli->prepare( 'SELECT intelligence

 FROM animals WHERE name = ?' );
 if ( $stmt ) {
  $stmt->bind_param( 's', $animalName );
  $stmt->execute();
  $stmt->bind_result( $intelligence );
  if ( $stmt->fetch() ) {
   print 'A $animalName has $intelligence intelligence.\n';
  } else {
   print 'Sorry, no records found.';
  }
  $stmt->close();
 }
 $mysqli->close();
?>
  实际上,这部分代码是前面描写代码的复制-它应用了一种面向对象的语法和组织方法,而不是严格的过程式代码。


  四、 更高级的抽象

  假如你应用外部库PearDB,那么,你可以对利用程序的安全保护模块进行全面的抽象。

  另一方面,应用这个库存在一个突出的毛病:你只能受限于某些人的思想,而且代码治理方面也添加了大批的工作。为此,在决定是否应用它们之前,你需要进行仔细地考虑。假如你决定这样做,那么,你至少确保它们能够真正帮助你'清算'你的用户输进的内容。

  五、 测试你的注进式保护才能

  正如我们在前面所讨论的,确保你的脚本安全的一个重要的部分是对它们进行测试。为此,最好的措施是你自己创立SQL代码注进测试。
在此,我们供给了一个这种测试的示例。在本例中,我们测试对一个SELECT语句的注进式攻击。

<?php
//被测试的保护函数
function safe( $string ) {
 return ''' . mysql_real_escape_string( $string ) . '''
}
//连接到数据库
///////////////////////
//试图进行注进
///////////////////////
$exploit = 'lemming' AND 1=1;';
//进行清算
$safe = safe( $exploit );
$query = 'SELECT * FROM animals WHERE name = $safe';
$result = mysql_query( $query );
//测试是否保护是足够的
if ( $result && mysql_num_rows( $result ) == 1 ) {
 exitt 'Protection succeeded:\n
 exploit $exploit was neutralized.';
}
else {
 exit( 'Protection failed:\n
 exploit $exploit was able to retrieve all rows.' );
}
?>
  假如你想创立这样的一个测试集,并实验基于不同的SQL命令的各种不同的注进,那么,你将会很快地探测出你的保护策略中的任何漏洞。一旦改正这些标题,那么,你就可以很有把握-你已经建立起真正的注进式攻击保护机制。

  六、 小结

  在本系列文章一开端,我们通过一个SQL注进讨论分析了对你的脚本的特定要挟-由不适当的用户输进所致。之后,我们描写了SQL注进的工作原理并准确地分析了PHP是怎样易于被注进的。然后,我们供给了一个实际中的注进示例。之后,我们推荐一系列措施来使试图的注进攻击变为无害的-这将分辨通过确保使所有提交的值以引号封闭,通过检查用户提交值的类型,以及通过过滤掉你的用户输进的埋伏危险的字符等方法来实现的。最后,我们推荐,你最好对你的校验例程进行抽象,并针对更改一个现有利用程序供给了脚本示例。然后,我们讨论了第三方抽象计划的优毛病。


推荐阅读
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
author-avatar
mobiledu2502886131
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有