[代码审计]某国产OA漏洞挖掘

如果觉得该文章有帮助的,麻烦师傅们可以搜索下微信公众号:良月安全。点个关注,感谢师傅们的支持。
这两天比较闲,没有什么项目。于是看看了之前获取到的一个系统的源码,结果一看是.net。我哪会什么.net代码审计啊,本着来都来了的原则,还是打算看看。

工具准备

ILSpy:[icsharpcode/ILSpy: .NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform! (github.com)](https://github.com/icsharpcode/ILSpy)

ILSpy主要用于反编译dll动态链接库。默认安装就好,安装完成后如果没有安装.net框架,工具会给出连接下载默认安装即可。安装完成后打开如下。
在这里插入图片描述

正式审计

首先看下目录。
在这里插入图片描述
是webform架构,那他的路由就是在任意目录下的asxm、aspx、ashx等文件中调用bin目录下的动态链接库。先看下这个系统的一个历史漏洞。

历史漏洞追踪

在这里插入图片描述

看的出来时调用了SalaryAccounting类,我们通过ILSpy反编译bin目录下的KPMIIS.Web.dll,然后进去找到对应的类。
在这里插入图片描述
从pyload中可以看出是调用Calculate方法和staffId参数。直接源码贴下

[WebMethod]
public string Calculate(string SalaryCategory, string StaffBirthDay, string staffId, string Department, string SubOrg, string taxMonthly)
			}
		string message = AccountProcess(SalaryCategory, StaffBirthDay, staffId.TrimEnd(new char[1] { ',' }), strOrganizationCode, SubOrg, taxMonthly);
		sbMessage.Append(message);
	}
	catch (Exception ex)
		protected string AccountProcess(string SalaryCategory, string StaffBirthDay, string staffId, string Department, string SubOrg, string taxMonthly)
{
	try
	{
		StringBuilder sqlStr = new StringBuilder();
		sqlStr.Append("SELECT HR_SalaryFilesHistory.SFH_STAFF_ID FROM dbo.HR_SalaryFilesHistory  WHERE HR_SalaryFilesHistory.SFH_SA_ID != 0 ");
		if (!string.IsNullOrEmpty(SalaryCategory))
		{
			sqlStr.Append($" AND SCO_CATEGORY_ID={SalaryCategory} ");
		}
		if (!string.IsNullOrEmpty(StaffBirthDay))
		{
			sqlStr.Append(string.Format(" AND YEAR(SFH_SALARY_YEARS)=YEAR('{0}') AND MONTH(SFH_SALARY_YEARS)=MONTH('{0}') ", StaffBirthDay + "-01"));
		}
		if (!string.IsNullOrEmpty(staffId))
		{
			sqlStr.Append($" AND SFH_STAFF_ID IN (SELECT tempString FROM F_SplitNew('{staffId}',','))");
		}
		if (!string.IsNullOrEmpty(Department))
		{
			sqlStr.Append($" AND SFH_STAFF_DEPARTMENT_ID IN (SELECT tempString FROM F_SplitNew('{Department}',',')) ");
		}
		if (!string.IsNullOrEmpty(SubOrg))
		{
			sqlStr.Append($" AND SUB_ORG_ID = {SubOrg} ");
		}
		DataSet ds = Gateway.Default.FromCustomSql(sqlStr.ToString()).ToDataSet();
		StringBuilder staffIdFlow = new StringBuilder();
		if (ds.Tables.Count > 0)
		{
			for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
			{
				if (i == ds.Tables[0].Rows.Count - 1)
				{
					staffIdFlow.Append(ds.Tables[0].Rows[i][0]);
				}
				else
				{
					staffIdFlow.Append(string.Concat(ds.Tables[0].Rows[i][0], ","));
				}
			}
		}
		_bllSalaryFilesHistory.Delete(Convert.ToDateTime(StaffBirthDay), Convert.ToInt32(SalaryCategory), staffId, Department, SubOrg);
		ReshuffledAccounting(SalaryCategory, StaffBirthDay, staffId, Department, SubOrg, staffIdFlow.ToString());
		_bllSalaryFilesHistory.Insert(Convert.ToDateTime(StaffBirthDay), Convert.ToInt32(SalaryCategory), 1, staffId, Department, SubOrg, taxMonthly);
		DataTable dtHistory = _bllHrVSalaryFilesHistoryList.GetDataTable(HR_V_SalaryFilesHistoryList._.SCO_CATEGORY_ID == SalaryCategory && HR_V_SalaryFilesHistoryList._.SFH_SALARY_YEAR == DateTime.Parse(StaffBirthDay).Year && HR_V_SalaryFilesHistoryList._.SFH_SALARY_MONTH == DateTime.Parse(StaffBirthDay).Month);
		StringBuilder sbWhere = new StringBuilder();
		if (!string.IsNullOrEmpty(SalaryCategory))
		{
			sbWhere.Append($" and T1.SCO_CATEGORY_ID = {SalaryCategory}");
		}
		if (!string.IsNullOrEmpty(staffId))
		{
			sbWhere.Append($" and SFH_STAFF_ID in ({staffId})");
		}
		if (!string.IsNullOrEmpty(StaffBirthDay))
		{
			sbWhere.Append(string.Format(" and T1.SFH_SALARY_YEARS = '{0}'", new DateTime(Convert.ToDateTime(StaffBirthDay).Year, Convert.ToDateTime(StaffBirthDay).Month, 1).ToString("yyyy-MM-dd")));
		}
		DataTable dtSalaryHistoryTotalTable = Gateway.Default.FromStoredProcedure("HR_P_SalaryHistoryTotalTable").AddInputParameter("@where", DbType.String, sbWhere.ToString()).ToDataSet()
			.Tables[0];
		WhereClip wcMonthly = new WhereClip() && new WhereClip(" 1 = 1 ", null, null, null);
		string wcMonthDate = "";
		if (!string.IsNullOrEmpty(StaffBirthDay))
		{
			wcMonthly = wcMonthly && new WhereClip($" ham.MONTHLY_DATE = '{StaffBirthDay}' ", null, null, null);
			wcMonthDate = StaffBirthDay;
		}
		if (!string.IsNullOrEmpty(staffId))
		{
			wcMonthly = wcMonthly && new WhereClip($" A.STAFF_ID in ({staffId}) ", null, null, null);
		}
		if (!string.IsNullOrEmpty(Department))
		{
			string strOrganizationCode = "";
			strOrganizationCode = new BLLCOMMON_Organization().GetIDsOrganizations(Department);
			if (strOrganizationCode != "")
			{
				wcMonthly = wcMonthly && new WhereClip(string.Format(" A.ORGANIZATION_ID in ({0}) ", string.IsNullOrEmpty(strOrganizationCode) ? "-1" : strOrganizationCode), null, null, null);
			}
		}
		if (!string.IsNullOrEmpty(SubOrg))
		{
			wcMonthly = wcMonthly && new WhereClip(string.Format(" E.SUB_ORG_ID in ({0}) ", string.IsNullOrEmpty(SubOrg) ? "-1" : SubOrg), null, null, null);
		}
		DataTable dtMonthly = _bllHrAttendanceMonthly.GetTable(wcMonthly, new WhereClip($" FLOW_STATE = {3} ", null, null, null), wcMonthDate);

可以看到是通过字符拼接的方式直接拼接参数,进入FromCustomSql执行sql语句,从而导致sql注入。这样的话同理的其他一些参数也可以sql。

sql注入挖掘

那我们知道了这里的sql的执行流程,我们直接全局搜索FromCustomSql,查看是否其他sql语句参数可控且无过滤。因为ILSpy的全局搜索不是很好用,所以这边保存代码导出用vscode打开查看搜索。可以看到有很多。
在这里插入图片描述
这里随便找一两个接口测试一下就结束了。
在这里插入图片描述

文件上传挖掘

依旧是先搜索关键字。
在这里插入图片描述
首先就可以看到存在fckeditor编辑器,编辑器上传这边就不多说了,继续查看其他接口。
后面有陆续找到一些图片、附件上传的接口,发现都存在过滤。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最后发现有一处上传未过滤,具体信息就不透露了。因为本人能力不足实在太菜,只会照葫芦画瓢,大概只能到这种程度了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值