当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2015-092960

漏洞标题:LebiShop商城系统最新版设计缺陷及XSS盲打后台

相关厂商:www.lebi.cn

漏洞作者: xfkxfk

提交时间:2015-01-26 10:04

修复时间:2015-04-26 10:06

公开时间:2015-04-26 10:06

漏洞类型:xss跨站脚本攻击

危害等级:中

自评Rank:10

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-01-26: 细节已通知厂商并且等待厂商处理中
2015-01-26: 厂商已经确认,细节仅向厂商公开
2015-01-29: 细节向第三方安全合作伙伴开放
2015-03-22: 细节向核心白帽子及相关领域专家公开
2015-04-01: 细节向普通白帽子公开
2015-04-11: 细节向实习白帽子公开
2015-04-26: 细节向公众公开

简要描述:

LebiShop商城系统最新版设计缺陷及XSS盲打后台

详细说明:

LebiShop商城系统最新版验证码存在设计缺陷可无视验证码,及存储型XSS盲打后台
验证码设计缺陷:
LebiShop商城系统有两者验证码验证方式
1、直接判断POST提交的验证码已经COOKIE中的验证码是否相等
如前台普通用户登陆时

// Shop.Ajax.Ajax_user
public void User_Login()
{
string verifycode = RequestTool.RequestString("verifycode");
string code = CookieTool.GetCookieString("CheckCodef");
string UserName = RequestTool.RequestSafeString("UserName");
string PWD = RequestTool.RequestSafeString("Password");
if (code != verifycode)
{
base.Response.Write("{\"msg\":\"" + base.Tag("验证码错误") + "\"}");
return;
}


直接判断verifycode和CheckCodef是否相等
这里我们在发送请求时,将POST和COOKIE中的值设置为一样即可绕过
2、判断COOKIE的某值是否为空,然后在进行第1中方式的验证
如后台登陆

// Shop.Admin.Ajax.Ajax_login
public void AdminLogin()
{
string userName = RequestTool.RequestString("userName");
string UserPWD = RequestTool.RequestString("UserPWD");
string code = RequestTool.RequestString("code");
int saveusername = RequestTool.RequestInt("saveusername", 0);
int type = RequestTool.RequestInt("type", 0);
if (CookieTool.GetCookieString("AdminLoginError") != "")
{
string ccode = CookieTool.GetCookieString("CheckCodef");
if (ccode != code)
{
base.Response.Write(Language.Tag("验证码错误", this.CurrentLanguage.Code));
return;
}
}


先判断COOKIE中的AdminLoginError是否为空,在进行code的判断
这里在发送请求时,直接将COOKIE中的AdminLoginError设置为空即可绕过验证码
XSS盲打后台
很多地方都存在盲打后台的地方,全局只进行了<,>,'三个符号的处理
但是在获取X-Forwarded-For时,没有使用全局处理,直接赋值
如在商家用户登陆处

// Shop.Supplier.Ajax.Ajax_user
public void User_Login()
{
string msg = "";
string userName = RequestTool.RequestSafeString("userName");
string UserPWD = RequestTool.RequestSafeString("UserPWD");
string code = RequestTool.RequestString("code");
string logintype = RequestTool.RequestString("logintype", "supplier");
int saveusername = RequestTool.RequestInt("saveusername", 0);
if (CookieTool.GetCookieString("SupplierLoginError") != "")
{
string ccode = CookieTool.GetCookieString("CheckCodef");
if (ccode != code)
{
base.Response.Write(Language.Tag("验证码错误", base.CurrentLanguage.Code));
return;
}
}
if (EX_User.UserLogin(userName, UserPWD, true))
{
this.CurrentUser = EX_User.CurrentUser();
if (EX_Supplier.Login(this.CurrentUser, logintype, 0, out msg))
{
if (saveusername == 1)
{
CookieTool.SetCookieString("SupplierUserName", userName, 1440);
CookieTool.SetCookieString("saveusername", "1", 1440);
}
else
{
CookieTool.SetCookieString("SupplierUserName", "", -1);
CookieTool.SetCookieString("saveusername", "", -1);
}
Log.Add("登陆系统", "Login", this.CurrentUser.id.ToString(), this.CurrentUser.UserName);
msg = "OK";
}
else
{
msg = Language.Tag("账号状态异常", base.CurrentLanguage.Code);
}
}
else
{
msg = Language.Tag("用户名或密码错误", base.CurrentLanguage.Code);
base.Response.Cookies.Add(new HttpCookie("SupplierLoginError", "1"));
Log.Add("登陆系统", "Login", "", this.CurrentUser, "[" + userName + "]用户名或密码错误");
}
base.Response.Write(msg);
}


这里是否登录成功都会有log记录
跟进Log.Add函数

// Shop.Bussiness.Log
public static void Add(string content, string tablename, string keyid, string description)
{
EX_User.CurrentUser();
EX_Admin.CurrentAdmin();
Log.Add(content, tablename, keyid, null, null, null, description);
}


继续跟进

// Shop.Bussiness.Log
public static void Add(string content, string tablename, string keyid, Lebi_User user, Lebi_Administrator admin, Lebi_Supplier supplier, string description)
{
Lebi_Log log = new Lebi_Log();
if (admin != null)
{
log.Admin_id = admin.id;
log.AdminName = admin.UserName;
}
if (user != null)
{
log.User_id = user.id;
log.UserName = user.UserName;
}
if (supplier != null)
{
log.Supplier_id = supplier.id;
log.Supplier_SubName = supplier.SubName;
}
if (keyid.Length > 500)
{
keyid = keyid.Substring(0, 500);
}
log.Content = content;
log.Keyid = keyid;
log.TableName = tablename;
log.URL = RequestTool.GetRequestUrlNonDomain();
log.RefererURL = RequestTool.GetUrlReferrerNonDomain();
if (description.Length > 500)
{
log.Description = description.Substring(0, 500);
}
else
{
log.Description = description;
}
log.IP_Add = RequestTool.GetClientIP();
B_Lebi_Log.Add(log);
}


到最后,注意这里log.IP_Add = RequestTool.GetClientIP();

// Shop.Tools.RequestTool
public static string GetClientIP()
{
string result2;
try
{
string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (result == null || result == string.Empty)
{
result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
if (result == null || result == string.Empty)
{
result = HttpContext.Current.Request.UserHostAddress;
}
result2 = result;
}
catch
{
result2 = "";
}
return result2;
}


这里直接从HTTP_X_FORWARDED_FOR获取了内容,然后进入了log中

漏洞证明:

将X-Forwarded-For设置为:<img src=1 onerror=alert(1)>
然后随便登录

1.png


此时log中已经记录的登陆信息
在后台配置,操作日志中:

2.png


成功跨入后台

修复方案:

严格验证及过滤

版权声明:转载请注明来源 xfkxfk@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2015-01-26 16:51

厂商回复:

漏洞已修复,感谢

最新状态:

暂无


漏洞评价:

评论

  1. 2015-01-26 14:11 | sco4x0 ( 实习白帽子 | Rank:31 漏洞数:13 | O_o)

    x总连刷8弹啊

  2. 2015-01-26 14:51 | xfkxfk 认证白帽子 ( 核心白帽子 | Rank:2179 漏洞数:338 | 呵呵!)

    @sco4x0 这都一个礼拜了,才审核,还没完。。

  3. 2015-01-26 15:11 | 鶆鶈 ( 普通白帽子 | Rank:306 漏洞数:30 )

    不要太犀利,登上乌云,8个提醒,全是你啊,我已经报警了。

  4. 2015-04-30 14:51 | BeenQuiver ( 普通白帽子 | Rank:101 漏洞数:26 | 专注而高效,坚持好的习惯千万不要放弃)

    x得好