一、SQL注入原理:

注入:通过GET / POST 方式把恶意的语句插入到原来的代码中,导致恶意的语句被执行。

SQL 注入:攻击者探测出开发者编程过程中的漏洞,利用这些漏洞,将一种将恶意的SQL代码插入或添加到应用(用户)的输入参数的攻击,巧妙的构造SQL语句,对数据库系统的内容进行直接检索或修改。

SQL注入的前提条件:

  • 用户输入(参数)可控。
  • 数据(参数)带入到后端的数据库中进行查询

二、SQL注入流程:

(1)信息收集:

  • 数据库类型 查看sql注入页面 是否报错,来判断数据库类型
  • 数据库版本 函数: version()、@@version
  • 数据库用户 user() 、 system_user
  • 数据库权限 —is-dba 查看数据库是否是高权限

收集的信息还有很多

(2)数据库数据获取: 1. 暴力破解 2. 通过语句查询

  1. 获取库信息
    2. 获取表信息
    3. 获取列信息
    4. 获取数据
    access 只有表,通过暴力破解,通过表再去获取

    (3)权限提升:

  2. 执行命令 SQL Server SA提权、mysql UDF、MOF提权
    2. 读文件 读中间件配置文件,该数据库配置文件
    3. 写文件 写webshell 到网站

三、关于MySQL数据库的user表段

MySQL 无论是4.x 还是 5.x 都有一个独立的数据库,名字就叫 ”mysql“ ,当中有很多数据表,保存MySQL的各种设置参数。其中user表段设置了MySQL中数据库用户的部分信息。

user表段中,user字段为用户登录名,可以有相同的名字重复
image.png

MySQL 5.7.6 以后版本将原来的 pasword 字段修改为 authentication-string,
authentication_string 字段为登录密码哈希,是40位的密码,类似于MD5,可以在md5 在线破解网站进行破解。

host 字段设置的是这个用户可以在哪些机器上登录,如果为localhost表示只能本机登录,host可以是数据库IP 也可以是数据库服务器的名称,若host为 ” localhost ” 不一定表示没有希望,如果服务器某个网站装有 phpmyadmin 这个软件的话,是可以利用的。
image.png

file_priv字段规定了这个用户是不是可以读取硬盘里的文件,设置为Y表示允许,设置为N表示禁止。
image.png

四、常用的一些函数

  • user() :数据库的用户,格式为 user@server ,例如 root@localhost 通常最高管理账户为root ,服务器以 localhost 也就是本地居多,也可以是服务器名例如 mysqldbserver,也可以是IP 例如 192.168.100.111。所有的 user 都会在mysql 数据库中的user表段中记录,用于设置权限等。

  • current_user() 当前用户名,当前登陆的用户具有什么权限的话。

  • database() : 当前数据库名,网站建设者任意给予的数据库的名称

  • version() / @@version;: 当前使用的数据库的版本,一般为4.x、5.x或者版本更高。
  • @@datadir: 数据路径。数据库存储数据总要有个路径存放数据,就是这里
  • session_user() 链接数据库的用户名
  • @@version_comment 数据库服务器的信息
  • @@basedir mysql安装路径
  • @@version_compile_os 操作系统版本
  • @@version_compile_machine 查看机器的型号

hex() 和 unhex() : 有一些注入点由于数据库对数据字段的类型定义,可能不支持UNION 来显示不同类型的内容,所以使用hex对数据进行hex编码,或者直接将数据进行hex转码后,输入hex转码后的内容。

  • load_file: 这是mysql 以文本的形式读取文件的参数。

例如 linux 系统的网站 load_file(‘etc/passwd’) 或者 windows 系统的网站 load_file(‘c:\boot.ini’)。这个参数可以用的前提是,user() 用户在mysql.user表中的字段为 file_priv 设置为Y,查看是否有写入权限。需要注意的是,如果是windows 系统,保险起见将路径设置为双斜杠,因为双斜杠在计算机语言中是单斜杠的意思,如果为单斜杠。例如 d:\table ,那么这个路径中的 \t 就会解析成键盘上的 table 键, \n\r 类似。 很多时候php的网站的 gpf 会设置为ON ,(对特殊字符进行转义,将单引号 自动修改为 \’) 那么 load_file(’c:\boot.ini’) 就会变成 load_file(\’c:\\boot.ini\’) 出现语法错误,得不到结果。解决的方法就是对 c:\boot.ini 进行hex编码,输入hex转码得内容。

注意: secure_file_priv 必须为空,不能为NULL,否则不能去读文件的内容

secure-file-priv参数是用来限制LOAD DATA, SELECT … OUTFILE, and LOAD_FILE()传到哪个指定目录的。

  • ure_file_priv的值为null ,表示限制mysqld 不允许导入|导出
  • 当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下
  • 当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制

如何查看secure-file-priv参数的值:
show global variables like ‘%secure%’;

  • into outfile:将查询结果输出保存到一个文件中<br />/ ``` select ‘<?php phpinfo(); ?>’ into outfile “C:\phpStudy\MySQL\bin\1.php”;

select * from student into outfile ‘C:/phpStudy/MySQL/bin/test.php’;

  1. 需要注意的点:
  2. 1. outfile 可导出多行,并会在每⾏的结束加上换⾏符<br />如果test表中的内容有多行<br />![](https://cdn.nlark.com/yuque/0/2021/png/1442084/1614525075490-1c25f002-d424-4090-8d71-915714c0d21e.png#align=left&display=inline&height=48&margin=%5Bobject%20Object%5D&originHeight=48&originWidth=186&size=0&status=done&style=none&width=186)<br />导出效果<br />![](https://cdn.nlark.com/yuque/0/2021/png/1442084/1614525075522-d712747a-b6d6-4690-b38c-7315c57f5e0b.png#align=left&display=inline&height=36&margin=%5Bobject%20Object%5D&originHeight=36&originWidth=143&size=0&status=done&style=none&width=143)
  3. 1. outfile 将数据写到文件里时有特殊的格式转换<br />`a\naa\raaaa`写入时`\n`被转义,并且文件末尾加了一个新行<br />![](https://cdn.nlark.com/yuque/0/2021/png/1442084/1614525075481-4ba4cdc4-a2c2-4734-af80-6953836db350.png#align=left&display=inline&height=143&margin=%5Bobject%20Object%5D&originHeight=143&originWidth=548&size=0&status=done&style=none&width=548)<br />导致写shell时要注意特殊字符
  4. 1. outfile 的路径不能是0x开头或者char转换以后的路径,只能是引号包裹的路径<br />导致写shell时无法通过hex编码或char()来bypass引号转义等
  5. 1. 文件不能覆盖写入,所以写入文件必须为不存在
  6. SELECT <?php phpinfo() ?> into outfile '路径' 前提是gpf设置为off,有注入点,权限很大,file_privY,知道网站的真实路径。
  7. - dumpfile

select ‘<?php phpinfo(); ?>’ into dumpfile “C:\phpStudy\MySQL\bin\1.php”; select * from student into outfile ‘C:/phpStudy/MySQL/bin/test.php’; ``` 需要注意的点:

  1. dumpfile 只能导出一行
    2、SQL注入产生原理和常用的一些函数 - 图4
  2. dumpfile 在写⽂件时会保持⽂件的原⽣内容/原数据格式,适合写二进制文件,如exe文件,udf提权的dll文件
    2、SQL注入产生原理和常用的一些函数 - 图5
  3. dumpfile 的路径不能是0x开头或者char转换以后的路径
  4. 文件不能覆盖写入,所以写入文件必须为不存在


  • 导入语句load data infile()读文件

条件:

  • 所读文件的绝对路径
  • secure_file_priv 的值非NULL或包含了所读文件的绝对路径
  • mysql服务有对所读文件的读权限
  • mysql连接用户有FILE权限/如果指定LOCAL关键词则无需FILE权限
  • 如果是mysql8,需要SET GLOBAL local_infile=1;

<br />
load data infile()将所读文件内容存储到表中
load data [local] infile '/etc/passwd' into table result;
如果指定LOCAL关键词,则表明从客户端的主机上按路径读取文件,适合站库分离,无需FILE权限。

路径获取常见方法:
报错显示,遗留文件,漏洞报错,平台配置文件,爆破等

五、 MySQL字符串拼接和字符串截取函数

(1)concat

  • select concat(id,’|’,username,’|’,password) from users; 每个字段必须指定分隔符,去拼接字符串

image.png

(2)concat_ws

  • select concat_ws(‘|’,id,username,password) from users; 用固定的分隔符去拼接id,username,password。

image.png

(3) group_concat

  • select group_concat(‘\n’,username) from users; \n (
    浏览器)换行 去拼接字符串

image.png

(4)substr 截取函数

select substr((select username from users limit 0,1),1,2);
limit m,n 函数是从m行开始查m+n行。 substr 从第一位开始截取两位
image.png

(5)mid 函数

select substr((select username from users limit 0,1),1,2);
从第二个字母截取三个字段
image.png

(6)left 函数

  • select left(‘Avenue’,3); 从左截取两位

image.png

(7)right 函数

  • select right(‘Avenue’,2); 从右截取字符串个数

image.png

(8)locate 函数

locate(substr,str,pos):返回字符串1在字符串2中第一次出现的位置,从位置pos开始算起;
如果返回0,表示从pos位置开始之后没有了,如果返回值 大于0,表示有。
2、SQL注入产生原理和常用的一些函数 - 图13
2、SQL注入产生原理和常用的一些函数 - 图14

由于这函数的用法,不能结合ascii或者ord来使用,只能结合if来使用,下面来操作一下。
select locate(‘security’,’1234security’); 返回第一个字符串首次在第二个字符串出现得位置
image.png

(9)ascii、ord 函数

返回指定的ASCII字符对应的值
image.png

  • select ascii(‘a’);
  • select ord(‘a’);

(10)char 函数

返回指定数字对应的ascii码字符函数:
select char(97);
image.png

(11)length、count 函数

计算长度、数量的函数

  • select length(database()); 查询数据库的长度
  • select count(*) from users; users表里13条数据。

image.png