有许多工具和方法可用于目录和参数模糊测试/暴力破解。在本模块中,我们将主要关注用于 Web 模糊测试的 ffuf 工具,因为它是可用于 Web 模糊测试的最常见和最可靠的工具之一。
将讨论以下主题:
ffuf
等工具为我们提供了一种方便的自动化方法来对 Web 应用程序的各个组件或网页进行模糊测试。这意味着,例如,如果 Web 服务器上存在具有我们列表中名称的页面,则我们使用一个列表,该列表用于向 Web 服务器发送请求。如果我们得到响应代码 200,那么我们知道这个页面存在于 Web 服务器上,我们可以手动查看它。
术语模糊测试
是指一种测试技术,该技术将各种类型的用户输入发送到某个接口以研究它会如何反应。如果我们对 SQL 注入漏洞进行模糊测试,我们将发送随机特殊字符并查看服务器会如何反应。如果我们对缓冲区溢出进行模糊测试,我们将发送长字符串并增加它们的长度,以查看二进制文件是否以及何时会中断。
我们通常为每种类型的 Web 模糊测试使用常用术语的预定义单词列表,以查看 Web 服务器是否接受它们。这样做是因为 Web 服务器通常不会提供所有可用链接和域的目录(除非配置得非常糟糕),因此我们必须检查各种链接并查看哪些链接返回页面。例如,如果我们访问 https://www.hackthebox.eu/doesnotexist,我们将得到一个 HTTP 代码 404 Page Not Found
,并看到下面的页面:
但是,如果我们访问一个存在的页面,例如 /login
,我们将获得登录页面并获得 HTTP 代码 200 OK,
并看到下面的页面:
这是页面和目录的 Web 模糊测试背后的基本思想。不过,我们不能手动执行此操作,因为这将花费很长时间。这就是为什么我们有可以自动、高效且非常快速地执行此操作的工具。此类工具每秒发送数百个请求,研究响应 HTTP 代码,并确定页面是否存在。因此,我们可以快速确定存在哪些页面,然后手动检查它们以查看其内容
为了确定存在哪些页面,我们应该有一个包含 Web 目录和页面常用单词的单词列表,这与密码字典攻击
非常相似,我们将在本模块后面讨论。虽然这不会显示特定网站下的所有页面,因为有些页面是随机命名或使用唯一名称的,但一般来说,这会返回大部分页面,在某些网站上达到高达 90% 的成功率。
我们不必通过手动创建这些单词列表来重新发明轮子,因为已经付出了巨大的努力来搜索 Web 并确定每种类型的模糊测试最常用的单词。一些最常用的单词列表可以在 GitHub SecLists 存储库下找到,该存储库将单词列表分类为各种类型的模糊测试,甚至包括常用密码,我们稍后将用于密码暴力破解。
shellHTTP 选项: -H:设置 HTTP 请求头,格式为 "Name: Value",可以使用多个 -H 参数。 -X:设置 HTTP 请求方法,默认为 GET。 -b:设置 Cookie 数据,格式为 "NAME1=VALUE1; NAME2=VALUE2",支持 curl 功能。 -d:设置 POST 请求的 body 数据。 -ignore-body:不获取响应内容,默认获取。 -r:跟踪重定向,默认为 false。 -recursion:递归扫描,只支持 FUZZ 关键字,且 URL 必须以 FUZZ 结尾,默认为 false。 -recursion-depth:设置递归深度,默认为 0(不递归)。 -replay-proxy:通过指定的代理回放匹配的请求。 -timeout:设置 HTTP 请求的超时时间(秒),默认为 10 秒。 -u:设置目标 URL。 -x:设置 HTTP 代理 URL。 常规选项: -V:显示版本信息,默认为 false。 -ac:自动校准过滤选项,默认为 false。 -acc:自定义自动校准字符串,可以使用多次,隐式启用 -ac。 -c:启用输出彩色显示,默认为 false。 -maxtime:设置整个过程的最大运行时间(秒),默认为 0(不限制)。 -maxtime-job:设置每个作业的最大运行时间(秒),默认为 0(不限制)。 -p:设置请求之间的延迟时间,或者延迟范围。例如 "0.1" 或 "0.1-2.0"。 -s:静默模式,不打印额外信息,默认为 false。 -sa:遇到所有错误时停止,隐式启用 -sf 和 -se。 -se:遇到不正常的错误时停止,默认为 false。 -sf:当超过 95% 的响应返回 403 Forbidden 时停止,默认为 false。 -t:设置并发线程数,默认为 40。 -v:详细输出,打印完整 URL 和重定向位置(如果有)。 匹配选项: -mc:匹配 HTTP 状态码,或者使用 "all" 匹配所有状态码,默认为 200,204,301,302,307,401,403。 -ml:匹配响应中的行数。 -mr:使用正则表达式匹配响应。 -ms:匹配 HTTP 响应的大小。 -mw:匹配响应中的单词数。 过滤选项: -fc:根据 HTTP 状态码过滤响应,可以提供逗号分隔的代码或范围。 -fl:根据响应中的行数过滤,可以提供逗号分隔的行数或范围。 -fr:根据正则表达式过滤响应。 -fs:根据响应大小过滤,可以提供逗号分隔的大小或范围。 -fw:根据响应中的单词数过滤,可以提供逗号分隔的单词数或范围。 输入选项: -D:DirSearch 单词列表兼容模式。与 -e 参数一起使用,默认为 false。 -e:设置扩展名列表,用于扩展 FUZZ 关键字。 -ic:忽略单词列表中的注释,默认为 false。 -input-cmd:使用命令生成输入。使用 --input-num 指定输入的数量,覆盖 -w。 -input-num:设置要测试的输入数量,默认为 100。 -mode:多词典操作模式。可用模式:clusterbomb, pitchfork,默认为 clusterbomb。 -request:指定包含原始 HTTP 请求的文件。 -request-proto:指定与原始请求一起使用的协议,默认为 https。 -w:设置单词列表文件路径,并可以指定关键字(通过冒号分隔),例如 /path/to/wordlist:KEYWORD。 输出选项: -debug-log:将所有内部日志写入指定的文件。 -o:将输出写入文件。 -od:设置存储匹配结果的目录路径。 -of:设置输出文件格式。可选格式:json, ejson, html, md, csv, ecsv,或者 'all' 表示所有格式,默认为 json。
从上面的例子中我们可以看出,主要的两个选项是 -w
用于单词列表和 -u
用于 URL。我们可以为关键字分配一个单词列表,以便在我们想要模糊搜索的地方引用它。例如,我们可以选择我们的单词列表,并通过在它后面添加 :FUZZ
来为其分配关键字 FUZZ
:
example:
bashKriem@htb[/htb]$ ffuf -w /opt/useful/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://SERVER_IP:PORT/FUZZ
上一节中我们发现我们可以访问blog,但是这个目录返回了一个空页面,我们无法定位其中的链接或者页面。所以我们还要再次使用模糊测试。但是,在我们开始之前,我们必须找出网站使用的页面类型,例如 .html
、.aspx
、.php
或其他。
识别该漏洞的一种常见方法是通过 HTTP 响应标头查找服务器类型并猜测扩展名。例如,如果服务器是 apache
,则可能是 .php
,或者如果服务器是 IIS
,则可能是 .asp
或 .aspx
,依此类推。不过,这种方法不是很实用。因此,我们将再次使用 ffuf
对扩展进行模糊测试,类似于我们对目录进行模糊测试的方式。我们不是将 FUZZ
关键字放在目录名称所在的位置,而是将其放置在扩展名所在的位置。FUZZ
的 AND WORD 列表来表示常见的扩展。我们可以在 SecLists
中使用以下 wordlist 进行扩展
在我们开始模糊测试之前,我们必须指定该扩展名将位于哪个文件的末尾!我们总是可以使用两个单词列表,每个单词都有一个唯一的关键字,然后对两个单词列表执行 FUZZ_1.FUZZ_2
进行模糊测试。但是,我们总是可以在大多数网站中找到一个文件,即 index.*
,因此我们将它用作我们的文件和模糊扩展名
我们确实得到了几次命中,但只有 .php
给出了代码为 200
的响应。伟大!我们现在知道这个网站在 PHP
上运行,以开始对 PHP
文件进行模糊测试。
现在,我们将使用与 ffuf
相同的关键字概念,使用 .php
作为扩展名,将 FUZZ
关键字放在文件名应该在的位置,并使用我们用于模糊目录的相同单词列表:
shell-sessionffuf -w /opt/useful/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://SERVER_IP:PORT/blog/FUZZ.php
到目前为止,我们一直在对目录进行模糊测试,然后在这些目录下进行模糊测试,然后对文件进行模糊测试。但是,如果我们有几十个目录,每个目录都有自己的子目录和文件,这将需要很长时间才能完成。为了能够自动化这一点,我们将使用所谓的递归模糊测试
当我们递归扫描时,它会自动在其页面上可能包含的任何新识别的目录下开始另一次扫描,直到它对主网站及其所有子目录进行模糊测试。
某些网站可能有一个很大的子目录树,例如 /login/user/content/uploads/...etc
,这将扩展扫描树,并且可能需要很长时间才能扫描所有子目录。这就是为什么始终建议为递归扫描指定深度
的原因,这样它就不会扫描比该深度更深的目录。一旦我们对第一个目录进行模糊测试,我们就可以选择最有趣的目录并运行另一次扫描以更好地指导我们的扫描。
在 ffuf
中,我们可以使用 -recursion
标志启用递归扫描,也可以使用 -recursion-depth
标志指定深度。如果我们指定 -recursion-depth 1
,它只会模糊测试主目录及其直接子目录。如果标识了任何子子目录(如 /login/user
,它不会对页面进行模糊测试)。在 ffuf
中使用递归时,我们可以使用 -e .php
指定我们的扩展
最后,我们还将添加标志 -v
来输出完整的 URL。否则,可能很难分辨哪个 .php
文件位于哪个目录下。
让我们重复我们使用的第一个命令,在指定 .php
作为我们的扩展时向其添加递归标志,看看我们得到什么结果:
shell-sessionffuf -w /opt/useful/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://SERVER_IP:PORT/FUZZ -recursion -recursion-depth 1 -e .php -v
正如我们所看到的,这次扫描花费的时间要长得多,发送的请求数量几乎是 6 倍,并且 wordlist 的大小增加了一倍(一次有 .php
次,一次没有)。尽管如此,我们还是获得了大量结果,包括我们之前确定的所有结果,所有这些都是通过一行命令完成的。
当我们访问 /blog
下的页面后,我们收到一条消息,指出 Admin panel moved to academy.htb
.如果我们在浏览器中访问网站,我们会得到 can’t connect to the server at www.academy.htb
:
这是因为我们所做的练习不是任何人都可以访问的公共网站,而是 HTB 内部的本地网站。浏览器只知道如何访问 IP,如果我们为他们提供 URL,它们会尝试通过查看本地 /etc/hosts
文件和公共 DNS 域名系统
来将 URL 映射到 IP。如果 URL 也不在 URL 中,它将不知道如何连接到它。
如果我们直接访问该 IP,浏览器会直接访问该 IP 并知道如何连接到它。但在这个例子中,我们告诉它去 academy.htb
,所以它查看本地的 /etc/hosts
文件,却没有找到任何提及它的内容。它向公共 DNS 询问它(例如 Google 的 DNS 8.8.8.8
),但没有找到任何提及它的内容,因为它不是公共网站,最终无法连接。因此,要连接到 academy.htb
,我们必须将其添加到我们的 /etc/hosts
文件中。我们可以通过以下命令来实现这一点:
shellKriem@htb[/htb]$ sudo sh -c 'echo "SERVER_IP academy.htb" >> /etc/hosts'
但是,我们得到的网站与直接访问 IP 时得到的网站相同,因此 academy.htb
是我们目前一直在测试的同一域名。我们可以通过访问 /blog/index.php
来验证这一点,并查看我们可以访问该页面。
当我们在这个 IP 上运行测试时,即使我们对目标进行了完全递归
扫描,也没有发现任何关于 admin
或 panels 的信息。 So, in this case, we start looking for sub-domains under '*.academy.htb' and see if we find anything, which is what we will attempt in the next section.
在本节中,我们将学习如何使用 ffuf
来识别任何网站的子域(即 *.website.com
)
子域是另一个域的基础的任何网站。例如,https://photos.google.com
是 google.com
的 photos
子域。
在这种情况下,我们只是通过检查不同的网站是否具有将我们重定向到正常工作的服务器 IP 的公共 DNS 记录来检查它们是否存在。那么,让我们运行一次扫描,看看我们是否得到任何命中。在开始扫描之前,我们需要两样东西:
wordlist
单词表
target
目标
幸运的是,在 SecLists
存储库中,有一个针对子域词表的特定部分,由通常用于子域的常用词组成。我们可以在 /opt/useful/seclists/Discovery/DNS/
中找到它。在我们的例子中,我们将使用一个较短的单词列表,即 subdomains-top1million-5000.txt
。如果我们想扩展扫描,我们可以选择一个更大的列表。
对于我们的目标,我们将 inlanefreight.com
作为我们的目标,并在其上运行扫描。让我们使用 ffuf
并将 FUZZ
关键字放在子域的位置,看看我们是否得到任何结果:
我们看到我们确实得到了一些回报。现在,我们可以尝试在 academy.htb
上运行同样的事情,看看我们是否得到任何返回:
我们看到我们没有得到任何回复。这是否意味着 academy.htb
下没有子域?-不。
这意味着 academy.htb
下没有公共
子域,因为它没有公共 DNS 记录,如前所述。即使我们确实将 academy.htb
添加到我们的 /etc/hosts
文件中,我们只添加了主域,所以当 ffuf
寻找其他子域时,它不会在 /etc/hosts
中找到它们,而是会询问公共 DNS,这显然不会有它们。
正如我们在上一节中看到的,我们能够使用公有 DNS 记录对公有子域进行模糊测试。但是,当涉及到模糊测试没有公共 DNS 记录的子域或不公开的网站下的子域时,我们不能使用相同的方法。在本节中,我们将学习如何使用 Vhost Fuzzing
执行此操作。
VHost 和子域之间的主要区别在于,VHost 基本上是在同一服务器上提供服务的“子域”,并且具有相同的 IP,因此单个 IP 可以为两个或多个不同的网站提供服务。
在许多情况下,许多网站实际上会拥有非公开的子域,并且不会在公共 DNS 记录中发布它们,因此如果我们在浏览器中访问它们,我们将无法连接,因为公共 DNS 不知道他们的 IP。同样,如果我们使用子域模糊测试
,我们将只能识别公有子域,而无法识别任何非公有子域。
这就是我们在已有的 IP 上使用 VHosts Fuzzing
的地方。我们将在同一 IP 上运行扫描并测试扫描,然后我们将能够识别公有和非公有子域以及 VHost。
要扫描 VHosts,而无需手动将整个单词列表添加到我们的 /etc/hosts
,我们将模糊测试 HTTP 标头,特别是 Host:
标头。为此,我们可以使用 -H
标志来指定标头,并在其中使用 FUZZ
关键字,如下所示:
shell-sessionffuf -w /opt/useful/seclists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://academy.htb:PORT/ -H 'Host: FUZZ.academy.htb'
我们看到单词列表中的所有单词都返回了 200 OK!
这是意料之中的,因为我们只是在访问 http://academy.htb:PORT/
时更改标题。所以,我们知道我们总是会得到 200 个 OK。
但是,如果 VHost 确实存在,并且我们在标头中发送了正确的 VHost,我们应该获得不同的响应大小,因为在这种情况下,我们将从该 VHost 获取页面,这可能会显示不同的页面
到目前为止,我们还没有对 ffuf
进行任何过滤,默认情况下,结果会通过其 HTTP 代码自动过滤,该代码会过滤掉代码 404 NOT FOUND
,并保留其余部分。但是,正如我们在上一次运行 ffuf
时所看到的,我们可以得到许多代码为 200
的响应。因此,在这种情况下,我们将不得不根据另一个因素过滤结果,我们将在本节中学习。
Ffuf
提供了匹配或筛选出特定 HTTP 代码、响应大小或字数的选项。我们可以通过 ffuf -h
看到:
在这种情况下,我们不能使用匹配,因为我们不知道来自其他 VHost 的响应大小是多少。我们知道错误结果的响应大小,从上面的测试中可以看出,它是 900
,我们可以使用 -fs 900
将其过滤掉。现在,让我们重复相同的上一个命令,添加上面的标志,看看我们得到什么:
通过fuff模糊测试出当前网站的网页,并尝试get或post方法传参,模糊测试出参数名(通过返回size的不同判断是否有该参数)
样例:
shellffuf -w /opt/useful/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u http://admin.academy.htb:PORT/admin/admin.php?FUZZ=key
首先,先模糊测试出我们正常网页传回size大小为多少,然后将这些冗余size过滤掉,
bash-fs xxx
传回数据只有我们需要的。
post请求与get请求不同,get请求是将请求参数放置在url里进行传参,而post则是将其打包在报文中的data字段内传参。
这也导致我们并不能有效地、直接的模糊测试。
当然,对于post测试,fuff也是有办法的
要使用ffuf模糊测试data字段,我们需要使用-d标志,同时我们还需要使用-X标志表示我们使用post传参。
[!NOTE]
提示:在PHP中,“POST”数据“content-type”只能接受“application/x-www-form-urlencoded”。因此,我们可以使用“-H 'Content-Type: application/x-www-form-urlencoded'”在“ffuf”中设置它。
以id为例:
通过shell创建字典并写入文件:
shellfor i in $(seq 1 1000); do echo $i >> ids.txt; done
shellffuf -w ids.txt:FFUF -u http://admin.academy.htb/admin/admin.php -X POST -d 'id=FFUF' -H 'Content-Type: application/x-www-form-urlencoded' -fs 786
这样我们就通过自己构建的字典完成参数值的post方法的模糊测试。
测出来是73.
然后我们将73带入,用curl回显:
shellcurl http://admin.academy.htb/admin/admin.php -X POST -d 'id=73' -H 'Content-Type: application/x-www-form-urlencoded'
即可。
[!CAUTION]
如果发现ping的通,curl不行,试一试
unset http(s)_proxy
1.对上面显示的 IP 的“*.academy.htb”运行子域/虚拟主机模糊扫描。您可以识别哪些子域? (只写子域名)
使用ffuf子域模糊测试
shellffuf -w /pathtowordlist -u http://xxxx.xx:port -H 'Host: FUZZ.xxxx.xx'
2.在运行页面模糊扫描之前,您应该首先运行扩展模糊扫描。域接受哪些不同的扩展名?
使用拓展模糊测试:
3.您将识别的页面之一应显示“您无权访问!”。完整页面的 URL 是什么?
4.在上一个问题的页面中,您应该能够找到该页面接受的多个参数。这些是什么?
使用post方法传参
5.尝试对您确定的工作值参数进行模糊测试。其中一个应该返回一面旗帜。旗帜的内容是什么?
本文作者:Hyrink
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!