php安全编程—sql注入攻击

原文:php安全编程—sql注入攻击

php安全编程——sql注入攻击

定义

  1. SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。
  2. 根据相关技术原理,SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行了非法的数据查询。基于此,SQL注入的产生原因通常表现在以下几方面:
    • 不当的类型处理;
    • 不安全的数据库配置;
    • 不合理的查询集处理;
    • 不当的错误处理;
    • 转义字符处理不合适;
    • 多个提交处理不当。
  3. 在某些表单中,用户输入的内容直接用来构造动态sql命令,或者作为存储过程的输入参数,这些表单特别容易受到sql注入的攻击。而许多网站程序在编写时,没有对用户输入的合法性进行判断或者程序中本身的变量处理不当,使应用程序存在安全隐患。这样,用户就可以提交一段数据库查询的代码,根据程序返回的结果,获得一些敏感的信息或者控制整个服务器,于是sql注入就发生了

常用技术

  1. 强制产生错误
    对数据库类型、版本等信息进行识别是此类型攻击的动机所在。它的目的是收集数据库的类型、结构等信息为其他类型的攻击做准备,可谓是攻击的一个预备步骤。利用应用程序服务器返回的默认错误信息而取得漏洞信息。
  2. 采用非主流通道技术
    除HTTP响应外,能通过通道获取数据,然而,通道大都依赖与数据库支持的功能而存在,所以这项技术不完全适用于所有的数据库平台。SQL注入的非主流通道主要有E-mail、DNS以及数据库连接,基本思想为:先对SQL查询打包,然后借助非主流通道将信息反馈至攻击者。
  3. 使用特殊的字符
    不同的SQL数据库有许多不同是特殊字符和变量,通过某些配置不安全或过滤不细致的应用系统能够取得某些有用的信息,从而对进一步攻击提供方向。
  4. 使用条件语句
    此方式具体可分为基于内容、基于时间、基于错误三种形式。一般在经过常规访问后加上条件语句,根据信息反馈来判定被攻击的目标
  5. 利用存储过程
    通过某些标准存储过程,数据库厂商对数据库的功能进行扩展的同时,系统也可与进行交互。部分存储过程可以让用户自行定义。通过其他类型的攻击收集到数据库的类型、结构等信息后,便能够建构执行存储过程的命令。这种攻击类型往往能达到远程命令执行、特权扩张、拒绝服务的目的。
  6. 避开输入过滤技术
    虽然对于通常的编码都可利用某些过滤技术进行SQL注入防范,但是鉴于此种情况下也有许多方法避开过滤,一般可达到此目的的技术手段包括SQL注释和动态查询的使用,利用截断,URL编码与空字节的使用,大小写变种的使用以及嵌套剥离后的表达式等等。借助于此些手段,输入构思后的查询可以避开输入过滤,从而攻击者能获得想要的查询结果。
  7. 推断技术
    能够明确数据库模式、提取数据以及识别可注入参数。此种方式的攻击通过网站对用户输入的反馈信息,对可注入参数、数据库模式推断,这种攻击构造的查询执行后获得的答案只有真、假两种。基于推断的注入方式主要分为时间测定注入与盲注入两种。前者是在注入语句里加入语句诸如“waitfor 100”,按照此查询结果出现的时间对注入能否成功和数据值范围的推导进行判定;后者主要是“and l=l”、“and l=2”两种经典注入方法。这些方式均是对一些间接关联且能取得回应的问题进行提问,进而通过响应信息推断出想要信息,然后进行攻击

防范方法

  1. 强制字符格式(类型)

    • 对于整形变量, 运用 intval函数将数据转换成整数
    • 浮点型参数:运用 floatval或doubleval函数分别转换单精度和双精度浮点型参数
    • 字符型参数:运用 addslashes函数来将单引号“’”转换成“\’”,双引号“"”转换成“"”,反斜杠“\”转换成“\”,NULL字符加上反斜杠“\”如果是字符型,先判断magic_quotes_gpc是否为On,当不为On的时候运用 addslashes转义特殊字符
  2. 生产环境关闭数据库错误提示,以避免攻击者得到数据库的相关信息。
  3. SQL语句中包含变量加引号
    SELECT * FROM article WHERE articleid='$id'
    没有把变量放进单引号中,那我们所提交的一切,只要包含空格,那空格后的变量都会作为SQL语句执行,给了攻击者构造特殊sql语句的可能。因此,我们要养成给SQL语句中变量加引号的习惯
  4. 使用pdo 使用 prepared statements ( 预处理语句 )和参数化的查询。这些SQL语句被发送到数据库服务器,它的参数全都会被单独解析。使用这种方式,攻击者想注入恶意的SQL是不可能的
    • 使用PDO访问MySQL数据库时,真正的real prepared statements 默认情况下是不使用的。为了解决这个问题,你必须禁用 prepared statements的仿真效果。下面是使用PDO创建链接的例子:

      <?php
      $dbh = new PDO('mysql:dbname=mydb;host=127.0.0.1;charset=utf8', 'root', 'pass');
      $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
      ?>  

      这可以确保SQL语句和相应的值在传递到mysql服务器之前是不会被PHP解析的(禁止了所有可能的恶意SQL注入攻击)

    完整示例代码:

        <?php
        $dbh = new PDO("mysql:host=localhost; dbname=mydb", "root", "pass");
        $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //禁用prepared statements的仿真效果
        $dbh->exec("set names 'utf8'");
        $sql="select * from table where username = ? and password = ?";
        $query = $dbh->prepare($sql);
        $exeres = $query->execute(array($username, $pass));
        if ($exeres) {
            while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
                print_r($row);
            }
        }
        $dbh = null;
        ?>  

    当调用 prepare() 时,查询语句已经发送给了数据库服务器,此时只有占位符 ? 发送过去,没有用户提交的数据;当调用到 execute()时,用户提交过来的值才会传送给数据库,它们是分开传送的,两者独立的,SQL攻击者没有一点机会。

  5. 如下几种情况,pdo prepared statements 将不能起到防范的作用
    • PDO::ATTR_EMULATE_PREPARES 启用或禁用预处理语句的模拟。 有些驱动不支持或有限度地支持本地预处理。使用此设置强制PDO总是模拟预处理语句(如果为 TRUE ),或试着使用本地预处理语句(如果为 FALSE)。如果驱动不能成功预处理当前查询,它将总是回到模拟预处理语句上。
    • 不能让占位符 ? 代替一组值,这样只会获取到这组数据的第一个值,
      select * from table where userid in ( ? );
      如果要用in來查找,可以改用find_in_set()实现:
      $ids = '1,2,3,4,5,6'; select * from table where find_in_set(userid, ?);
    • 不能让占位符代替数据表名或列名,如:
      select * from table order by ?;
    • 不能让占位符 ? 代替任何其他SQL语法,如:
      select extract( ? from addtime) as mytime from table;
时间: 2024-09-09 16:10:10

php安全编程—sql注入攻击的相关文章

Spring MVC防御CSRF、XSS和SQL注入攻击

解决CSRF的办法:客户端向服务器提交请求时,服务器一定要校验口令.客户端指定页面要有服务器端提供的口令 本文说一下SpringMVC如何防御CSRF(Cross-site request forgery跨站请求伪造)和XSS(Cross site script跨站脚本攻击). 说说CSRF 对CSRF来说,其实Spring3.1.ASP.NET MVC3.Rails.Django等都已经支持自动在涉及POST的地方添加Token(包括FORM表单和AJAX POST等),似乎是一个tag的事情

技巧和诀窍防范SQL注入攻击_漏洞研究

[原文地址]Tip/Trick: Guard Against SQL Injection Attacks [原文发表日期] Saturday, September 30, 2006 9:11 AM SQL注入攻击是非常令人讨厌的安全漏洞,是所有的web开发人员,不管是什么平台,技术,还是数据层,需要确信他们理解和防止的东西.不幸的是,开发人员往往不集中花点时间在这上面,以至他们的应用,更糟糕的是,他们的客户极其容易受到攻击. Michael Sutton 最近发表了一篇非常发人深省的帖子,讲述在

稳捷网络保护网站远离SQL注入攻击

一个被命名为LizaMoon的(SQL Injection)SQL注入攻击席卷全球,许 多网站遭受攻击,网页内容中被塞了lizamoon字串,疑似挂马链接,透过Google查询 lizamoon. com关键词,被稙入恶意链接的URL数在 两天内由28,000个急速增加到380,000个,甚至苹果的iTune网站也名列其中--对此,稳捷网络公司大中国区总经理彭朝晖先生表示,稳捷网络公司一直关注类似的SQL注入与黑客攻击事件.此次LizaMoon攻击利用了一个很巧妙的SQL注入,导致全球5万中文网

SQL注入攻击:防御和检查SQL注入的手段

虽然前面有许多文章讨论了SQL注入,但今天所讨论的内容也许可帮助你检查自己的服务器,并采取相应防范措施.知彼知己,方可取胜.首先要清楚SQL注入攻击有哪些种类. 观察近来的一些安全事件及其后果,安全专家们已经得到一个结论,这些威胁主要是通过SQL注入造成的.虽然前面有许多文章讨论了SQL注入,但今天所讨论的内容也许可帮助你检查自己的服务器,并采取相应防范措施. SQL注入攻击的种类 知彼知己,方可取胜.首先要清楚SQL注入攻击有哪些种类. 1.没有正确过滤转义字符 在用户的输入没有为转义字符过滤

入门:防范SQL注入攻击的新办法

近段时间由于修改一个ASP程序(有SQL注入漏洞),在网上找了很多相关的一些防范办法,都不近人意,所以我将现在网上的一些方法综合改良了一下,写出这个ASP函数,供大家参考. 以下是引用片段: Function SafeRequest(ParaName)  Dim ParaValue  ParaValue=Request(ParaName) if IsNumeric(ParaValue) = True then SafeRequest=ParaValue exit Function elseIf

SQL注入攻击-来自微软安全博客的建议

本文翻译自微软博客上刊载的相关文章,英文原文版权归原作者所有,特此声明.原文:http://blogs.technet.com/swi/archive/2008/05/29/sql-injection-attack.aspx近期趋势 从去年下半年开始,很多网站被损害,他们在用于生成动态网页的SQL数据库中存储的文本中被注入了恶意的HTML <script>标签.这样的攻击在2008年第一季度开始加速传播,并且持续影响有漏洞的Web程序.这些Web应用程序有这样一些共同点: 使用经典ASP代码的

防范SQL注入攻击的新办法

攻击 近段时间由于修改一个ASP程序(有SQL注入漏洞),在网上找了很多相关的一些防范办法,都不近人意,所以我将现在网上的一些方法综合改良了一下,写出这个ASP函数,供大家参考. Function SafeRequest(ParaName) Dim ParaValue ParaValue=Request(ParaName)if IsNumeric(ParaValue) = True thenSafeRequest=ParaValueexit FunctionelseIf Instr(LCase(

动态网页新手入门:防范SQL注入攻击的新办法

sql|动态|攻击|网页 近段时间由于修改一个ASP程序(有SQL注入漏洞),在网上找了很多相关的一些防范办法,都不近人意,所以我将现在网上的一些方法综合改良了一下,写出这个ASP函数,供大家参考. Function SafeRequest(ParaName)  Dim ParaValue  ParaValue=Request(ParaName) if IsNumeric(ParaValue) = True then SafeRequest=ParaValue exit Function els

防范SQL注入攻击的代码

攻击 SQL注入式攻击是利用是指利用设计上的漏洞,在目标服务器上运行Sql命令以及进行其他方式的攻击,动态生成Sql命令时没有对用户输入的数据进行验证是Sql注入攻击得逞的主要原因.比如: 如果你的查询语句是select * from admin where username='"&user&"' and password='"&pwd&"'" 那么,如果我的用户名是:1' or '1'='1 那么,你的查询语句将会变成: