SQL注入教程——(一)SQL注入原理

来源:互联网 发布:java的输入输出流 编辑:程序博客网 时间:2024/05/29 16:45

本系列文章将从SQL注入基础讲解,面向初学者,循序渐进。
如有不足,敬请指正。

前置技能

  1. 了解SQL语言、语法、操作、常用函数
    (基本的SQL数据库操作是进行SQL注入攻击的基础)
  2. 了解PHP语言,以及PHP+SQL的常用组合操作
  3. 了解网站架构、不同数据库的差异
  4. 了解burp suite、sqlmap等工具
  5. 了解http基本的get、post方法

本文以假设存在的www.test.com/index.php 注入页面为例

1.什么是SQL注入

所谓SQL注入,就是通过把SQL命令插入到 Web表单提交 或 URL 或 页面请求等的查询字符串中,最终达到欺骗服务器执行恶意的SQL命令。

即:将构造的SQL语句插入到正常提交的字符串中,并使服务器将字符串中的命令解析为可执行命令而不是字符串。

e.g.-1
www.test.com/index.php 的源码中有如下的代码:

 $query="select name from users where id='$_GET['id']'"

以get方式获取参数id,基于用户输入的参数id找到相应的name,正常情况下id为1,2等,比如url为:
www.test.com/index.php?id=1
此时数据库执行的命令为:

select name from users where id='1'

但当用户输入如下url时:
www.test.com/index.php?id=1' union select database()%23(‘%23’为’#’的url编码,’#’为mysql注释符,注释掉后面的语句)
此时数据库执行的命令是:

select name from users where id='1' union select database()#'

不仅可以得到id为1的name字段内容,还可以得到当前数据库名

e.g.-2
当前数据库存在名为users的表,其中包含username、passwd两列,该表存在一条username为admin,passwd为password的数据。
网页核心源码如下:

$query="select * from users where username='$_POST['username']' and passwd='$_POST['password']'"

以post方式获取用户输入的username和password
正常情况下提交的username为admin,password为password 方可以验证成功而登录,且数据库执行的命令为:

select * from users where username='admin' and passwd='password'

此时数据库返回username为admin,password为password 的数据项,
但是当只知道username为admin而不知道密码时怎么办呢?
构造username为admin,password为' or '1'='1 ,此时执行的SQL语句为:

select * from users where username='admin' and passwd='' or '1'='1'

由于'1'='1' 条件恒为真,该语句将返回users表中的所有数据(and优先级高于or的优先级,由于表中不存在username='admin' and passwd='' 的数据项,则该条件为假,然后结合or '1'='1',条件变为永真,且*为通配符,所以该条SQL语句变为查找users表中的所有数据项,由于该表仅有一条数据项,所以匹配到的就是admin这条数据)
此时虽然不知道密码,但也可验证成功而登录。
如果username和password都不知道呢?
其实同理即可

2.SQL注入的产生

  • 动态字符串构建

    • 不正确的处理转义字符(宽字节注入)
    • 不正确的处理类型(报错泄露信息)
    • 不正确的处理联合查询
    • 不正确的处理错误(报错泄露信息)
    • 不正确的处理多次提交(二次注入)
  • 不安全的数据库配置

    • 默认预先安装的用户
    • 以root、SYSTEM 或者Administrator权限系统用户来运行
    • 默认允许很多系统函数(如xp_cmdshell, OPENROWSET 等)

3.SQL注入的作用

  • 绕过登录验证(万能密码等)
  • 获取敏感数据(获取数据库中的信息)
  • 文件操作(读取、写入文件等)
  • 执行系统命令
    等等

4.常见的SQL注入分类

1. 数字型注入

这类注入主要特点是不需要考虑引号的闭合,以www.test.com/index.php 为例,核心源码类似于:

$query="select name from users where id=$_GET['id']"

注意与e.g.-1的不同
http://www.text.com/index.php?id=1 正常
http://www.test.com/index.php?id=1' 运行异常
http://www.test.com/index.php?id=1 and 1=1 正常
http://www.test.com/index.php?id=1 and 1=2 运行异常
此方法也可用于测试某页面是否存在数字型注入。

2.字符型注入

这类注入需要注意引号的闭合 ,核心源码类似如下:

$query="select name from users where id='$_GET['id']'"

http://www.test.com/index.php?id=1 正常
http://www.test.com/index.php?id=1' 运行异常
http://www.test.com/index.php?id=1' and 1=1 运行异常
http://www.test.com/index.php?id=1' and 1=1%23 正常
http://www.test.com/index.php?id=1' and '1'='1 正常

SQL注入还有基于报错型SQL注入、基于布尔/时间的SQL注入、可联合查询的SQL注入等等

5.SQL注入攻击的影响范围

  • 数据库:MS-SQL Server、Oracle、My-SQL、DB2、Informix等所有基于SQL语言标准的数据库软件;

  • 应用程序:ASP、PHP,JSP、CGI、CFM等所有应用程序;