防sql注入

[转]SQL 注入
SQL 注入
很多 web 开发者没有注意到 SQL 查询是可以被篡改的,因而把 SQL 查询当作可信任的命令。殊不知道,SQL 查询可以绕开访问控制,从而绕过身份验证和权限检查。更有甚者,有可能通过 SQL 查询去运行主机操作系统级的命令。
直接 SQL 命令注入就是攻击者常用的一种创建或修改已有 SQL 语句的技术,从而达到取得隐藏数据,或覆盖关键的值,甚至执行数据库主机操作系统命令的目的。这是通过应用程序取得用户输入并与静态参数组合成 SQL 查询来实现的。下面将会给出一些真实的例子。
由于在缺乏对输入的数据进行验证,并且使用了超级用户或其它有权创建新用户的数据库帐号来连接,攻击者可以在数据库中新建一个超级用户。
Example#1 一段实现数据分页显示的代码……也可以被用作创建一个超级用户(PostgreSQL系统)。
复制PHP内容到剪贴板
PHP代码:
$offset = $argv[0]; // 注意,没有输入验证!
$query  = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);

一般的用户会点击 $offset 已被斌值的“上一页”、“下一页”的链接。原本代码只会认为 $offset 是一个数值。然而,如果有人尝试把以下语句先经过 urlencode() 处理,然后加入URL中的话:
0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
    select 'crack', usesysid, 't','t','crack'
    from pg_shadow where usename='postgres';
--
那么他就可以创建一个超级用户了。注意那个 0; 只不过是为了提供一个正确的偏移量以便补充完整原来的查询,使它不要出错而已。
Note: -- 是 SQL 的注释标记,一般可以使用来它告诉 SQL 解释器忽略后面的语句。

对显示搜索结果的页面下手是一个能得到密码的可行办法。攻击者所要做的只不过是找出哪些提交上去的变量是用于 SQL 语句并且处理不当的。而这类的变量通常都被用于 SELECT 查询中的条件语句,如 WHERE, ORDER BY, LIMIT 和 OFFSET。如果数据库支持 UNION 构造的话,攻击者还可能会把一个完整的 SQL 查询附加到原来的语句上以便从任意数据表中得到密码。因此,对密码字段加密是很重要的。
Example#2 显示文章……以及一些密码(任何数据库系统)
复制PHP内容到剪贴板
PHP代码:
$query  = "SELECT id, name, inserted, size FROM products
                  WHERE size = '$size'
                  ORDER BY $order LIMIT $limit, $offset;";
$result = odbc_exec($conn, $query);

可以在原来的查询的基础上添加另一个 SELECT 查询来获得密码:
'
union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable;
--
假如上述语句(使用 ' 和 --)被加入到 $query 中的任意一个变量的话,那么就麻烦了。
SQL 中的 UPDATE 也会受到攻击。这种查询也可能像上面的例子那样被插入或附加上另一个完整的请求。但是攻击者更愿意对 SET 子句下手,这样他们就可以更改数据表中的一些数据。这种情况下必须要知道数据库的结构才能修改查询成功进行。可以通过表单上的变量名对字段进行猜测,或者进行暴力破解。对于存放用户名和密码的字段,命名的方法并不多。
Example#3 从重设密码……到获得更多权限(任何数据库系统)
复制PHP内容到剪贴板
PHP代码:
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";

但是恶意的用户会把 ' or uid like'%admin%'; -- 作为变量的值提交给 $uid 来改变 admin 的密码,或者把 $pwd 的值提交为 "hehehe', admin='yes', trusted=100 "(后面有个空格)去获得更多的权限。这样做的话,查询语句实际上就变成了:
复制PHP内容到剪贴板
PHP代码:
// $uid == ' or uid like'%admin%'; --
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --";
// $pwd == "hehehe', admin='yes', trusted=100 "
$query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE
...;";

下面这个可怕的例子将会演示如何在某些数据库上执行系统命令。
Example#4 攻击数据库所在主机的操作系统(MSSQL Server)
复制PHP内容到剪贴板
PHP代码:
$query  = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);

如果攻击提交 a%' exec master..xp_cmdshell 'net user test testpass /ADD' -- 作为变量 $prod的值,那么 $query 将会变成
复制PHP内容到剪贴板
PHP代码:
$query  = "SELECT * FROM products
                    WHERE id LIKE '%a%'
                    exec master..xp_cmdshell 'net user test testpass /ADD'--";
$result = mssql_query($query);

MSSQL 服务器会执行这条 SQL 语句,包括它后面那个用于向系统添加用户的命令。如果这个程序是以 sa 运行而 MSSQLSERVER 服务又有足够的权限的话,攻击者就可以获得一个系统帐号来访问主机了。
Note: 虽然以上的例子是针对某一特定的数据库系统的,但是这并不代表不能对其它数据库系统实施类似的攻击。使用不同的方法,各种数据库都有可能遭殃。

预防措施
也许有人会自我安慰,说攻击者要知道数据库结构的信息才能实施上面的攻击。没错,确实如此。但没人能保证攻击者一定得不到这些信息,一但他们得到了,数据库有泄露的危险。如果你在用开放源代码的软件包来访问数据库,比如论坛程序,攻击者就很容得到到相关的代码。如果这些代码设计不良的话,风险就更大了。
这些攻击总是建立在发掘安全意识不强的代码上的。所以,永远不要信任外界输入的数据,特别是来自于客户端的,包括选择框、表单隐藏域和 cookie。就如上面的第一个例子那样,就算是正常的查询也有可能造成灾难。
永远不要使用超级用户或所有者帐号去连接数据库。要用权限被严格限制的帐号。
检查输入的数据是否具有所期望的数据格式。PHP 有很多可以用于检查输入的函数,从简单的变量函数和字符类型函数(比如 is_numeric(),ctype_digit())到复杂的 Perl 兼容正则表达式函数都可以完成这个工作。
如果程序等待输入一个数字,可以考虑使用 is_numeric() 来检查,或者直接使用 settype() 来转换它的类型,也可以用 sprintf() 把它格式化为数字。
Example#5 一个实现分页更安全的方法
复制PHP内容到剪贴板
PHP代码:
settype($offset, 'integer');
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
// 请注意格式字符串中的 %d,如果用 %s 就毫无意义了
$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
                 $offset);

使用数据库特定的敏感字符转义函数(比如 mysql_escape_string() 和 sql_escape_string())把用户提交上来的非数字数据进行转义。如果数据库没有专门的敏感字符转义功能的话 addslashes() 和 str_replace() 可以代替完成这个工作。看看第一个例子,此例显示仅在查询的静态部分加上引号是不够的,查询很容易被攻破。
要不择手段避免显示出任何有关数据库的信心,尤其是数据库结构。参见错误报告和错误处理函数。
也可以选择使用数据库的存储过程和预定义指针等特性来抽象数库访问,使用户不能直接访问数据表和视图。但这个办法又有别的影响。
除此之外,在允许的情况下,使用代码或数据库系统保存查询日志也是一个好办法。显然,日志并不能防止任何攻击,但利用它可以跟踪到哪个程序曾经被尝试攻击过。日志本身没用,要查阅其中包含的信息才行。毕竟,更多的信息总比没有要好。

时间: 2024-11-27 17:36:56

防sql注入的相关文章

EasyASP v2.2新功能介绍(1):Easp是如何实现防sql注入的

EasyASP终于到v2.2了,目前还在完善手册,群里有很多人问如何使用的问题 ,所以打算在写手册的同时写一些新功能的介绍,方便使用Easp 的童鞋们快速 进入状态.说实话,看到这么多人还在写ASP.还在支持Easp,觉得蛮难得的, 所以也一直没有丢下Easp的开发,还是希望Easp能给最后的ASPer们一点微薄的 帮助. EasyASP v2.2的改动比较大,放弃了不少原来我觉得不好用的方法,当然, 更多的是加入了不少我觉得会用得很哈屁的新功能.这是这个系列的第一篇文章 ,准备讲讲EasyAS

防SQL注入:生成参数化的通用分页查询语句

前些时间看了玉开兄的"如此高效通用的分页存储过程是带有sql注入漏洞的"这篇文章,才突然想起 某个项目也是使用了累似的通用分页存储过程.使用这种通用的存储过程进行分页查询,想要防SQL注入 ,只能对输入的参数进行过滤,例如将一个单引号"'"转换成两个单引号"''",但这种做法是不安全 的,厉害的黑客可以通过编码的方式绕过单引号的过滤,要想有效防SQL注入,只有参数化查询才是最终 的解决方案.但问题就出在这种通用分页存储过程是在存储过程内部进行SQ

PHP用PDO防Sql注入注意事项

在PHP 5.3.6及以前版本中,并不支持在DSN中的charset定义,而应该使用PDO::MYSQL_ATTR_INIT_COMMAND设置初始SQL, 即我们常用的 set names gbk指令. 为何PDO能防SQL注入? 请先看以下PHP代码:  代码如下 复制代码 <?php $pdo = new PDO("mysql:host=192.168.0.1;dbname=test;charset=utf8","root"); $st = $pdo-&

php mysql_real_escape_string防sql注入详解

mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符.下列字符受影响:  代码如下 复制代码 x00 n r ' " x1a 如果成功,则该函数返回被转义的字符串.如果失败,则返回 false. 易利用下面的这个函数,就可以有效过滤了.  代码如下 复制代码 function safe($s){ //安全过滤函数 if(get_magic_quotes_gpc()){ $s=stripslashes($s); } $s=mysql_real_es

在Global.asax文件里实现通用防SQL注入漏洞程序(适应于post/get请求)_实用技巧

首先,创建一个SQLInjectionHelper类完成恶意代码的检查 代码如下: 复制代码 代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Text.RegularExpressions; /// <summary> ///SQLInjectionHelper 的摘要说明 /// </summary> public cla

discuz防SQL注入程序代码

discuz 是一套通用的 PHP 社区论坛软件系统,在国内占有大量的用户群体,是做论坛的首选系统,在很早的时候就用 discuz 做论坛系统,感触最深的应该就是论坛的安全问题了,以前使用的时候,经常会有大量的信息进行注入,真是防不胜防. 好在 discuz 系统的更新很迅速,每一次的安全问题很快就得到了更新,而最头疼的问题恐怕就是 sql 的注入了,其实不只 discuz 系统,互联网上进行网络攻击的 SQL 注入是很可怕的,虽然 discuz 系统现有的安全问题已经非常完善了,但因为系统功能

Black Hat|长亭科技:防SQL注入利器-SQLChop

本文讲的是 Black Hat|长亭科技:防SQL注入利器-SQLChop,当程序过分信任用户的输入,直接将用户的输入与后台的SQL语句拼接在一起并执行时,如果用户输入带有恶意,SQL注入就发生了. 美国当地时间8月5日,国内安全新兴企业长亭科技在黑帽大会的军火库分会场(Arsenal),现场为来自全球各地的安全从业人员进行技术讲解,并演示他们的"无规则SQL注入攻击检测与防御引擎". 结合统计资料和实际情况来看,SQL注入仍然占据互联网威胁安全事件中非常大的比例(接近1/3)而且并没

asp.net防sql注入多种方法与实例代码应用(1/4)

asp教程.net防sql注入多种方法与实例代码应用 清除Request方法的注入问题         static string[] get_sql_a()         {             string Sql_1 = "exec|insert+|select+|delete|update|count|master+|truncate|char|declare|drop+|drop+table|creat+|creat+table";             string

asp防sql注入源程序

<% squery=lcase(Request.ServerVariables("QUERY_STRING")) sURL=lcase(Request.ServerVariables("HTTP_HOST")) SQL_injdata =":|;|>|<|--|sp_|xp_||dir|cmd|^|(|)|+|$|'|copy|format|and|exec|insert|select|delete|update|count|*|chr|

实践有效的网站防SQL注入方法(二)

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 姊妹篇"<实践有效的网站防SQL注入(一)>"跟大家交流了防止sql注入的黄金方法,从开发入手,在两个层次解决,我想如果大家按照介绍的步骤都能够做到,我想大家应该能够做到很好的防御效果.但我们说,没有100%的安全,网站的微小功能变动或升级都可能会对全局造成影响,这也就是为什么eesafe网站安全联盟收录的网站