我的博客地址:http://www.ldsecurity.cn/
1. 未授权访问概念:
有些项目可能存在很多的页面,有些页面开发者在设计的过程中,可能会去判断用户是否登录,如果没有登录就无法访问。
2. 白盒审计未授权的关键点:
判断用户的身份可能会导致后台本身有多个功能文件页面
1、在每个文件里面添加判断代码
2、创建一个文件专门用来判断,其他文件包含调用它
找未授权访问
找那些文件没有包含验证代码文件
2、验证代码文件有没有可以绕过
3. 白盒找 .aspx 未授权点:
1. 首先我们看登录之后的地址:
首先我们进行登录:假设我们知道用户名和密码。
登录之后,我们发现我们的登录页面后,去访问相应的资源的地址是:
http://ip/purchase/pd.aspx(登录之后才能进行访问的地址)
2. idea 打开该项目进行审计:
我们将 pd.aspx 文件的第一行代码提取出来。关注最后一个关键字,之所以要关注
pd.aspx 这个文件是因为你登录之后就是跳转的 pd.aspx ,而这个文件可能就是用来判断当前用户是否处于登录状态。
lnherits 是继承的意思,可以理解为包含,很可能被包含的这个文件就是用来判断用户是否是登录状态。
Inherits="purchase.purchase.pd" %>
<%@ Page Title="" Language="C#" MasterPageFile="~/purchase/purchase.Master" ClientIDMode="Static" AutoEventWireup="true" CodeBehind="pd.aspx.cs" Inherits="purchase.purchase.pd" %>
接下来我们就是需要找是否存在一个 dll 文件叫做 purchase。
1. dll 文件的解释:
在 java 开发中,项目最后都会进行打包,这个包的后缀名是 .jar 结尾,里面封装了核心的代码。通过 .jar 包即可运行 java 项目。而在这个 c# 项目中,.dll 后缀结尾的文件和 .jar 是类似的,里面都是封装了一些核心的代码,只不过这个核心代码是 c# 。
2. purchase.dll 文件:
可以发现,dll 文件内容是二进制形式的。既然是二进制,那么我们就可以去进行反编译了。
3. 反编译 .dll 文件:
1. 在 purchase.dll 中查找 purchase.purchase.pd 文件:
我们根据上面提到的 purchase.purchase.pd 文件,进行相应的查找,注意区分大小写。
purchase.purchase.pd 文件代码:
我们发现,这个代码似乎并没有啥问题,就算你看不懂,也没关系,因为你只需要知道它是不是在进行是否登录成功的验证即可,而下面这个,很显然不是在进行验证。
// purchase.purchase.pd
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class pd : Page
{
protected DropDownList pdtypes;
protected TextBox pdusername;
protected TextBox pddate;
protected TextBox note;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
pddate.Text = DateTime.Now.ToString("yyyy-MM-dd");
}
}
}
那么我们可能是找错 dll 文件了,我们回到最初的 .aspx 文件。
<%@ Page Title="" Language="C#" MasterPageFile="~/purchase/purchase.Master" ClientIDMode="Static" AutoEventWireup="true" CodeBehind="pd.aspx.cs" Inherits="purchase.purchase.pd" %>
我们再来查找是否存在这个文件:/purchase/purchase.Master
查找到是存在这个文件的:
purchase.Master 文件的第一行代码:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="purchase.Master.cs" Inherits="Purchase.Purchase.pur" %>
那么接下来 Purchase.Purchase.pur 就是我们应该考虑要去查找的文件。
2. 在 purchase.dll 文件中查找 Purchase.Purchase.pur 文件:
这里之所以是在 purchase.dll 文件里面进行查找,是因为从名字的前缀就可以知道,该 dll 文件里面对 purchase 目录进行了核心代码的封装。
4. 找到未授权访问点:
Purchase.Purchase.pur 文件代码如下所示:
// Purchase.Purchase.pur
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
public class pur : MasterPage
{
public string apppath = HttpContext.Current.Request.ApplicationPath;
protected HtmlHead Head1;
protected ContentPlaceHolder head;
protected Literal lt_username;
protected Literal lb_username;
protected PlaceHolder ht;
protected PlaceHolder ph1;
protected HtmlForm fm;
protected ScriptManager ScriptManager1;
protected ContentPlaceHolder ContentPlaceHolder1;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
HtmlHead header = Page.Header;
HtmlMeta htmlMeta = new HtmlMeta();
htmlMeta.HttpEquiv = "官方说明";
htmlMeta.Content = "本程序由启明星工作室开发,详见官网 http://www.dotnetcms.org 联系QQ 983506039 ";
header.Controls.AddAt(0, htmlMeta);
Head1.Title = "启明星采购系统-" + Head1.Title;
if (DateTime.Now > DateTime.Parse("2017-1-1"))
{
Helper.Result((Page)(object)Page, "已经到期啦,请到http://www.dotnetcms.org 下载新版 ");
}
if (UserHelper.GetUserId <= 0)
{
base.Response.Redirect("../login.aspx");
return;
}
string text2 = (lb_username.Text = (lt_username.Text = UserHelper.GetUserName));
ph1.Visible = true;
ht.Visible = true;
}
}
public string GetCss(string url)
{
url = apppath + "/purchase/" + url;
if (base.Request.CurrentExecutionFilePath.StartsWith(url, StringComparison.OrdinalIgnoreCase))
{
return "active1";
}
return "";
}
}
我们找到上面的核心代码,我们只需要知道一个点就是,当你进行登录的时候,你会携带一个 UserId 的参数,默认应该是 >0 的,那么如果你能够将这个参数修改为 <= 0的话,那么我们是不是可以进行相应的一些绕过了,然后去访问 login.aspx
if (UserHelper.GetUserId <= 0)
{
base.Response.Redirect("../login.aspx");
return;
}
那么找到漏洞点之后,接下来我们进行的就是漏洞利用了。
4. 未授权利用:
1. 查看 UserHelper.GetUserId 方法:
GetUserId 方法代码:
// UserHelper
using System.Web;
public static int GetUserId
{
get
{
if (Helper.IsUseAd && HttpContext.Current.Request.Cookies["userinfo"] == null)
{
UsersHelper.LoginAd(GetSamaccountName());
}
if (HttpContext.Current.Request.Cookies["userinfo"] != null)
{
return int.Parse(HttpContext.Current.Request.Cookies["userinfo"]["userid"]);
}
return -1;
}
}
核心代码:如果不为空,则会将 userid 转换为 int 类型。
if (HttpContext.Current.Request.Cookies["userinfo"] != null)
{
return int.Parse(HttpContext.Current.Request.Cookies["userinfo"]["userid"]);
}
我们添加一个参数:
cookie:userinfo=userid=1;即可实现登录的绕过。