Java教程

网络应用层安全之SQL注入

本文主要是介绍网络应用层安全之SQL注入,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

网络应用层安全之SQL注入

在这里插入图片描述

注入攻击,就是数据与代码没有分离产生的结果,计算机或服务器把用户输入的数据当做代码执行,其中有两个关键条件:①用户能够控制输入,②代码进行了拼接。

SQL注入是发生在 Web 程序中数据库层的安全漏洞,是网站最常见最简单的漏洞。网站考虑地再详细也会被黑客们抓到漏洞和破绽,SQL注入利用程序对输入数据不会判断和处理进行恶意攻击,使用具有特定意义的SQL 语句执行非法操作。

简言之,SQL 注入就是在用户输入的字符串中加入 SQL 语句,如果程序没有对输入进行处理,那么这些注入进去的 SQL 语句就会被数据库服务器误认为是正常的 SQL 语句而运行,攻击者就可以执行计划外的命令或访问未被授权的数据。

原理

1. 通过服务器返回的错误信息给黑客提供攻击信息

如果网站web服务器开启了错误回显,则会给攻击者提供方便。攻击者在输入中输入不合理的字符,通过返回的错误信息,攻击者可以知道服务器使用的哪种数据库,查询的语句等等信息,有助于构造能攻击该网站的注入攻击语句。

因此在后续的预防中会提到“不要给用户返回错误信息”,但是即使服务器关闭了这个错误回显,攻击者也可以通过“盲注”的方式,即构造简单的条件语句,根据页面是否发生变化来判断注入的SQL语句是否执行。

2. 与原本SQL语句进行拼接,形成新的指令

复习SQL的增删改查

// 插入单行数据
select into ... values ...

// 表添加到新表
select into ... select ... from ...

// 删除数据某些数据
delect from ... where ...

// 删除整个表的数据
truncate table ...

update ... set .. where ...

例如,对一个接受输入数据的数据库语句:

SELECT * FROM users WHERE user_id = $user_id

如果传入参数为:1234; DELETE FROM users

那么传入的参数会与SQL语句合并,计算机理解为新的SQL语句

SELECT * FROM users WHERE user_id = 1234; DELETE FROM users

则会删除 users 表中的所有数据。

3. 利用插入注释执行非法命令

复习SQL的 or

使用 AND 来显示所有姓为 “Carter” 并且名为 “Thomas” 的人:

SELECT * FROM Persons WHERE FirstName='Thomas' AND LastName='Carter'

使用 OR 来显示所有姓为 “Carter” 或者名为 “Thomas” 的人:

SELECT * FROM Persons WHERE firstname='Thomas' OR lastname='Carter'

例如,对某个查询语句

SELECT COUNT(*) AS 'num' FROM game_score WHERE game_id=24411 AND version=$version

如果输入 version 包含了恶意的字符串'-1' OR 3 AND SLEEP(500)--,那么最终查询语句会变为:

SELECT COUNT(*) AS 'num' FROM game_score WHERE game_id=24411 AND version='-1' OR 3 AND SLEEP(500)--

计算机检测到 SLEEP(500) 将导致 SQL 语句一直运行,恶意消耗性能资源

或者,查询语句为:

select * from users where nickname='{user_name}'

当输入user_name为(’ or 1='1)时,语句变为

select * from users where user_name='' or 1='1'

可以让黑客进入系统

4. 添加额外条件

在 SQL 语句中添加一些额外条件,以此来改变执行行为。条件一般为真值表达式。例如:

UPDATE users SET userpass='$userpass' WHERE user_id=$user_id;

如果 user_id 被传入恶意的字符串“1234 OR TRUE”,那么最终的 SQL 语句会变为:

UPDATE users SET userpass= '123456' WHERE user_id=1234 OR TRUE;

这将更改所有用户的密码。

预防

  • 字符串长度验证,仅接受指定长度范围内的变量值。sql注入脚本必然会大大增加输入变量的长度,通过长度限制,比如用户名长度为 8 到 20 个字符之间,超过就判定为无效值。
  • 不管客户端是否做过数据校验,在服务端必须要有数据校验(长度、格式、是否必填等等),在数据提交到数据库之前,就过滤内容,正则表达式很不错
  • 对单引号和双"-"、下划线、百分号等sql注释符号进行转义
  • 对接收的参数进行类型格式化,如id参数值获取后,进行int类型转换
  • 参数化查询(避免动态拼装SQL):连接并访问数据时,使用参数来给传递值。在使用参数化查询的情况下,数据库服务器不会将参数的内容视为 SQL 语句的一部分来进行处理,先进行数据库语句的编译,再套用参数运行。因此就算参数中含有破坏性的指令,也不会被数据库所运行。MySQL 的参数格式是以“?”字符加上参数名称而成。
UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4
  • 永远不要使用管理员权限的数据库连接(sa、root、admin),为每个应用使用单独的专用的低特权账户进行有限的数据库连接。限制数据库权限和特权,将数据库用户的功能设置为最低要求。
  • 不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。这样对方就算获取到整个表的数据内容,也没什么价值。
  • 避免直接向用户显示数据库错误,因为攻击者可以使用这些错误消息来获取有关数据库的信息。应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装,把异常信息输出到日志而不是在页面中展示。
  • 做好 XSS 跨站攻击的防护,防止攻击者伪造管理员信息进入系统后台。
这篇关于网络应用层安全之SQL注入的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!