### 0x01 漏洞概述 相关厂商: live800.com 漏洞时间: 2015-10-18 loginAction.jsp SQL注射漏洞,可看客户与客服对话内容,泄露大量敏感信息。 ### 0x02 漏洞细节 在loginAction.jsp中发现以下内容: ``` String loginName=request.getParameter("loginName"); String password=request.getParameter("password"); String loginServerUrl = request.getParameter("loginServerUrl"); OperatorInfo operatorInfo=new OperatorInfo(); operatorInfo.setLoginName(loginName); password = URLUtil.unEscapeHtml(password); operatorInfo.setPassword(password); operatorInfo.setLoginServerUrl(loginServerUrl); int result=DBManager.validateLogin(request.getParameter("companyLoginName"),operatorInfo);//跟踪此方法 if(DBError.NO_EXCEPTION==result&&operatorInfo.validateLogin()&&!StringUtils.isNullOrLengthZero(operatorInfo.getId())) ``` 跟踪用于登录的DBManager.validateLogin()方法,代码做了混淆看着有点吃力: ``` public static int validateLogin(String paramString, OperatorInfo paramOperatorInfo) { if (paramOperatorInfo == null) { return 17; } String str1 = paramOperatorInfo.getPassword(); if...
### 0x01 漏洞概述 相关厂商: live800.com 漏洞时间: 2015-10-18 loginAction.jsp SQL注射漏洞,可看客户与客服对话内容,泄露大量敏感信息。 ### 0x02 漏洞细节 在loginAction.jsp中发现以下内容: ``` String loginName=request.getParameter("loginName"); String password=request.getParameter("password"); String loginServerUrl = request.getParameter("loginServerUrl"); OperatorInfo operatorInfo=new OperatorInfo(); operatorInfo.setLoginName(loginName); password = URLUtil.unEscapeHtml(password); operatorInfo.setPassword(password); operatorInfo.setLoginServerUrl(loginServerUrl); int result=DBManager.validateLogin(request.getParameter("companyLoginName"),operatorInfo);//跟踪此方法 if(DBError.NO_EXCEPTION==result&&operatorInfo.validateLogin()&&!StringUtils.isNullOrLengthZero(operatorInfo.getId())) ``` 跟踪用于登录的DBManager.validateLogin()方法,代码做了混淆看着有点吃力: ``` public static int validateLogin(String paramString, OperatorInfo paramOperatorInfo) { if (paramOperatorInfo == null) { return 17; } String str1 = paramOperatorInfo.getPassword(); if (StringUtils.isNullOrLengthZero(new String[] { str1, paramString })) { return 17; } paramOperatorInfo.setPassword(Password.getEncodingPassword(str1)); String str2 = ak.i(paramString);//跟踪此方法 if (StringUtils.isNullOrLengthZero(str2)) { return 17; } paramOperatorInfo.setCompanyId(str2); return OperatorDBM.validateLogin(paramOperatorInfo); } ``` 再跟踪 ak.i()方法: ``` public static String i(String paramString) { StringBuffer localStringBuffer = new StringBuffer(); localStringBuffer .append("select company_id from company where company_login_name='"); localStringBuffer.append(paramString); localStringBuffer.append("' and user_type!='"); localStringBuffer.append("U"); localStringBuffer.append("'"); return DBCommuter.getAnAttribute(localStringBuffer.toString()); } ``` 在这里看到SQL语句是由参数拼接而成的,最后跟踪DBCommuter.getAnAttribute(localStringBuffer.toString())看看SQL是怎么执行的: ``` public static final String getAnAttribute(String paramString) { if (paramString == null) { return null; } String str = null; Connection localConnection = null; Statement localStatement = null; ResultSet localResultSet = null; if (Live800Define.isOracle) paramString = MysqlToOracle.dividePage(paramString); try { localConnection = a(); localStatement = localConnection.createStatement(); localResultSet = localStatement.executeQuery(paramString); if (localResultSet.next()) { str = localResultSet.getString(1); } a(localStatement.getWarnings(), paramString); a(localResultSet.getWarnings(), paramString); localResultSet.close(); localResultSet = null; localStatement.close(); localStatement = null; localConnection.close(); localConnection = null; } catch (SQLException localSQLException1) { localSQLException1.printStackTrace(); if (a.isWarnEnabled()) { a.logWarn(paramString, localSQLException1); } } finally { if (localResultSet != null) { try { localResultSet.close(); } catch (SQLException localSQLException2) { a.logFatal("close rs error!", localSQLException2); } localResultSet = null; } if (localStatement != null) { try { localStatement.close(); } catch (SQLException localSQLException3) { a.logFatal("close stmt error!", localSQLException3); } localStatement = null; } if (localConnection != null) { try { localConnection.close(); } catch (SQLException localSQLException4) { a.logFatal("close connect error!", localSQLException4); } localConnection = null; } } return str; } ``` 从以上的代码不难看出程序未进行参数化查询导致SQL注入漏洞发生。 还是以华为作为测试用例,访问以下地址登录: http://robotim.vmall.com/live800/login.jsp?aaa=1 抓取数据包:  其中的companyLoginName存在SQL注入: http://robotim.vmall.com/live800/loginAction.jsp?companyLoginName=1%27or(select%20sleep(2))%23&loginName=a111&password=111 可以看到页面成功延迟2s,用SQLMAP跑出账户密码:  成功登录后台:  在后台有个对话记录查询功能:  直接导出详细记录即可查看对话记录:  ### 0x03 修复方案 做一个filter全局过滤SQL注入危险字符