Intro to HTTP Verb Tampering
HTTP协议的工作原理是在HTTP请求开始时接受各种HTTP方法作为谓词。根据web服务器配置,可以编写web应用程序的脚本以接受用于其各种功能的特定HTTP方法,并基于请求的类型执行特定操作。 虽然程序员主要考虑两种最常用的HTTP方法,GET和POST,但任何客户端都可以在其HTTP请求中发送任何其他方法,然后查看web服务器如何处理这些方法。假设web应用程序和后端web服务器都被配置为只接受GET和POST请求。在这种情况下,发送不同的请求将导致显示web服务器错误页面,这本身并不是一个严重的漏洞(除了提供糟糕的用户体验并可能导致信息泄露之外)。另一方面,如果web服务器配置不限于仅接受web服务器所需的HTTP方法(例如GET/POST),并且web应用程序没有被开发为处理其他类型的HTTP请求(例如HEAD、PUT),那么我们可能能够利用这种不安全的配置来访问我们无法访问的功能,或者甚至绕过某些安全控制。
HTTP Verb Tampering
可以想象,上面的一些方法可以执行非常敏感的功能,比如将(PUT)或删除(DELETE)文件写入后端服务器上的webroot目录。正如Web请求模块中所讨论的,如果Web服务器没有安全地配置为管理这些方法,我们可以使用它们来控制后端服务器。然而,HTTP谓词篡改攻击更常见(因此更为关键)的原因是,它们是由后端web服务器或web应用程序中的错误配置引起的,这两者都可能导致漏洞。
Insecure Configurations
不安全的web服务器配置导致第一类HTTP谓词篡改漏洞。web服务器的身份验证配置可能仅限于特定的HTTP方法,这将使一些HTTP方法在没有身份验证的情况下可以访问。例如,系统管理员可以使用以下配置要求对特定网页进行身份验证:
<Limit GET POST>
Require valid-user
</Limit>
正如我们所看到的,即使配置为身份验证方法指定了GET和POST请求,攻击者仍然可能使用不同的HTTP方法(如HEAD)来完全绕过此身份验证机制,这将在下一节中看到。这最终导致身份验证绕过,并允许攻击者访问他们不应该访问的网页和域。
Insecure Coding
不安全的编码实践会导致其他类型的HTTP谓词篡改漏洞(尽管有些人可能不考虑这种谓词篡改)。当web开发人员应用特定的过滤器来减轻特定的漏洞,而不使用该过滤器覆盖所有HTTP方法时,就会发生这种情况。例如,如果发现某个网页易受SQL注入漏洞的攻击,并且后端开发人员通过以下应用输入净化筛选器来减轻SQL注入漏洞:
$pattern = "/^[A-Za-z\s]+$/";
if(preg_match($pattern, $_GET["code"])) {
$query = "Select * from ports where port_code like '%" . $_REQUEST["code"] . "%'";
...SNIP...
}
我们可以看到,过滤器==只在GET参数==上进行测试。如果GET请求不包含任何坏字符,那么将执行查询。但是,在执行查询时,会使用$_REQUEST[“code”]参数,这些参数也可能包含POST参数,从而导致HTTP谓词的使用不一致。在这种情况下,攻击者可能会使用POST请求来执行SQL注入,在这种情况中,GET参数将为空(不包括任何坏字符)。该请求将通过安全过滤器,这将使函数仍然容易受到SQL注入的攻击。 虽然上述两个漏洞都是在公共场合发现的,但第二个漏洞要常见得多,因为它是由于编码错误造成的,而第一个漏洞通常可以通过安全的web服务器配置来避免,因为文档经常警告不要这样做。在接下来的部分中,我们将看到这两种类型的示例以及如何利用它们。
Bypassing Basic Authentication
利用HTTP谓词篡改漏洞通常是一个相对简单的过程。我们只需要尝试其他HTTP方法,看看web服务器和web应用程序是如何处理它们的。虽然许多自动漏洞扫描工具可以一致地识别由不安全的服务器配置引起的HTTP Verb篡改漏洞,但它们通常无法识别由不可靠的编码引起的HTTP篡改漏洞。这是因为一旦我们绕过身份验证页面,第一种类型就可以很容易地识别出来,而另一种类型则需要主动测试,看看我们是否可以绕过现有的安全过滤器。 第一种类型的HTTP谓词篡改漏洞主要由不安全的Web服务器配置引起,利用该漏洞可以绕过某些页面上的HTTP基本身份验证提示。
Identify
当我们在本节结束时开始练习时,我们看到我们有一个基本的File Manager web应用程序,在其中我们可以通过键入新文件的名称并点击enter来添加新文件:
但是,假设我们试图通过单击红色的“重置”按钮来删除所有文件。在这种情况下,我们看到该功能似乎仅限于经过身份验证的用户,因为我们得到了以下HTTP基本身份验证提示:
由于我们没有任何凭据,我们将获得一个401未经授权的页面:由于我们没有任何凭据,我们将获得一个401未经授权的页面
所以,让我们看看我们是否可以通过HTTP动词篡改攻击绕过这一点。为此,我们需要确定哪些页面受到此身份验证的限制。如果我们在点击Reset按钮后检查HTTP请求,或者在点击该按钮后查看该按钮导航到的URL,我们会发现它位于/admin/Reset.php。因此,/admin目录仅限于经过身份验证的用户,或者只有/admin/recet.php页面。我们可以通过访问/admin目录来确认这一点,并且确实会提示我们再次登录。这意味着完整的/admin目录受到限制。
Exploit
为了尝试利用该页面,我们需要确定web应用程序使用的HTTP请求方法。我们可以在Burp Suite中拦截请求并进行检查:
由于页面使用GET请求,我们可以发送POST请求,并查看网页是否允许POST请求(即验证是否涵盖POST请求)。要做到这一点,我们可以右键点击Burp中拦截的请求,然后选择Change request Method,它会自动将请求更改为POST请求:
完成后,我们可以单击“前进”并在浏览器中查看页面。不幸的是,如果我们不提供凭据,我们仍然会被提示登录,并将获得401未经授权的页面:
因此,web服务器配置似乎同时涵盖了GET和POST请求。然而,正如我们之前所了解到的,我们可以使用许多其他HTTP方法,最显著的是HEAD方法,它与GET请求相同,但不会在HTTP响应中返回正文。如果成功,我们可能不会收到任何输出,但重置功能仍应执行,这是我们的主要目标。 要查看服务器是否接受HEAD请求,我们可以向其发送OPTIONS请求,并查看接受了哪些HTTP方法,如下所示:
Tanin@htb[/htb]$ curl -i -X OPTIONS http://SERVER_IP:PORT/
HTTP/1.1 200 OK
Date:
Server: Apache/2.4.41 (Ubuntu)
Allow: POST,OPTIONS,HEAD,GET
Content-Length: 0
Content-Type: httpd/unix-directory
正如我们所看到的,响应显示Allow:POST、OPTIONS、HEAD、GET,这意味着web服务器确实接受HEAD请求,这是许多web服务器的默认配置。因此,让我们再次尝试拦截重置请求,这次使用HEAD请求来查看web服务器如何处理它:
一旦我们将POST更改为HEAD并转发请求,我们将看到我们不再得到登录提示或401未授权页面,而是得到一个空输出,正如HEAD请求所预期的那样。如果我们返回到File Manager web应用程序,我们将看到所有文件确实已被删除,这意味着我们在没有管理员访问权限或任何凭据的情况下成功触发了重置功能:
Bypassing Security Filters
另一种更常见的HTTP谓词篡改漏洞是由web应用程序开发过程中出现的不安全编码错误引起的,这导致web应用程序无法覆盖某些功能中的所有HTTP方法。这通常出现在检测恶意请求的安全筛选器中。例如,如果安全过滤器用于检测注入漏洞,并且只检查POST参数(例如$_POST[参数])中的注入,则可以通过将请求方法更改为GET来绕过它。
为了避免我们的代码中存在HTTP Verb篡改漏洞,我们必须与HTTP方法的使用保持一致,并确保相同的方法始终用于整个web应用程序的任何特定功能。始终建议通过测试所有请求参数来扩大安全筛选器中的测试范围。这可以通过以下函数和变量来实现:
Language | Function |
---|---|
PHP | $_REQUEST['param'] |
Java | request.getParameter('param') |
C# | Request['param'] |