V5.6.3.152.186 20240811之前
某通电子文档安全管理系统是一款综合性的数据智能安全产品,涵盖了透明加密、数据分类分级、访问控制等多项核心技术。该系统保护范围广泛,包括终端电脑、智能终端以及各类应用系统,能有效防止数据泄露,满足数据安全合规要求。该系统采用事前主动防御、事中实时控制、事后及时追踪的设计理念,全方位保障用户终端数据安全。
首先进入WEB-INF的web.xml页面中,Fn+F搜索CDGAuthoriseTempletService1
Ctrl点击键入该类中,该类位于com/esafenet/servlet/service/document/CDGAuthoriseTempletService1.class中,这个是一个servlet文件,找到与前端交互的方法即service方法
对该代码分析如下
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
ServiceUtil.XMLInit(this.xStream);//调用一个工具类,用于初始化初始化xstream对象,用于XML序列化和反序列化
CDGAuthoriseTemplet caTempl \= new CDGAuthoriseTemplet();//可能是一个数据访问对象(DAO)
String toServerXML \= ServiceUtil.getXMLFromRequest(request);//获取请求中的xml字符串
GetCDGAuthoriseTemplet gcat \= (GetCDGAuthoriseTemplet)this.xStream.fromXML(toServerXML);//将XML字符串反序列化为GetCDGAuthoriseTemplet类型的对象gcat
boolean flag \= this.validateInfo(gcat);//对反序列化的内容进行校验
if (!flag) {//校验结果为false,直接进行gcat序列化为xml发送响应
ServiceUtil.sendInfo(request, response, this.xStream.toXML(gcat));
} else {
CDGAuthoriseTempletModel model \= new CDGAuthoriseTempletModel();
try {
caTempl \= model.getAuthoriseTempletList(caTempl, gcat.getUserId(), gcat.getSecretLevelId());//取授权模板列表
ServiceUtil.sendInfo(request, response, this.xStream.toXML(caTempl));//将结果(即caTempl对象)的XML表示发送给客户端。
} catch (Exception var9) {
Exception e \= var9;
e.printStackTrace();
gcat.setReturnMessage("error099");
ServiceUtil.sendInfo(request, response, this.xStream.toXML(gcat));
}
}
}
分析:上述代码就是接受前端的请求数据,数据类型为xml,将其进行xml反序列之后进行校验,进行校验成功之后调用getAuthoriseTempletList方法,之后将内容进行序列化返回给前端
我们先分析一下这个校验即this.validateInfo(gcat);
private boolean validateInfo(GetCDGAuthoriseTemplet gcat) {
String userId \= gcat.getUserId();
String secretLevelId \= gcat.getSecretLevelId();
if (userId != null && !"".equals(userId)) {
if (secretLevelId != null && !"".equals(secretLevelId)) {
try {
User localUser \= this.userDao.findUserById(userId);
if (localUser \== null) {
gcat.setReturnMessage("error007");
return false;
} else {
return true;
}
} catch (Exception var5) {
gcat.setReturnMessage("error104");
return false;
}
} else {
gcat.setReturnMessage("error112");
return false;
}
} else {
gcat.setReturnMessage("error101");
return false;
}
}
}
上述代码就是先判断序列化之后的内容中userId以及secretLevelId是否为空,不为空则进行findUserById操作,Ctrl点击跟进该方法
分析:绿框中的内容对userid的内容转换为小写,尝试从缓存(usermap)中获取用户信息,找到将结果返回
蓝框中的内容就是去数据库中查找是否有该userId,若有则将结果返回
分析完这个校验之后,接着进入到校验成功之后else语句中即如图代码中
分析:调用了model.getAuthoriseTempletList方法进行模板列表的更新,之后进行序列化并将结果返回给前端
Ctrl点击进入到getAuthoriseTempletList方法中
它又调用了List<AuthoriseTemplet>下的getAuthoriseTempletList方法,我们继续跟进
分析:调用 this.getAuthoriseTempletList(userId, secretLevelId) 方法来获取与指定用户和密级相关的 CDGAuthoriseTempletInfo 对象列表其中包含包括名称(name)、描述(description)、密级(secretLevel)、创建日期(createDate)。然后创建一个空的 ArrayList 类型的 authoriseTempletList,用于存储转换后的 AuthoriseTemplet 对象,将获取到的对象列表中的内容给到AuthoriseTemplet 对象之后返回这个对象
我们进入到getAuthoriseTempletList方法中查看它是如何获取对象列表的
分析:该方法就是判断我们传递的userId、 secretLevelId是否为空,若不为空就将其拼接到sql语句中(猜测这就是sql注入漏洞形成的原因),之后调用dao.getAuthoriseTempletList(sqls.toString())将其结果返回
进入到List<CDGAuthoriseTempletInfo>下的getAuthoriseTempletList方法中,这里见我们转入的参数进行了sql语句的拼接后,调用了dao.getAuthoriseTempletList方法,这里有多个地方声明了该方法我们选择的是第一个
分析:该方法会将我们传入的参数直接拼接到sql语句中即(sql.append(condtion)),之后进行调用getCommonResults(sql.toString())方法执行sql语句的查询(并且没有任何过滤)并将结果赋值给maps,之后就是判断maps是否为空,将maps中的内容赋值给list,返回list。
经过以上分析我们已经确定了该漏洞的成因,
CDGAuthoriseTempletModel下的getAuthoriseTempletList方法--->List<AuthoriseTemplet>下的 getAuthoriseTempletList方法,其中的参数就是我们可以控制的由前端传过来UserId和SecretLevelIdList<AuthoriseTemplet>下的 getAuthoriseTempletList方法-->List<CDGAuthoriseTempletInfo>下的getAuthoriseTempletList方法,通过sqls.append将我们可以控制的参数进行sql语句的拼接List<CDGAuthoriseTempletInfo>下的getAuthoriseTempletList方法-->dao.getAuthoriseTempletList(sqls.toString())只进行getCommonResults进而执行sql语句并将结果返回因此只要我们在前端传入的参数UserId是缓存中的内容或者是数据库中的存在的值进而绕过validateInfo的if校验,进入到else语句中,之后SecretLevelId传入我们恶意的sql语句,进入getAuthoriseTempletList方法中进行sql语句的执行,这样从而将我们想要的数据以xml的格式返回到响应中
电子文档安全管理系统(CDG)
然后用加解密工具去加密
https://github.com/wafinfo/DecryptTools
发送 POC 可直接获取到管理员账户密码。
POST /CDGServer3/CDGAuthoriseTempletService1 HTTP/1.1
Host:
Cache-Control: max-age=0
Sec-Ch-Ua: "Not:A-Brand";v="99", "Chromium";v="112"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/112.0.5615.138 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,\*
/\*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/xml
Content-Length: 510
加密数据
最后将返回的结果进行解密,可看到账户密码信息