三十八关(GET- Stacked Query Injection - String)
一个单引号,很轻松的就报错了,也明显可以看出闭合
那下面的岂不是就轻轻松松了?是的,确实是轻轻松松了,但这里却要带来一种新的,什么呢,大概叫做sql注入利用方式了,叫做 “堆叠注入”。
我们知道,在SQL中,分号;
是用来表示一条sql语句的结束。试想一下我们在结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。
而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?
区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句(而且只能查询相同的列数,和相同的字段类型),而堆叠注入可以执行的是任意的sql语句。oracle数据库中不能使用堆叠注入。
?id=1';create table test like users--+
这里示范一下,可以看到,成功创建一个表,其他的就自由发挥吧。
但是完成这一关后,我没忍住去尝试了一下第一关,却失败了,看来要想产生堆叠注入,也是有特定的条件的,那就看一下源代码,探究一下吧。这里直接是一个几乎完整的源代码。
if(isset($_GET['id']))
{
$id=$_GET['id'];
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
$con1 = mysqli_connect($host,$dbuser,$dbpass,$dbname);
if (mysqli_connect_errno($con1))
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
else
{
@mysqli_select_db($con1, $dbname) or die ( "Unable to connect to the database: $dbname");
}
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
/* execute multi query */
if (mysqli_multi_query($con1, $sql))
{
/* store first result set */
if ($result = mysqli_store_result($con1))
{
if($row = mysqli_fetch_row($result))
{
echo '<font size = "5" color= "#00FF00">';
printf("Your Username is : %s", $row[1]);
echo "<br>";
printf("Your Password is : %s", $row[2]);
echo "<br>";
echo "</font>";
}
// mysqli_free_result($result);
}
/* print divider */
if (mysqli_more_results($con1))
{
//printf("-----------------\n");
}
//while (mysqli_next_result($con1));
}
else
{
echo '<font size="5" color= "#FFFF00">';
print_r(mysqli_error($con1));
echo "</font>";
}
/* close connection */
mysqli_close($con1);
}
else { echo "Please input the ID as parameter with numeric value";}
其他的,似乎都不怎么重要,让我们看到这个函数mysqli_multi_query()
,这个就是可以堆叠注入的关键原因。
mysqli_multi_query() 函数执行一个或多个针对数据库的查询。多个查询用分号进行分隔。
三十九关(GET - Stacked Query Injection - Intiger based)
这一关稍加判断,判断出是一个数字型,别的都没啥了。
四十关(GET - BLIND based - String - Stacked)
直接来判断注入点吧,输入?id=1'
,页面无返回
输入?id=1"
,页面正常返回,据此,可以判断出单引号参与了闭合,但是还需要确认是否有括号。
我直接用burp跑一下,确认是')
闭合的。
后面的就无须多说了。
四十一关(GET . BLIND based - Intiger . Stacked)
稍加判断,是个数字型。
四十二关(POST - Error based - String - Stacked)
看到这个界面就比较熟悉,和24关二次注入比较像,试了一下发现下方的忘记密码和新用户都没有什么东西,那就只能从登陆和密码修改里面入手了。
那先来试一下登录框吧,先尝试在username中构造,再尝试在password中构造。在password框里面输入单引号时产生报错信息,那就在这里尝试一下堆叠注入吧。
在密码框中输入dumb';create table test1 like users;#
,这时去查看数据库,又多出了一张表
在登录页面找到sql注入漏洞之后,再来看一下密码修改页面有没有机会呢,尝试一番之后,似乎并没有什么机会。查看源代码,原来是进行了转义。
$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']);
四十三关(POST - Error based - String - Stacked with twist)
这一关和上一关一样的,只不过换成了')
闭合。
四十四关(POST - Error based - String - Stacked -Blind)
这关单纯变成了盲注了,但是没有关系我们输入username=dumb
,password=dumb'#
时成功登录,判断出这里是单引号闭合,剩下的就不必再尝试了。
四十五关(POST - Error based - String - Stacked - Blind)
使用password=dumb')#
登录成功,后续就堆叠就完事了。
四十六关(GET - Error based - Numeric - ORDER BY CL AUSE)
来看到这一关,提示我们给出sort
参数
那我们就给一个?sort=1
吧,于是出现了如下结果
再给个其他的数字试一下,给个?sort=2
吧,于是结果变为了
通过这个结果不难猜到后台的语句是这样的
select * from uses order by xxx
但是,一个小小的order By,我们该如何利用呢,刚才学过堆叠注入的话,那就先来测试一下堆叠注入吧,但是很遗憾的,直接就报错了。
那还能咋办呢,我们可以看到,这个表只有三个列,当我们给的参数不为 1,2,3时,就会报错,而其中,0这个特别的数字也是一样。0为什么特别呢,在0可以是一个表达式的布尔返回值。那我们可否利用这一点来进行盲注呢?
但是尝试了一下之后,,,我失败了。给个?sort=1 and 0
,然而还是正常显示出数据。
那还有啥办法?无往不利的报错注入?毕竟这一关输入单双引号的时候也是给出了错误提示的。果然,报错注入还是香啊,有报错信息的话,一定要优先考虑。
除此之外,前面虽然布尔盲注不能用了,但是延时注入还可以用,输入?sort=1 and sleep(5)
,看到网页明显延迟,剩下的就自己发挥吧。
四十七关(GET - Error based - String - ORDER BY CLAUSE)
这一关和前面还是一样的,但是测试一下闭合,输入一个单引号,直接报错,直接看出是单引号闭合。
但是这个单引号强行闭合,我是想不到的,因为使用单引号闭合之后,原本的排序就失去了作用,我给个?sort=2
,却并不能按照第二列的顺序正常排序。
也试了一下输入列名?sort=username
,但是还是没能正常排序。但是既然关卡要这么出,那也没有办法,就闭合一下再用报错注入和延时注入吧。
四十八关(GET - Error based - Blind- Numeric- ORDER BY CLAUSE )
直接使用?sort=2
排序一下,看是否有使用引号包裹。排序成功,看来是没有。
那我们直接就可以开始 注入了?不不不,第四十六关就是这样,这关肯定不同,不看标题都能想到,先来个单引号看下有没有报错信息吧。
果然没有报错信息了,那报错注入自然是不能用了。那就看看延时注入吧,?sort=2 and sleep(5)
,成功延迟,那就使用延时注入就好了。
四十九关(GET - Error based - String- Blind - ORDER BY CLAUSE)
还是直接使用?sort=2
来进行排序,可以看到,并没有排序成功,那必然是又有什么包裹了。
输入?sort=2'
,直接没了回显,但是输入?sort=2"
,却正常显示,那看来就是有单引号参与闭合了,但是还需要确定有没括号。
直接使用sleep函数来判断是否即可。?sort=2' and sleep(2)
,成功产生延迟,接下来延时注入即可。
五十关(GET - Error based - ORDER BY CLAUSE -numeric- Stacked injection)
直接给个?sort=2
,发现排序成功,那这一关难道有什么特别的吗。
直接来一个单引号,有报错信息,再来sleep一下,也成功延迟,那这关有啥特别的地方呢。前面我们布尔盲注的想法出错,因为select之所以能使用布尔盲注,是因为有where
这个条件判断语句,order by 自然是不行的。那堆叠注入是否可用呢,稍加一试,
?sort=2;create table test50 like users
,还真能用。
五十一关(GET - Error based - ORDER BY CLAUSE-String- Stacked Injection)
老规矩,直接拿第二列来排序,然后并没有正常排序,看来又有字符包裹了
输入一个单引号,报错,可使用报错注入,使用sleep(),成功延时。再试一下堆叠注入,也能用。总的来说就是比上一关多了一个单引号,没其他特点。
五十二关(GET - Blind based - ORDER BY CLAUSE -numeric- Stacked injection
)
老规矩,直接拿第二列来排序,排序成功,没有字符包裹。
输入单引号好双引号,都没有报错信息,报错注入不能使用。
使用一下sleep(),成功延迟,可以延时注入。
最后再尝试一下堆叠注入,也成功执行。
五十三关(GET - GET - Blind based - ORDER BY CLAUSE -String- stacked injection)
老规矩,直接拿第二列来排序,然后并没有正常排序,看来又有字符包裹了
输入单引号,没有报错信息,报错注入不能使用。输入双引号,正常返回页面,看来有单引号参与闭合。
使用sleep()判断注入判断注入点,?sort=2' and sleep(2)--+
延时成功。
最后再尝试一下堆叠注入,也成功执行。