Skip to main content
  1. Posts/

MCMS Vulnerable Collection

··467 words·
loading
·
Table of Contents
Vulnerable - This article is part of a series.
Part 8: This Article

Ref
#

MCMS V5.2.4
MCMS V5.2.4 代码审计

Vulnerable
#

SQL_INJECTION
#

注入点 1
#

  • ms-base/net/mingsoft/base/dao/IBaseDao.xml#sqlWhere
    <sql id="sqlWhere" databaseId="mysql">
        <if test="sqlWhereList != null">
        <foreach collection="sqlWhereList" item="item" index="index"
                 open="and( " separator=" " close=" )">

            <if test="item.el == 'eq'">
                <choose>
                    <when test="item.multiple != null and item.multiple == true">
                        FIND_IN_SET(#{item.value}, ${item.field})>0
                    </when>
                    <otherwise>
                        ${item.field} = #{item.value}
                    </otherwise>
                </choose>
            </if>
            <!-- 其他逻辑省略,大量使用了 ${item.field} -->
            <if test="item.el == 'like'">
                ${item.field} like CONCAT(CONCAT('%',#{item.value}),'%')
            </if>
        </foreach>
        </if>
    </sql>

反向寻找接口

  • net.mingsoft.base.entity.BaseEntity#getSqlWhereList
    • net.mingsoft.cms.action.ContentAction#list
@PostMapping("/list")
@ResponseBody
public ResultData list(@ModelAttribute @ApiIgnore ContentBean content, HttpServletResponse response, HttpServletRequest request, @ApiIgnore ModelMap model, BindingResult result) {
        BasicUtil.startPage();
        List contentList = contentBiz.query(content);
        return ResultData.build().success(new EUListBean(contentList,(int) BasicUtil.endPage(contentList).getTotal()));
}

接口毫无校验,用户可通过请求参数直接提交如 sqlWhere=[{"field":"1=1 or sleep(3)","el":"eq","value":"1"}] 的 JSON 数据段,直接造成 SQL 语句拼接注入。(涵盖 net.mingsoft.cms.action.web.ContentAction 等多处 list 注入)

注入点 2
#

  • ms-base/net/mingsoft/base/dao/IBaseDao.xml#queryBySQL
    <!-- mysql根据sql动态查询开始 -->
    <select id="queryBySQL" resultType="Map" databaseId="mysql">
        select *
        from ${table}
        <where>
            1=1
            <foreach item="item" index="key" collection="wheres" open="AND"
                     separator="AND" close=""> ${key} = #{item}
            </foreach>
            <include refid="net.mingsoft.base.dao.IBaseDao.sqlWhere"></include>
        </where>
        <!-- ...... -->
    </select>

反向寻找接口

  • net.mingsoft.base.biz.impl.BaseBizImpl#queryBySQL
    • net.mingsoft.basic.action.BaseAction#validated
      • net.mingsoft.mdiy.action.PageAction#verify
@Api(tags={"自定义页面接口"})
@RequestMapping("/${ms.manager.path}/mdiy/page")
public class PageAction extends BaseAction {
	
	//... 略去其他代码

    @GetMapping("verify")
    @ResponseBody
    public ResultData verify(String fieldName, String fieldValue, String id, String idName){
            boolean verify = false;
            // 漏洞参数直接传递至父类验证逻辑中
            if(StringUtils.isBlank(id)){
                    verify = super.validated("mdiy_page",fieldName,fieldValue);
            }else{
                    verify = super.validated("mdiy_page",fieldName,fieldValue,id,idName);
            }
            if(verify){
                    return ResultData.build().success(false);
            }else {
                    return ResultData.build().success(true);
            }
    }
}
// 父类 BaseAction 中封装了通用字段验证功能:
protected boolean validated(String tableName,String fieldName, String fieldValue) {
        Map where = new HashMap<>(1);
        // fieldName 未过滤作为主键直接赋给查询条件 wheres
        where.put(fieldName, fieldValue);
        List list = appBiz.queryBySQL(tableName, null, where);
        if (ObjectUtil.isNotNull(list) && !list.isEmpty()) {
                return true;
        }
        return false;
}

接口对于用户传入的 fieldName 毫无校验过滤。由外界在 verify 方法传参 fieldName=xx ,接着进入底层由 <foreach> 取为其 map 的 key 然后使用 ${key} 原样拼接,导致在动态查询验证时发生 SQL 注入。

Vulnerable - This article is part of a series.
Part 8: This Article

Related