这一部分我们要简要介绍以下 Web Hacking 的基本内容,预计分三次博客。
在访问 Web 应用时,浏览器提供了若干个工具来帮助我们发现一些潜在问题和有用的信息。
比如可以查看网站源代码。查看源代码可以 右键 网页,然后选择 查看网站源代码:
或者可以在 URL 前加上 view-source: 也能查看源代码:
除了能查看源代码,浏览器一般都有开发者工具,快捷键是 F12。在开发者工具中,最常用的就是 Inspector、Debugger 和 Network 模块了。
这些是浏览器中比较基本和常见的工具,接下来将从常见的 Web 漏洞上进行讲解。
Content discovery
在 Web 应用中的内容包括文件、视频、备份、网站、图片等等。但是并不是所有的内容都会展示在用户面前,或者说被允许公开访问,比如供内部员工使用的页面、网站配置文件、网站备份文件等。
有三种方式可以实现 内容发现:手动、自动、OSINT (Open-source intelligence,开源情报)。
手动
手动实现 内容发现 有5个方式:
- Robots.txt
- 图标
- Sitemap.xml
- HTTP 头
- 网站框架
Robots.txt
Robots.txt 是一份文档,它告诉搜索引擎哪些网页是否能显示在搜索引擎结果中,或者说禁止特定搜索引擎抓取网站。该文件为渗透测试人员提供了一份很好的清单,因为它列出了网站所有者不希望渗透测试人员发现的网站。
Favicon
Favicon 是浏览器地址栏或标签页中显示的一个小图标,用于打造网站品牌。
有时候开发人员在使用框架搭建网站时,框架的 favicon 会被遗留下来。如果开发人员忘记替换这些图标,则会为渗透测试人员提供网站框架的线索。
OWASP 提供了一个常用框架图标的数据库: OWASP favicon database - OWASP
可以通过如下命令获取图标的 md5 值:curl {图标URL地址} | md5sum
将图标的 md5值 交给 OWASP 数据库中搜索,即可得到结果。
Sitemap.xml
和 robots.txt 文件限制搜索引擎可以查看的内容不同,sitemap.xml 提供了网站所有者希望在搜索引擎上列出的每个文件的列表。这些文件有时会包含网站中比较难浏览到的区域,甚至会列出当前网站不再使用但仍然在幕后工作的一些旧网页。
HTTP 头
当我们向 Web 服务器发出请求时,服务器会返回各种 HTTP 头。HTTP 头有时会包含一些有用的信息,如 Web 服务器软件和可能使用的编程语言。
比如下图就可以看出 Web 服务器软件为 Nginx,使用了 PHP 语言。
user@machine$ curl http://MACHINE_IP -v # curl -v 表示启用了 verbose 模式,它将输出 HTTP 头
* Trying MACHINE_IP:80...
* TCP_NODELAY set
* Connected to MACHINE_IP (MACHINE_IP) port 80
> GET / HTTP/1.1
> Host: MACHINE_IP
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< X-Powered-By: PHP/7.4.3
< Date: Mon, 19 Jul 2021 14:39:09 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
网站框架
一旦获取了网站框架的线索,就可以找到该框架的网站,在这个网站中,我们可以了解到更多关于框架的信息和其他信息,从而可能发现更多内容。
OSINT (开源情报)
开源情报 指一些可以帮助发现目标网站信息的外部资源。常见的 开源情报 有如下几种:
- Google hacking / Dorking
- Wappalyzer
- Wayback machine
- Github
- S3 buckets
Google hacking / Dorking
Google hacking / Dorking 利用了 Google 的高级搜索引擎功能,用户可以借助该功能筛选出特定结果。
Filter | Example | 描述 |
site | site:tryhackme.com | 只返回指定网站地址的结果 |
inrul | inurl:admin | 返回 URL 中包含指定单词的结果 |
filetype | filetype:pdf | 返回特定文件扩展名的结果 |
intitle | intitle:admin | 返回网站标题中包含指定单词的结果 |
Wappalyzer
Wappalyzer 是一款在线工具和浏览器扩展,它可以帮助识别网站使用的技术,比如 框架、CMS、编程语言等。
Wayback machine
Wayback machine (Wayback Machine (archive.org)) 是一个可以追溯到上世纪 90 年代末的网站历史档案。用户可以搜索一个域名,它就会显示这个域名上的历史页面。通过该档案有助于发现当前网站上仍然在运行的旧网页。
Github
Git 是一个版本控制系统,可以跟踪项目中文件的更改,使团队工作更加容易。当团队中成员完成修改之后,成员们会以消息的形式将这些修改提交,推送到一个中心位置(即版本库),其他成员就可以到版本库里把这些修改拉到自己的本地机器上。
Github 是互联网上的托管版 Git,仓库可以设置为公开或私有。我们可以使用 Github 的搜索功能查找公司名称或网站名称,尝试找到属于目标的资源库,比如源代码、密码或其他尚未发现的内容。
S3 Buckets
S3 Buckets 是亚马逊 AWS 提供的一种存储服务,允许人们将文件甚至静态网站内容存在云中,国内的 阿里云、腾讯云也提供了类似服务,它可以提供 HTTP/HTTPS 访问。文件所有者可以设置访问权限,使文件公开、私有甚至可写。假如访问权限设置不正确,可能会使本不应向公众开放的文件被允许访问。
S3 Buckets 的格式是 http(s)://{name}.s3.amazonaws.com ,其中 name 由所有者决定,比如 http(s)://tryhackme-assets.s3.amazonaws.com。
发现 S3 Buckets 的方法有很多,比如通过网站源代码,通过Github存储库中查找 URL,甚至通过自动化工具来查找。S3 Buckets 往往有常见命名,比如 {name}-assets、 {name}-www、 {name}-public、 {name}-private 等,我们可以从这些常见命名入手,进行自动化查找。
自动
这就需要借助工具来实现自动发掘,这种工具通过对网站发送成百上千甚至上百万的请求来检查网站上是否存在某些文件或目录,使我们可以访问到以前不知道的资源。在这个过程中,我们需要用到一个叫 词表 (wordlist) 的东西。
词表 如同字典,它是包含了一长串常用单词的文本文件。工具使用词表中的单词来逐个检索,进而找到资源。所以,自动化工具的效率取决于词表的质量。
自动化工具有很多,用于 信息收集 的自动化工具一般为 ffuf、dirb 和 gobuster。
Subdomain enumeration
子域名枚举可以帮助扩大攻击面,尝试发现到更多的潜在攻击点。子域名枚举可以通过:暴力、OSINT 和 虚拟主机 来获得。
OSINT
SSL/TLS 证书
当 CA 为域名颁发 SSL/TLS 证书时,CA 会将其写入 Certificate Transparency (CT,证书透明度) 日志,这些日志可公开访问为域名创建的每个 SSL/TLS 证书。CT 日志的目的是防止恶意和意外制作的证书被使用,我们也可以借助该日志发现属于某个域名的子域名。
crt.sh | Certificate Search 和 Entrust Certificate Search - Entrust, Inc. 提供了可搜索的证书数据库。
搜索引擎
前面提到过 Google hacking 语法,该语法不仅可以进行 内容发现,还能进行子域名枚举。
在 hacking 语法中,site: 过滤词用于过滤出指定域名的网站,我们可以使用该过滤词构造出如下搜索请求:site:*.tryhackme.com -site:www.tryhackme.com 。这个请求表示,过滤出域名为 tryhackme.com 的网站,但排除 www.tryhackme.com 这个首页网站。经过这番查询,返回的就是可搜索到的子域名网站了。
Sublist3r
这个严格意义上不能算是 OSINT,更像是自动化工具。Sublist3r 这一工具可以用于加快 OSINT 的利用流程,自动执行使用 OSINT 探索子域名的过程。
暴力
暴力搜索 子域名 除了使用自动化工具遍历 URL,还可以遍历 DNS。因为大部分企业不会监控 DNS 服务器,所以我们可以从 DNS 服务器返回的记录中获取更多信息。
比如 dnsrecon 工具就可以通过爆破 DNS 服务器获取到网站子域名:
虚拟主机
由于 Web 服务器可以在一台服务器上托管多个网站,因此当客户端请求访问一个网站时,服务器会通过 HTTP 头中的 Host 字段知晓客户端想要访问哪个网站。基于此,我们可以通过更改 Host 字段并监控响应来确认是否发现了新的子域名。
一个个手动尝试肯定很耗时,因此我们也需要借助自动化工具来完成这一过程。
在 ffuf 工具中,我们就可以实现这样的遍历:
其中,-w 指定了要使用的词表,-H 表示添加/编辑了 Host 字段,-u 指定了目标URL。开始后,会将词表中遍历的内容放到 FUZZ 中进行处理。
使用上述命令会输出大量结果,有些结果可能不是我们想要的,因此需要做一点过滤。
我们可以通过 -fs 来过滤指定页面大小值的页面,这样结果就少了很多。
Authentication bypass
Authentication bypass 是比较严重的漏洞了,它往往会导致用户个人数据泄露。这里的 bypass 包括但不限于 绕过、破坏或混淆网站身份验证。
暴力
当我们碰到一个身份验证界面,比如登录时,我们需要先知道用户名,再去使用密码登录。因此首先获取一个有效的用户名列表是十分有用的。
有一些网站在注册用户时,面对重复的用户名会进行提示,可以根据这个提示来获取当前已有用户名。
我们可以使用自动化工具来完成这一任务,此处我们继续使用 ffuf:
其中除了之前讲到的参数,-X 表示请求方法,像登录注册这种表单提交一般都是用 POST 方法的;-d 指定了我们要发送的数据;-mr 用于过滤,其保留了出现要查找的文本的页面。
通过上面的命令,可以得到一个用户名列表,假设我们将其保存为 valid_username.txt。那么接下来就是对这些用户名进行密码爆破。
注意到 -d 中要传输的数据,因为之前我们只有一个爆破点,因此用一个 FUZZ 即可指明爆破位置。而现在我们不仅要使用 用户名,还要爆破 密码,所以给它们各自一个代号,此处分别为 w1 和 w2。同样的,在 -w 指示使用的词表时,已经为词表对应了代号。-fc 用于过滤 HTTP 状态码不是 200 的页面。
最终得到用户名和其对应密码,这样就是一次身份验证的绕过。
逻辑缺陷
有些身份验证可能会包含逻辑缺陷。逻辑缺陷是指应用程序的逻辑路径被绕过、规避或操纵。
下面是一个逻辑缺陷的示例。
现在有一个页面用于重置密码,要想成功重置密码,首先需要知道要被重置密码的账户对应的邮箱地址。如果输入的电子邮件地址无效,则会收到一个错误信息。
假如我们只有用户名,无法成功爆破密码,就可以从重置密码入手。但是这看起来似乎无从下手,因为就算知道了邮箱地址,我们也不知道邮箱密码。
如上图所示,尽管我们知道有一个用户名为 robert,也知道重置密码的邮件已经发出,但无法知道邮箱密码的话也无法重置成功。
但此时我们注意到 URL,邮箱地址是跟随 URL 发送过去的,也就是说它使用 GET 请求方法发送,而用户名是通过 POST 方式传输过去的。
用 curl 命令复现前面的步骤,则获得下述命令:
其中,-H 表示指定 HTTP 头中的 Content-Type 字段,此处设置成 application/x-www-form-urlencoded 以使 Web 服务器正确理解我们发起的请求;-d 指定了要发送的数据,该数据会以 POST 的请求方式发送过去。
在后端收到请求时,会读取请求中的参数。在这个页面中,其使用了 PHP 的 $_REQUEST 函数来接收参数。 $_REQUEST 函数可以接收请求中的 GET 和 POST 参数,但如果 GET 和 POST 参数的名字一样,则优先选择 POST 参数。基于这个特性,我们修改 curl 命令:
不同之处在于,我们在 -d 传输的数据中添加了一个 email 参数,将该参数的地址设置为攻击者的邮箱地址。这样,当后端接收到请求后,发现 email 参数在 GET 和 POST 请求中都存在,那么就会选取 POST 参数,即攻击者的邮箱地址,那么重置密码的邮件也就发送给了攻击者。
可以看到响应中返回了这一串字,说明邮件已经发送到攻击者邮箱中。
Cookie tampering
之前提到过,HTTP 是无状态的,需要 Cookie 来使 Web 服务器识别用户身份和状态。
但是 Cookie 可以通过 HTTP 头篡改,因此假如我们窃取到某个用户 A 的 Cookie,就可以直接使用该 Cookie 登录上页面,欺骗 Web 服务器自己是用户 A。
或者,有些 Cookie 表示的是一种状态,假设有个页面有这样一个 Cookie:
Cookie: logged_in = false; admin = false
那么我们就可以将其中的 logged_in 和 admin 全部设置为 true,这样我们就能欺骗 Web 服务器我们已经以 admin 身份登录到当前页面上了。
大部分时候,Cookie 可能会被编码,常见的编码有 MD5、SHA-256、SHA-512、SHA1 等。此时要篡改的话,需要将篡改内容经过一次编码后再传给 Web 服务器。
还是上面的 Cookie,假如它经过了 Base64 编码,那我们需要传递给 Web 服务器下述字符串:bG9nZ2VkX2luPXRydWU7YWRtaW49dHJ1ZQ==。这一串字符串经过 Base64 解码后,就是 logged_in=true;admin=true。