在 Nmap 中执行 SQL 注入实验

Beginner

介绍

SQL 注入(SQL Injection)是一种常见的攻击技术,攻击者通过构造恶意输入,在后端数据库中执行任意 SQL 语句,从而利用 Web 应用程序的漏洞。在本实验中,我们将使用 Docker 搭建一个基于 sqli-labs 的 SQL 注入环境,并通过动手实验来理解 SQL 注入漏洞的原理和利用方法。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 93%。获得了学习者 95% 的好评率。

识别注入点

欢迎来到我们的 Web 安全测试入门课程,本课程将重点介绍如何识别潜在的 SQL 注入漏洞。SQL 注入是 Web 应用程序中常见且可能造成严重后果的安全漏洞,但通过正确的知识,你可以学会如何识别并预防它。

什么是 SQL 注入?

SQL 注入是一种攻击技术,攻击者将恶意的 SQL 代码插入到 Web 应用程序的数据库查询中。如果 Web 应用程序未对用户输入进行适当的清理,这可能导致数据泄露、数据丢失或其他严重问题。

识别潜在的 SQL 注入点

与数据库交互的 Web 应用程序通常会在 URL 中包含参数。如果这些参数未经过适当的清理,它们可能会被利用。例如,你可能会看到如下 URL:

http://some-website.com/page.php?id=XX

在这个 URL 中,id 是一个与数据库交互的参数。任何使用此类参数的网页,如果输入未经过适当的清理,都可能存在 SQL 注入漏洞。

测试 SQL 注入:单引号技术

测试 SQL 注入漏洞的一种简单方法是使用单引号技术。以下是具体步骤:

  1. 在 URL 的参数值后附加一个单引号(')。例如,你可以将 URL 修改为:http://some-website.com/page.php?id=1'
  2. 如果网页在按下回车后返回错误信息,这可能意味着该网站存在 SQL 注入漏洞。

这种方法之所以有效,是因为在 SQL 中,无论是数值还是字符串数据类型,当引入不平衡的单引号时都会生成语法错误。这种错误可以揭示 SQL 注入漏洞的存在。

重要提示

如果你附加单引号后没有显示错误,这并不一定意味着不存在 SQL 注入漏洞。可能是应用程序过滤了单引号,这时你需要使用其他技术来测试漏洞。别担心,我们将在后续课程中介绍这些更高级的技术。

请记住,道德黑客的目的是提高安全性。在你的测试过程中,始终尊重隐私和合法性。祝你学习愉快!

确定 SQL 注入类型

干得漂亮!你已经成功识别了潜在的 SQL 注入点。现在,让我们进入下一步:确定 SQL 注入漏洞的类型。我们将重点关注两种主要类型:数值型 SQL 注入和字符串型 SQL 注入。

数值型 SQL 注入

当输入参数(我们称之为 x)被 Web 应用程序视为整数时,SQL 查询可能如下所示:

select * from <table_name> where id = x

为了识别数值型 SQL 注入,我们使用两个简单的逻辑条件:and 1=1and 1=2。具体步骤如下:

  1. 在浏览器中输入 http://some-website.com/page.php?id=x and 1=1。如果页面正常加载,继续下一步。
  2. 现在,尝试输入 http://some-website.com/page.php?id=x and 1=2。如果页面返回错误或行为异常,这可能表明存在数值型 SQL 注入漏洞。

为什么这种方法有效?

当你输入 and 1=1 时,生成的 SQL 查询如下:

select * from <table_name> where id = x and 1=1

条件 1=1 始终为真,因此如果页面正常加载,这表明输入被直接插入到 SQL 查询中。

当你输入 and 1=2 时,生成的 SQL 查询如下:

select * from <table_name> where id = x and 1=2

条件 1=2 始终为假,因此如果页面行为异常(例如返回错误),这表明我们的输入影响了 SQL 查询,暗示可能存在 SQL 注入漏洞。

字符串型 SQL 注入

在某些情况下,输入参数 x 被 Web 应用程序视为字符串。SQL 查询可能如下所示:

select * from <table_name> where id = 'x'

为了识别字符串型注入,我们使用与数值型注入类似的方法,但使用字符串条件:and '1'='1'and '1'='2'。具体步骤如下:

  1. 在浏览器中输入 http://some-website.com/page.php?id=x' and '1'='1。如果页面正常加载,继续下一步。
  2. 现在,尝试输入 http://some-website.com/page.php?id=x' and '1'='2。如果页面返回错误或行为异常,这可能表明存在字符串型 SQL 注入漏洞。

为什么这种方法有效?

当你输入 and '1'='1' 时,生成的 SQL 查询如下:

select * from <table_name> where id = 'x' and '1'='1'

条件 '1'='1' 始终为真,因此如果页面正常加载,这表明输入被直接插入到 SQL 查询中。

当你输入 and '1'='2' 时,生成的 SQL 查询如下:

select * from <table_name> where id = 'x' and '1'='2'

条件 '1'='2' 始终为假,因此如果页面行为异常(例如返回错误),这表明我们的输入影响了 SQL 查询,暗示可能存在 SQL 注入漏洞。

在这两种情况下,请记住,Web 应用程序的异常响应可能提示你找到了 SQL 注入点。然而,始终确保你有权限执行这些测试,并负责任地使用你的技能。祝你学习愉快!

利用 SQL 注入绕过身份验证

在本实验中,我们将深入探讨 SQL 注入漏洞。我们的重点是如何利用这些漏洞绕过登录身份验证,这种技术通常被称为“万能密码”攻击。

准备实验环境

首先,我们需要准备实验环境。我们将使用 Damn Vulnerable Web Application (DVWA) —— 一个故意设计为不安全的 PHP/MySQL Web 应用程序,是理解 Web 应用程序安全的理想学习工具。

  1. 下载 sqli-labs Docker 镜像: sqli-labs Docker 镜像可在 Docker Hub 上下载。在终端中使用以下命令拉取镜像:

    docker pull acgpiano/sqli-labs
  2. 启动 sqli-labs Docker 容器: 下载镜像后,使用以下命令运行容器:

    docker run -it -d --name sqli-labs -p 80:80 -p 13306:3306 acgpiano/sqli-labs

    该命令启动一个新容器,并将容器中的端口 80 和 3306 分别映射到主机上的端口 80 和 13306。

通过以上步骤,你已经成功设置了必要的实验环境。

设置完成后,打开 Firefox 并在地址栏中输入 http://localhost

如果你是第一次访问 http://localhost,请点击 Setup/reset Database for lab 以准备实验,然后刷新网页。

识别 SQL 注入

点击 Less-11 后,你应该会看到一个简单的登录页面。尝试输入任意用户名 123 和密码 123

错误页面会提示你“无效的用户名或密码”。

解析后端代码

让我们看一下负责身份验证过程的后端代码:

// 获取变量
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
 $uname=$_POST['uname'];
 $passwd=$_POST['passwd'];

 // 将连接参数记录到文件中以便分析
 $fp=fopen('result.txt','a');
 fwrite($fp,'User Name:'.$uname);
 fwrite($fp,'Password:'.$passwd."\n");
 fclose($fp);

 // 连接数据库
 @$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
 $result=mysql_query($sql);
 $row = mysql_fetch_array($result);
....
}

实际执行的 SQL 查询如下:

SELECT * FROM users WHERE username='123' AND password='123' LIMIT 0,1

这个查询很容易理解:如果返回一行,其中 usernamepassword 都匹配,则登录成功。

利用漏洞

基于上一个实验的知识,让我们尝试输入以下 payload:

用户名:123' or 1=1 #
密码:123' or 1=1 #

有趣的是,这让我们成功登录了!原因是实际执行的 SQL 查询如下:

SELECT * FROM users WHERE username='123' or 1=1 #' AND password='123' or 1=1 #'

在 MySQL 中,# 符号用于注释掉行的其余部分,因此查询实际上变为:

SELECT * FROM users WHERE username='123' or 1=1

由于条件 or 1=1 始终为真,查询将始终返回结果,从而导致成功登录。

我们还可以尝试不使用注释符号的变体:

用户名:123' or '1'='1
密码:123' or '1'='1

实际执行的 SQL 查询如下:

SELECT * FROM users WHERE username='123' or '1'='1' AND password='123' or '1'='1'

在这种情况下,两个 or 条件确保它们之间的 and 条件始终为真,从而导致成功登录。

结论

如上所示,有许多技术可用于利用 SQL 注入漏洞并绕过身份验证。你可以自由探索和尝试不同的 payload。我们的目标是理解这些漏洞,以便更好地保护自己的应用程序免受其害。祝你道德黑客学习愉快!

总结

在本实验中,我们学习了如何使用单引号技术识别 SQL 注入漏洞,以及如何通过特定的 payload 确定 SQL 注入的类型(数值型或字符串型)。我们还探讨了如何利用 SQL 注入漏洞绕过登录身份验证,这是一种常见的场景,被称为“万能密码”攻击。通过动手实验,我们获得了理解和利用 SQL 注入漏洞的实践经验,这些漏洞在 Web 应用程序中非常普遍,尤其是在输入清理未正确实施的情况下。