数据库安全之SQL注入
许多 web 开发者没有细致到 SQL 查询是可以被窜改的,因此把 SQL 查询当作可信托的下令。殊不知道,SQL 查询可以绕开拜访控制,从而绕过身份验证和权限查抄。更有甚者,有可能经过 SQL 查询去运行主机操纵体系级的下令。
间接 SQL 下令注入便是攻击者常用的一种创建或修正已有 SQL 语句的技术,从而到达获得隐藏数据,或笼罩关键的值,甚至执行数据库主机操纵体系下令的目标。这是经过应用程序获得用户输入并与静态参数组分解 SQL 查询来完成的。下面将会给出一些真实的例子。
由于在缺乏对输入的数据举行验证,而且利用了超等用户或其它有权创建新用户的数据库帐号来毗连,攻击者可以在数据库中新建一个超等用户。 例子 27-2. 一段完成数据分页表现的代码……也可以被用作创建一个超等用户(PostgreSQL体系)。
$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; 只不外是为了提供一个正确的偏移量以便补充完整原来的查询,使它不要堕落罢了。
注: -- 是 SQL 的解释标志,一般可以利用来它报告 SQL 解释器忽略背面的语句。
对表现搜索效果的页面动手是一个能失掉密码的可行步伐。攻击者所要做的只不外是找出哪些提交上去的变量是用于 SQL 语句而且处置惩罚不妥的。而这类的变量通常都被用于 SELECT 查询中的条件语句,如 WHERE, ORDER BY, LIMIT 和 OFFSET。如果数据库支持 UNION 结构的话,攻击者还可能会把一个完整的 SQL 查询附加到原来的语句上以便从恣意数据表中失掉密码。因此,对密码字段加密是很紧张的。 例子 27-3. 表现文章……以及一些密码(任何数据库体系)
$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 子句动手,这样他们就可以更改数据表中的一些数据。这种环境下必需要知道数据库的结构才气修正查询乐成举行。可以经过表单上的变量名对字段举行猜测,或者举行暴力破解。对付寄存用户名和密码的字段,命名的要领并未几。 例子 27-4. 从重设密码……到获得更多权限(任何数据库体系)
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
?>
但是歹意的用户会把 ' or uid like'%admin%'; -- 作为变量的值提交给 $uid 来转变 admin 的密码,或者把 $pwd 的值提交为 "hehehe', admin='yes', trusted=100 "(背面有个空格)去获得更多的权限。这样做的话,查询语句现实上就酿成了:
// $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
...;";
?>
下面这个可怕的例子将会演示怎样在某些数据库上执行体系下令。 例子 27-5. 攻击数据库所在主机的操纵体系(MSSQL Server)
$query = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);
?>
如果攻击提交 a%' exec master..xp_cmdshell 'net user test testpass /ADD' -- 作为变量 $prod的值,那么 $query 将会酿成
$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 办事又有足够的权限的话,攻击者就可以获得一个体系帐号来拜访主机了。
注: 虽然以上的例子是针对某一特定的数据库体系的,但是这并不代表不克不及对其它数据库体系实行类似的攻击。利用不同的要领,各种数据库都有可能遭殃。
预防步伐
大概有人会自我慰藉,说攻击者要知道数据库结构的信息才气实行上面的攻击。没错,的确如此。但没人能包管攻击者肯定得不到这些信息,一但他们失掉了,数据库有泄漏的危险。如果你在用开放源代码的软件包来拜访数据库,比如论坛程序,攻击者就很容失掉到相关的代码。如果这些代码计划不良的话,风险就更大了。
这些攻击总是建立在掘客安全认识不强的代码上的。所以,永远不要信托外界输入的数据,特别是来自于客户端的,包括选择框、表单隐藏域和 cookie。就如上面的第一个例子那样,就算是正常的查询也有可能形成灾祸。
永远不要利用超等用户或全部者帐号去毗连数据库。要用权限被严格限制的帐号。
查抄输入的数据是否具有所盼望的数据格式。PHP 有许多可以用于查抄输入的函数,从简单的变量函数和字符范例函数(比如 is_numeric(),ctype_digit())到庞大的 Perl 兼容正则表达式函数都可以完成这个工作。
如果程序等待输入一个数字,可以思量利用 is_numeric() 来查抄,或者间接利用 settype() 来转换它的范例,也可以用 sprintf() 把它格式化为数字。 例子 27-6. 一个完成分页更安全的要领
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() 可以取代完成这个工作。看看第一个例子,此例表现仅在查询的静态部门加上引号是不够的,查询很容易被攻破。
要不择本领制止表现出任何有关数据库的信心,尤其是数据库结构。拜见错误陈诉和错误处置惩罚函数。
也可以选择利用数据库的存储过程和预定义指针等特性来抽象数库拜访,利用户不克不及间接拜访数据表和视图。但这个步伐又有另外影响。
除此之外,在容许的环境下,利用代码或数据库体系保存查询日记也是一个好步伐。显然,日记并不克不及防备任何攻击,但利用它可以跟踪到哪个程序曾经被尝试攻击过。日记本身没用,要查阅其中包含的信息才行。毕竟,更多的信息总比没有要好。
- 文章作者: 福州军威计算机技术有限公司
军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。
TAG:
评论加载中...
|