SQL注入式攻击

转自点击打开链接

       所谓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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于 SQL 注入的培训材料,我可以提供一些基本的知识和防范措施供您参考。请注意,以下内容仅供教育目的,不得用于非法活动。 1. 什么是 SQL 注入? SQL 注入是一种常见的网络安全漏洞,攻击者利用此漏洞在应用程序的数据库查询插入恶意的 SQL 代码。这可能导致攻击者获取敏感信息、修改数据或执行其他恶意操作。 2. 注入攻击的原理 注入攻击利用应用程序未正确过滤或转义用户输入的数据,使得攻击者能够将恶意 SQL 代码插入到应用程序的数据库查询。如果应用程序没有正确处理用户输入,攻击者可以利用这一点执行任意的数据库操作。 3. 防范 SQL 注入的措施 - 使用参数化查询或预编译语句:参数化查询可以防止恶意代码插入,确保用户输入的数据被视为数据而不是代码。 - 输入验证与过滤:对用户输入进行严格验证和过滤,确保只接受预期的数据类型和格。 - 最小权限原则:应该为数据库用户提供最小权限,限制其对数据库的访问和操作。 - 错误处理与日志记录:及时捕获并记录应用程序的错误信息,以便及时发现和修复漏洞。 - 定期更新和维护:及时更新和维护应用程序和相关的数据库,以修复已知的漏洞和安全问题。 4. 继续学习 如果您对 SQL 注入和其他网络安全问题感兴趣,可以参考以下资源进行进一步学习: - OWASP(开放 Web 应用安全项目)官方网站:https://www.owasp.org/ - SQL 注入攻击的防范指南:https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet 请记住,安全是一个持续的过程,不仅需要合适的技术措施,还需要不断的学习和保持警惕。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值