欢迎进入武汉轻洽网络技术有限公司官方网站!
服务热线:027-51831034,13971151027
   2年前 (2017-06-24)  Sql |   抢沙发  19 
文章评分 0 次,平均分 0.0

转自点击打开链接
所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。

一、SQL注入攻击的种类

首先要了解注入方式有哪些种类,才能更好的防御注入。

1. 没有正确的过滤转义字符
用户的输入没有进行转义字符过滤,而被传递给SQL语句,从而导致攻击者对数据库的操作,例如:
SELECT * FROM users WHERE name = ?如果用户名name被恶意伪造为
zhang3' or '1'=1此时SQL语句就会发生变化:
SELECT * FROM users WHERE name = 'zhang3' OR '1'='1';
因为'1'='1'是正确的,如果这段代码被用语一个认证过程,那么就能强迫选择一个合法的用户名。

2. 错误类型
如果程序没有实施类型强制,就会发生这种形式的攻击,例如:
UPDATE subject SET score= ? where name = 'zhang3'
如果成绩被恶意伪造为
100; DROP TABLE users #
此时SQL语句就会发生变化
UPDATE subject SET score= 100; DROP TABLE users; # where name = 'zhang3'
它会将“users”表从数据库中删除

3. 防注入函数中的漏洞
有时,一些防注入的过滤函数中也存在着漏洞,如PHP中的addslash,以及MYSQL服务器中mysql_real_escape_string()函数漏洞。这种漏洞允许一个攻击者根据错误的统一字符编码执行一次成功的SQL注入式攻击,例如:

输入
$name=41?' or sleep(10.10)=0 limit 1#

当使用addslashes($name)
//SQL输出可能为:
SELECT COUNT(*) AS total FROM users WHERE `name` LIKE 'A?\\\' or sleep(10.10)=0 limit 1#%';

其原因是addslash对于字符?'的漏洞。该漏洞最早2006年被国外用来讨论数据库字符集设为GBK时,0xbf27本身不是一个有效的GBK字符,但经过 addslashes() 转换后变为0xbf5c27,前面的0xbf5c是个有效的GBK字符,所以0xbf5c27会被当作一个字符0xbf5c和一个单引号来处理,结果漏洞就触发了。
网络上查询到有人说,当mysql_real_escape_string检测到的编码方式跟client设置的编码方式(big5/bgk)不一致时,mysql_real_escape_string跟addslashes是没有区别的

4. 盲目SQL注入式攻击
当一个Web应用程序容易被攻击,而其结果对攻击者却不可见时,就会发生所谓的盲目SQL注入式攻击。有漏洞的网页可能并不会显示数据,而是根据注入到合法语句中的逻辑语句的结果显示不同的内容。这种攻击相当耗时,需要攻击者根据间接数据去推断,但是一旦漏洞的位置和目标信息的位置被确立以后,一种称为Absinthe的工具就可以使这种攻击自动化。
5.条件响应
有一种SQL注入能够迫使数据库在一个普通的应用程序上计算一个逻辑语句的,例如:
SELECT title FROM book WHERE bookId = '234' AND 1=1
这会产生一个标准的输出,而语句
SELECT title FROM book WHERE bookId = '234' AND 1=2

在页面容易被SQL注入式攻击时,它有可能给出一个不同的结果,根据二者关系来判断程序错误处理逻辑。

6.条件性差错
条件性差错是一种盲目的SQL注入,如果WHERE语句为真,SQL注入会迫使数据库执行一个引起错误的语句,从而导致一个SQL错误。例如:
SELECT 1/0 FROM users WHERE rname='zhang3'
显然,如果用户zhang3存在的话,被零除将导致错误。

7.时间延误

时间延误是一种盲目的SQL注入,根据所注入的逻辑,它可以导致SQL引擎执行一个长队列或者是一个时间延误语句。攻击者通过衡量页面加载的时间,可以判定所注入的语句是否执行。

二、SQL注入的主要形式

1. 直接攻击,
将代码插入到与 SQL 命令中,并使用户输入的注入代码得意执行。
例如像表中插入一条数据,
INSERT INTO tbl_name(col1,col2,col3,col4) VALUES (xxx,xxxx,$_GET[id],xxx);
Mysql 支持在 value 中使用 select 子查询
INSERT INTO tbl_name (col1,col2,col3,col4) VALUES (xxx, xxxx, (SELECT * FROM tbl_other), xxx);
2. 间接攻击,
会将恶意代码注入到表中存储或作为元数据存储的字符串。在存储的字符串中会连接到到一个动态 SQL 命令中,以执行该恶意代码。
例如在已经过滤输入内容后,也可能产生二次攻击
Username: admin'--
Password: password
程序正确的过滤了单引号,'insert'语句如下:
INSERT INTO users VALUES ('admin''--', 'password')
假设程序允许用户更改密码,用户名为admin'--,上面的查询就变成了这样:
update users set password = 'password' where username = 'admin'--'
因此攻击者通过注册一个admin'--用户修改了admin的密码

三、如何防范SQL注入

1. 验证用户输入内容,使恶意参数不能直接被嵌入到SQL语句中,但是这种方法往往不能够考虑的很全面。
2. 使用参数化的过滤性语句,参数化的语句使用参数不是将用户输入直接嵌入到SQL语句中。用户输入就被限于一个参数。
3. 避免使用解释程序,因为这是攻击者借以执行非法命令的手段。
4. 精心编制错误消息,攻击者可以利用错误信息来获取数据库信息;
5. 确保数据库安全,使用一些额外的方式强化数据库安全。首先锁定应用数据,采用最小权限登陆数据库,撤销不必要的公共许可,使用强大的加密技术来保护敏感数据并维护审查跟踪。其次锁定数据库,对额外的系统对象锁定,约束即席查询,加强对验证周边严控制,最低权限操作系统账户并确保数据库打了最新补丁。
6. 实施代码的安全检查。首先,要在部署应用之前实施安全测试,还应在部署之后用漏洞扫描工具和站点监视工具对网站进行测试。
四、PHP处理SQL注入方法

处理SQL注入的方法很多,先总结以下两种方案:
1. 使用传统方法来避免SQL注入风险
采用输入验证并过滤输入数据的方式,网上有很多诸如此类的方法,下面是程序员小辉在一片文章中提到过的方法,是一个用来获取安全参数的方法,为了防止用户的错误数据和 php mysql 注入。
define(XH_PARAM_INT,0);
define(XH_PARAM_TXT,1);
function PAPI_GetSafeParam($pi_strName, $pi_Def = , $pi_iType = XH_PARAM_TXT)
{
if ( isset($_GET[$pi_strName]) )
$t_Val = trim($_GET[$pi_strName]);
else if ( isset($_POST[$pi_strName]))
$t_Val = trim($_POST[$pi_strName]);
else
return $pi_Def;

// INT
if ( XH_PARAM_INT == $pi_iType)
{
if (is_numeric($t_Val))
return $t_Val;
else
return $pi_Def;
}

// String
$t_Val = str_replace(, ,$t_Val);
$t_Val = str_replace(, ,$t_Val);
$t_Val = str_replace(, ,$t_Val);
if ( get_magic_quotes_gpc() )
{
$t_Val = str_replace(\\\, ,$t_Val);
$t_Val = str_replace(\\'', ',$t_Val);
}
else
{
$t_Val = str_replace(\, ,$t_Val);
$t_Val = str_replace(', ',$t_Val);
}
return $t_Val;
}
2. 使用PDO查询Mysql来避免SQL注入风险
当使用传统的mysql_connect、mysql_query方法来连接查询数据库时,如果过滤考虑的不够全面,就有SQL注入的防线,导致网站被攻击。虽然mysql_real_escape_string()函数能过滤用户提交的,但是也有0xbf27转换0xbf5c27的漏洞,而使用PDO的prepare方法来组合sql语句,避免直接使用用户提交的来作为查询条件,从而可以降低SQL注入的风险。
下面我们看一段代码使用实例:
$dbh = new PDO(mysql:host=localhost; dbname=demo, user, pass
$dbh-setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh-exec(set names 'utf8'
$sql=select * from user where name = ? and password = ?
$stm = $dbh-prepare($sql);
$exec= $stm-execute(array($name, $password));
if ($exec) {
$row = $stm-fetch(PDO::FETCH_ASSOC);
}
$dbh = null;
在使用PDO访问mysql数据库时,真正的real prepared statements默认情况下是不使用的,setAttribute这一行强制性的禁用PDO模拟预处理语句,这样可以确保SQL语句和相应的在传递到mysql服务器之前是不会被PHP解析的。
当调用prepare()时,查询语句已经发送给了数据库服务器,此时只有占位符?发送到数据库服务器,当调用execute()时,用户提交的数据才会传递给数据库,它们是分开传送的,两者独立,可以避免SQL注入。
但是PDO并不能帮助完全防范SQL注入,例如:
1. 不能让占位符?代替一组(select * from user where uid in (123, 321,445))
2. 不能让占位符?代替表明或列名(select * from user order by score)
3. 不能让占位符?代替其他SQL语法(select extract(year from orderdata) as orderyear from orders where orderid=1)

 

除特别注明外,本站所有文章均为轻洽网络原创,转载请注明出处来自https://www.qingqia.net/432.html

关于

发表评论

暂无评论

切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

切换登录

注册

扫一扫二维码分享