### 简要描述: LebiShop商城系统最新版漏洞大礼包,包括任意用户密码修改,密码重置,某接口直接拖库等 ### 详细说明: LebiShop商城系统最新版漏洞大礼包 第一个任意用户密码修改 在修改用户登陆密码和支付密码是都没有验证原始密码 在发送修改密码请求时,只需要遍历COOKIE中的userid即可修改全部用户密码 shop.ajax.ajax_userin文件中的setpassword方法 ``` // Shop.Ajax.Ajax_userin public void SetPassword() { string PWD = RequestTool.RequestString("Password"); PWD = EX_User.MD5(PWD); this.CurrentUser.Password = PWD; B_Lebi_User.Update(this.CurrentUser); base.Response.Write("{\"msg\":\"OK\"}"); } ``` 这里直接接受new password,然后跟进当前登陆用户COOKIE中的userid进行修改 [<img src="https://images.seebug.org/upload/201501/21163107ba2b479a33518b142a5649f7d3775e0b.png" alt="8.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/21163107ba2b479a33518b142a5649f7d3775e0b.png) 第二密码重置 在找回密码处存在缺陷导致可被重置任意用户密码 shop.ajax.ajax_user文件中的User_forgetpwd方法 ``` // Shop.Ajax.Ajax_user public void User_forgetpwd() { string Email_ = RequestTool.RequestString("Email"); string code = CookieTool.GetCookieString("CheckCodef"); string...
### 简要描述: LebiShop商城系统最新版漏洞大礼包,包括任意用户密码修改,密码重置,某接口直接拖库等 ### 详细说明: LebiShop商城系统最新版漏洞大礼包 第一个任意用户密码修改 在修改用户登陆密码和支付密码是都没有验证原始密码 在发送修改密码请求时,只需要遍历COOKIE中的userid即可修改全部用户密码 shop.ajax.ajax_userin文件中的setpassword方法 ``` // Shop.Ajax.Ajax_userin public void SetPassword() { string PWD = RequestTool.RequestString("Password"); PWD = EX_User.MD5(PWD); this.CurrentUser.Password = PWD; B_Lebi_User.Update(this.CurrentUser); base.Response.Write("{\"msg\":\"OK\"}"); } ``` 这里直接接受new password,然后跟进当前登陆用户COOKIE中的userid进行修改 [<img src="https://images.seebug.org/upload/201501/21163107ba2b479a33518b142a5649f7d3775e0b.png" alt="8.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/21163107ba2b479a33518b142a5649f7d3775e0b.png) 第二密码重置 在找回密码处存在缺陷导致可被重置任意用户密码 shop.ajax.ajax_user文件中的User_forgetpwd方法 ``` // Shop.Ajax.Ajax_user public void User_forgetpwd() { string Email_ = RequestTool.RequestString("Email"); string code = CookieTool.GetCookieString("CheckCodef"); string verifycode = RequestTool.RequestString("verifycode"); if (code != verifycode) { base.Response.Write("{\"msg\":\"" + base.Tag("验证码错误") + "\"}"); return; } Lebi_User user = B_Lebi_User.GetModel("Email='" + Email_ + "'"); if (user == null) { base.Response.Write("{\"msg\":\"" + base.Tag("用户不存在") + "\"}"); return; } try { Email.SendEmail_forgetpwd(user, base.CurrentTheme); if (ShopCache.GetBaseConfig().SMS_sendmode.Contains("SMSTPL_getpwd")) { SMS.SendSMS_forgetpwd(user); } } catch (Exception ex) { base.Response.Write("{\"msg\":\"" + ex.Message + "\"}"); } base.Response.Write("{\"msg\":\"OK\"}"); } ``` 跟进Email.SendEmail_forgetpwd方法 ``` // Shop.Bussiness.Email public static void SendEmail_forgetpwd(Lebi_User user, Lebi_Theme CurrentTheme) { Lebi_Language lang = B_Lebi_Language.GetModel("Code='" + user.Language + "'"); BaseConfig conf = ShopCache.GetBaseConfig(); user.CheckCode = EX_User.MD5(DateTime.Now.ToString()); B_Lebi_User.Update(user); string url = string.Concat(new object[] { "http://", RequestTool.GetRequestDomain(), ThemeUrl.GetURL("P_FindPassword", "", "", lang), "?id=", user.id, "&email=", user.Email, "&v=", user.CheckCode }); string title = Language.Content(conf.EmailTPL_getpwd_title, user.Language); string content = Language.Content(conf.EmailTPL_getpwd, user.Language); title = Email.ReplaceEmailTag(title, user, conf); content = Email.ReplaceEmailTag(content, user, conf); content = content.Replace("{$UserPWDURL}", url); bool flag = Email.Send(user.Email, title, content); Email.EmailJob(user.Email, title, content, flag, user, conf); } ``` 这里通过email发送邮件,关键是这里的验证code user.CheckCode = EX_User.MD5(DateTime.Now.ToString()); CheckCode 只是通过当前时间戳进行md5然后发送重置密码邮件如下: ``` http://plus.demo.lebi.cn/FindPassword.aspx?id=37&email=2754371317@qq.com&v=207ade4af42016cafd61543e308afae0 ``` 最后通过对比userid的用不的CheckCode 是否等于接收到的这个url中的CheckCode 简单的时间戳很容易被绕过,而且这里没有验证发送一次后就情况前面发送的CheckCode ,所以我们可以短时间内发送过个重置密码邮件,比如: 我们在2秒钟内发送多个重置密码请求,然后我们在遍历处2秒钟内的时间戳并md5 然后遍历md5后的字符串构造重置密码请求即可 第三某接口可之直接拖库 来看看代码 shop.api.api文件中的GetUsers方法 ``` // Shop.api.api public void GetUsers() { int id = RequestTool.RequestInt("user_id", 0); int size = RequestTool.RequestInt("size", 1); size = ((size < 0) ? 0 : size); size = ((size > 50) ? 50 : size); List<Lebi_User> users = B_Lebi_User.GetList("id>=" + id, "id asc", size, 1); List<apiUser> models = new List<apiUser>(); foreach (Lebi_User user in users) { models.Add(new apiUser { Address = user.Address, Password = user.Password, Area = EX_Area.GetAreaName(user.Area_id, 4), Birthday = user.Birthday, CashAccount_Bank = user.CashAccount_Bank, CashAccount_Code = user.CashAccount_Code, CashAccount_Name = user.CashAccount_Name, City = user.City, Count_Login = user.Count_Login, Currency_Code = user.Currency_Code, Email = user.Email, Face = user.Face, Fax = user.Fax, id = user.id, Introduce = user.Introduce, IP_Last = user.IP_Last, IP_This = user.IP_This, Language = user.Language, MobilePhone = user.MobilePhone, Money = user.Money, Money_xiaofei = user.Money_xiaofei, Msn = user.Msn, NickName = user.NickName, Phone = user.Phone, Point = user.Point, Postalcode = user.Postalcode, QQ = user.QQ, RealName = user.RealName, Sex = user.Sex, Time_Last = user.Time_Last, Time_lastorder = user.Time_lastorder, Time_Reg = user.Time_Reg, Time_This = user.Time_This, UserName = user.UserName }); } JavaScriptSerializer jss = new JavaScriptSerializer(); string json = jss.Serialize(models); json = jss.Serialize(new LBAPI { data = json, msg = "OK" }); base.Response.Write(json); } ``` 这里通过user_id的个数和size参数的大小,遍历出了用户,包括具体信息如代码中的属性信息 但是这里有一个接口密码apipwd ``` // Shop.api.api protected void Page_Load(object sender, EventArgs e) { string apipwd = RequestTool.RequestString("apipwd"); if (apipwd != ShopCache.GetBaseConfig().APIPassWord) { base.Response.Write("{\"msg\":\"验证失败\"}"); return; } string action = RequestTool.RequestString("action"); Type type = base.GetType(); MethodInfo methodInfo = type.GetMethod(action); if (methodInfo != null) { methodInfo.Invoke(this, null); } } ``` 当请求中的apipwd等于系统中设置的api密码时,即可通过此接口获取全部用户信息 在系统中apipwd是这样获取的: ``` ShopCache.GetBaseConfig().APIPassWord model.APIPassWord = ((ht["APIPassWord"] == null) ? "" : ((string)ht["APIPassWord"])); ``` 当默认系统中没有设置APIPassWord时则为空 重要的是此系统默认安装就没有设置APIPassWord,即APIPassWord为空 后台配置,基本设置中 [<img src="https://images.seebug.org/upload/201501/21162805ad589740bed1c64f9ff59b0b3af235cc.png" alt="6.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/21162805ad589740bed1c64f9ff59b0b3af235cc.png) 此时我们提交的请求中可设置apipwd=空即可 如下请求即可获取用户信息 [<img src="https://images.seebug.org/upload/201501/2116264158ccb49c9d5988c91397eae66dbfb66b.png" alt="5.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/2116264158ccb49c9d5988c91397eae66dbfb66b.png) 同理还能获取系统全部订单信息,shop.api.api文件中的GetOrders方法 [<img src="https://images.seebug.org/upload/201501/21162933a838efb3ab734615857611eb860b4190.png" alt="7.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/21162933a838efb3ab734615857611eb860b4190.png) ### 漏洞证明: [<img src="https://images.seebug.org/upload/201501/211629422ffe96bd0fa295c92f7795186eccc6c9.png" alt="5.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/211629422ffe96bd0fa295c92f7795186eccc6c9.png)