.Net代码审计

0x01目录架构

Global.asax用于处理应用程序级别的事件,例如应用程序启动(Application_Start)、会话启动(Session_Start)、应用程序错误(Application_Error)等。

Web.config这是 ASP.NET 应用程序的主要配置文件,用于定义应用程序的配置设置,例如数据库连接字符串、身份验证方式、自定义错误页面等。

bin文件夹放置了编译好的Dll文件,是后端服务接口代码的存放位置

0x02审计

SQL盲注——GetByName方法

Login.aspx是管理后台进行登陆的代码文件,对应GBLab.Web.dll的Login方法


将该GBLab.Web.dll文件放入ILSpy中反编译

在登陆时候传入的username参数以及password参数分别是txtUserName与txtPassword

通读一下方法代码,GetByName的作用大概是进行数据库查询判断有没有这个username,看看有没有过滤'"这些符号吧

Trim函数代码

public string Trim()
{
    return TrimHelper(2);
}

TrimHelper函数代码

private string TrimHelper(int trimType)
{
    int num = Length - 1;
    int i = 0;
    if (trimType != 1)
    {
        for (i = 0; i < Length && (char.IsWhiteSpace(this[i]) || IsBOMWhitespace(this[i])); i++)
        {
        }
    }
    if (trimType != 0)
    {
        num = Length - 1;
        while (num >= i && (char.IsWhiteSpace(this[num]) || IsBOMWhitespace(this[i])))
        {
            num--;
        }
    }
    return CreateTrimmedString(i, num);
}

这些代码并没有修改参数值,当trimType不等零时,进行num自减,它的意思应该是要去掉字符串后方的空白字符以及Bom空白字符,那怎么能过滤恶意的Sql参数呢?

根据GetByname函数,其会进行SQL语句的拼接,后会通过FindAll进行SQL语句的执行

public static T_User GetByName(string username)
{
    EntityList<T_User> entityList = Entity<T_User>.FindAll("select * from T_User where F_Account='" + username.DefaultIsNullOrEmpty("") + "'");
    if (entityList.Count == 0)
    {
        return null;
    }
    return entityList[0];
}

总结一下,GetByName进行SQL语句的查询,将查询的数据赋给byName,但是这个登陆功能点不会直接给我们回复(只有登录成功或失败),就是一个盲注注入点

Burp进行推叠时间盲注测试

admin';WAITFOR DELAY '00:00:10';--/**/

这个功能点测试完了拥有SQL盲注,登陆进去之后会请求/Manage/Index接口,要看这个接口的代码逻辑还是需要寻找路由

在Asp.net程序中,拥有区域路由配置以及全局路由配置,区域路由配置允许为应用程序的不同部分定义独立的路由规则

在Asp.net应用程序中Global.asax文件是Asp.net程序的入口点,通过它可以找到路由配置

全局路由代码,将接口{controller}/{action}/{id}映射到相应的控制器和动作方法

routes.MapRoute("Default", "{controller}/{action}/{id}", new
        {
            controller = "Home",
            action = "Index",
            id = UrlParameter.Optional
        }

在GBLab.Web.dll文件中发现区域路由代码,管理Manage接口

登陆之后的/Manage/Index接口逻辑由GBLab.Web.Areas.Manage.Views.dll中IndexController类的Index方法定义

T_User类两个方法,一个没有引入参数,另一个带入的后端生成的SessionID,Sql注入无了

现在看来T_User对于数据库的操作挺多的,那我们直接就在T_User类中查询select以及where等关键字,通过这种方式看看能不能找出其他Sql注入漏洞

通过select关键字查询出的第一个方法是GetByName方法,这个就是当时登陆时出现的SQL注入方法,这里我把反编译的C#代码保存到一个文件夹下了,使用notepad++全局查询发现在LoginUserController类中也使用了GetByName方法


这个功能点在页面超时时出现

Burp测试一下payload(同上)

继续查询select关键字,看下一个方法

SQL注入——ConfirmName方法

下一组方法是ConfirmName,直接拼接sql语句

全局搜索T_User.ConfirmName,发现两个方法均在Action_Edit_Add方法中调用,只不过一个是添加用户,一个是编辑用户

方法引用的参数只被DefaultIsNullOrEmpty处理了一下

添加用户,Burp截包

可测试后发现这个接口代码编译的有些问题,正常传参都会提示错误

测试编辑用户功能点吧

根据select关键字查询发现下一个方法是ConfirmName_ClassId,但是这个方法没有其他方法的调用

GetItemList方法没有将参数带入sql语句中

接下来两个函数都做了参数类型限制,int类型参数

SQL注入——GetPager方法

然后寻找了Where关键字发现了GetPager函数,该函数接收strWhere,带入了SQL条件

看看谁调用了它吧

在pager定义的类中,strWhere参数是string类型,貌似有戏

修改请求包插入payload,获得sql注入一枚

然后在T_User类中发现了三个update语句,怀疑有Sql注入

还是一样的套路,看看那个方法调用

乖乖,还是这个UserController类

可这个类方法没有获取前端传递的参数,没有其他方法的调用,算是一个废方法

看完了这个类,发现其实T_User.cs这个代码为UserController.cs这个代码类服务,而UserController.cs直接对应前端,构成后端服务接口类,用来处理用户操作

可还有部门操作,角色操作等类,这些类中每个方法的代码逻辑基本上是一样的,例如ConfirmName在每个Controller类都出现了,并且也定义了很多次

每个定义的方法也就改了改表名,该有sql注入的逻辑代码同样在其他方法类中出现

其他Controller类的sql注入原理也是这样,我在这里就不复现了,找找其他漏洞吧

文件上传漏洞

还记得文章初始时显示得目录架构吗?最令我关注得只有一个代码文件!那就是关于文件上传的UploadNewHandler.ashx

代码文件指向JQueryUploadDemo类UploadNewHandler方法

UploadNewHandler方法通过GetFiletypeName定义文件后缀名

从ILSpy中查看一下GetFiletypeName函数,这个方法获取两个参数,第一个参数是HttpPostedFile.FileName获取的文件名,第二个参数.jpg

那就是妥妥的文件上传漏洞,没有任何限制

传个一句话木马

哥斯拉连接成功