Sqli-labs-Less-23~24


Less-23


看到这个熟悉的get提交方式;按照咱们以往的思路就是探测初闭合方式,并使其闭合,然后拼接咱们的查询语句进行注入攻击。

害,按着咱们的老套路走发现行不通咯;这个时候不要犹豫直接查看源码。

原来是这个小可爱在捣鬼,这时候介绍一个替换函数
preg_replace()函数:preg_replace(要替换的东西,替换成啥东西,哪个里面的东西需要替换)
所以这个函数的功能就是将id中有含#和-的符号替换成空格;这也是为什么咱们后面的注释符无法生效的原因;又因为咱们的注释符无法生效,所以咱们的语句无法闭合;也就是查询语句无法生效,无法成功注入攻击;所以咱们得另想他法。
此时咱们先来看看咱们存在SQL注入的语句;

1
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

然后将咱们的语句拼接到里面;

1
SELECT * FROM users WHERE id='1'' LIMIT 0,1
1
SELECT * FROM users WHERE id='1' order by 3' LIMIT 0,1

此时会发现,咱们的查询语句后面都多了一个单引号,这很明显是一条错误的SQL。
经过查看学长们的博客发现了两种解决方法:


方法一:就是让所有的引号都找到自己的另一半

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


此时已经行得通了;页面回显正常。
补充:然后两个引号之间闭合,引号的内容会变成字符串,所以这个时候我们就无法使用order by 来查询字段
数目。因为order by后面接的是数字;当我们使用增加引号闭合时,数字就会转换成字符串,导致order by 语句
无法实施。
注入姿势:联合注入
因为页面又显示位,所以可以使用联合注入


试了一下报错注入和盲注发现似乎行不通。


方法二:%00截断原理

在了解%00截断原理之前我们先了解一下0x00截断原理
0x00截断原理:
0x00是十六进制表示方法,是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符。系统在对文件名的读取时,如果遇到0x00,就会认为读取已结束。这个可以用在对文件类型名的绕过上。但要注意是文件的16进制内容里的00,而不是文件名中的00!遇到ascii码为零的位置就停止,而这个ascii码为零的位置在16进制中是00,用0x开头表示16进制,也就是所说的0x00截断。
%00截断原理:
%00是被服务器解码为0x00发挥了截断作用。
不过既然是截断了,我们在构建注入语句时一定要记得加上分号;

此时的order by语句就用得了
法一:联合注入
因为页面有显示位,所以可以使用联合注入

法二:报错注入:
因为页面的抱错信息正确;所以可以使用报错注入

法三:布尔盲注
因为当猜解正确时,页面会正常回显;当猜解错误时,页面会错误回显;故可以使用布尔盲注


Less-24 Second Order injections Real treat Stored injections

此关为二阶注入也称二次排序注入或者存储型的注入
原理:二次注入(存储型注入),这种手法所利用的原理是:在网站处理用户提交的数据的时候,只是将某些敏感字符进行了转义。因而使得用户第一次提交的时候不会被当做代码执行。但是这些数据存入数据库的时候却没有转义,而网站程序默认数据库中的数据都是安全的,当网站程序第二次调用刚才存储的脏数据的时候,则不会转义使用而是直接使用,因此就会达到注入的效果。
遇事不决,查看源码:
1.咱们先从登入的源码入手:

在这里可以看到在登陆的时候网站会接收用户输入的账号和密码,然后调用mysql_real_excape_string()处理
mysql_real_excape_string()函数:转义函数;转义字符串中特殊的字符
例:当我们输入admin’#时会将单引号转义;变成admin'#;使得咱们无法闭合语句;转义会将单引号当做内容进行查询而使得闭合作用失效。因此在这个页面我们无法注入。
2.既然登入不行咱们继续看注册页面的源码

依旧和登入源码相同,对咱们提交的用户名和密码进行了转义;所以这个界面也就不存在注入攻击
但是往下看我们发现了一个sql语句

当我们两次输入的密码相同时;后台会将我们注册的用户名和密码插入users表中;也就是表示注册成功。
例:当我们注册的用户名为admin’#密码为666时,sql语句会变成

1
insert into users ( username, password) values("admin\' #", "666");

在SQL执行的过程中,单个转义符号是透明的(相当于告诉SQL我后面的单引号是一个插入的值而不是字符串的闭合标志),也就是说最终存储在数据库中的用户名是admin’#。因为转义只是暂时的,存储以后还是以单引号的形式存在的。这个也就是原理中的:但是这些数据存入数据库的时候却没有转义
3.接下来咱们查看一下修改密码的源码

噢吼!咱们发现此处的用户名并没有被转义;此时的用户名就是咱们刚才注册的那个admin’#;既然这样那么这里极有可能存在注入点;当我们登入成功时程序直接从后台数据库中获取账户信息。那么获取到的数据就是刚才我们注册的admin’#了。然后直接将这个username拼接到SQL中去执行

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

当拼接之后:

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

因为此处的注释符起到了作用,所以此时的sql语句又会变成

1
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'

这样一来,#后面的语句都被注释掉了。那么这条语句改的则是admin账户的密码而不是admin’ #的密码。
这个也就是上面原理中的:网站程序默认数据库中的数据都是安全的,当网站程序第二次调用刚才存储的脏数据的时候,则不会转义使用而是直接使用,因此就会达到注入的效果。
综上便是我对二阶注入的理解。
在注入查询时有点尴尬,因为我的联合查询语句无法生效

试一试报错注入:

发现还是不行;很尴尬
既然报错注入提示咱们用户名太长那就意味着布尔盲注也行不通吧
接下来分享一位大佬对二阶注入的理解:
1.黑客通过构造数据的形式,在浏览器或者其他软件中提交HTTP数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的SQL语句或者命令。
2.服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。
3.黑客向服务端发送第二个与第一次不相同的请求数据信息。
4.服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的SQL语句或者命令在服务端环境中执行。

服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功。
原文链接:https://blog.csdn.net/weixin_43606134/article/details/106174172